编写测试#

本节包含一系列关于在 conda 仓库中编写测试的指南和准则。


指南#

集成测试 本指南概述了如何使用完整的命令调用编写集成测试。它还介绍了创建供此类测试使用的夹具。


一般准则#

注意

需要注意的是,现有测试可能会偏离这些准则,这没关系。这些准则是为了告知我们希望所有新测试的外观和功能。

首选测试样式 (pytest)#

虽然我们的代码库包含基于类的 unittest 测试,但我们对所有新测试的首选格式是 pytest 样式测试。这些测试是使用函数编写的,并使用夹具处理测试上下文的设置和拆卸。我们建议您先熟悉 pytest,然后再尝试为 conda 编写测试。前往他们的 入门指南 了解更多信息。

组织测试#

测试应以反映主要 conda 模块的方式进行组织。例如,如果您要为 conda/base/context.py 中的函数编写测试,则应将此测试放在 tests/base/test_context.py 中。

"conda.testing" 模块#

这是一个包含任何可能有助于编写测试的内容的模块,包括夹具、函数和类。您可以根据需要随意对此模块进行添加,但请注意组织。例如,如果您的测试实用程序主要仅适用于 base 模块,请考虑将它们存储在 conda.testing.base 中。

添加新夹具#

对于范围或目的非常有限的夹具,可以在测试本身旁边定义它们。但是,如果这些夹具可以在多个测试中使用,则应将它们保存在单独的 fixtures.py 文件中。 conda.testing 模块已经包含几个此类文件。

如果您想在新的文件中添加新夹具,请确保在 tests/conftest.py::pytest_plugins 中添加对该模块的引用。这是我们向测试提供夹具的首选方法。由于这些是在环境中包含的方式,您应该注意命名方案并选择可能不会相互冲突的命名方案。考虑使用前缀来实现这一点。

上下文对象#

conda 中的上下文对象用作单例。这意味着每次运行 conda 命令时,只实例化一个对象。这是有道理的,因为它包含程序的所有配置,重新实例化它或创建多个副本效率低下。

这在测试中会导致问题,在测试中您可能希望在同一个进程中运行数百次 conda 命令。因此,在编写测试时,始终将此对象重置为全新状态非常重要。

这可以通过使用 reset_context 函数来完成,该函数也位于 conda.base.context 模块中。以下示例显示了如何修改上下文对象,然后使用 reset_conda_context pytest 夹具重置它

import os
import tempfile

from conda.base.context import reset_context, context
from conda.testing.fixtures import reset_conda_context

TEST_CONDARC = """
channels:
  - test-channel
"""


def test_that_uses_context(reset_conda_context):
    # We first created a temporary file to hold our test configuration
    with tempfile.TemporaryDirectory() as tempdir:
        condarc_file = os.path.join(tempdir, "condarc")

        with open(condarc_file, "w") as tmp_file:
            tmp_file.write(TEST_CONDARC)

        # We use the reset_context function to load our new configuration
        reset_context(search_path=(condarc_file,))

        # Run various test assertions, below is an example
        assert "test-channel" in context.channels

使用此测试夹具可确保将上下文对象恢复到测试之前的状态。对于此特定测试,这意味着 channels 设置将恢复为其默认配置。如果您需要在测试期间手动重置上下文,则可以通过手动调用 reset_context 命令来完成,如下面的示例所示

from conda.base.context import reset_context


def test_updating_context_manually():
    # Load some custom variables into context here like above...

    reset_context()

    # Continue testing with a fresh context...