编写测试#
本节包含一系列关于在 conda
仓库中编写测试的指南和准则。
指南#
集成测试 本指南概述了如何使用完整的命令调用编写集成测试。它还涵盖了创建 fixture 以用于这些类型的测试。
通用准则#
注意
应该注意的是,现有的测试可能偏离这些准则,这没关系。这些准则旨在说明我们希望所有新测试的外观和功能。
首选测试风格 (pytest)#
尽管我们的代码库包含基于类的 unittest
测试,但我们所有新测试的首选格式是 pytest
风格的测试。这些测试使用函数编写,并使用 fixture 处理测试上下文的设置和拆卸。我们建议您先熟悉 pytest
,然后再尝试为 conda
编写测试。前往他们的 入门指南 了解更多信息。
组织测试#
测试的组织方式应镜像主 conda
模块。例如,如果您要为 conda/base/context.py
中的函数编写测试,则应将此测试放在 tests/base/test_context.py
中。
“conda.testing”模块#
这是一个模块,其中包含任何可能有助于编写测试的内容,包括 fixture、函数和类。请随意向此模块添加内容,但请注意组织。例如,如果您的测试实用程序主要仅用于 base
模块,请考虑将它们存储在 conda.testing.base
中。
添加新的 fixture#
对于范围或目的非常有限的 fixture,可以与测试本身一起定义它们。但是,如果这些 fixture 可以跨多个测试使用,则应将它们保存在单独的 fixtures.py
文件中。conda.testing
模块已经包含其中几个文件。
如果您想在新文件中添加新的 fixture,请务必在 tests/conftest.py::pytest_plugins
中添加对此模块的引用。这是我们将 fixture 提供给测试的首选方式。由于它们包含在环境中的方式,您应该注意命名方案,并选择不太可能相互冲突的方案。考虑使用前缀来实现此目的。
上下文对象#
conda
中的上下文对象用作单例。这意味着每次 conda
命令运行时,只会实例化一个对象。这是有道理的,因为它保存了程序的所有配置,重新实例化它或制作多个副本将是低效的。
这在测试期间会导致问题,您可能希望在同一进程中运行 conda
命令数百次。因此,在编写测试时,务必始终将此对象重置为全新状态。
这可以通过使用 reset_context
函数来实现,该函数也位于 conda.base.context
模块中。以下示例显示了如何修改上下文对象,然后使用 reset_conda_context
pytest
fixture 重置它
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
使用此测试 fixture 确保您的上下文对象返回到测试之前的状态。对于此特定测试,这意味着 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...