跳转到主要内容

pytest的轻松测试发现/组织

项目描述

PyPI - Package Version PyPI - Python Version PyPI - License CircleCI Codecov

pytest-relaxed

pytest-relaxed 为pytest提供“轻松”的测试发现。

它是 https://pypi.python.org/pypi/spec 的精神继承者,但是为 pytest 而非 nosetests 构建的,并重新思考了设计的一些方面(例如增加对各种行为的自愿选择能力。)

有关开发路线图,请参阅维护者的 路线图页面

理由

是否曾经觉得我们把测试放在 tests/ 中,然后命名文件为 test_foo.py,命名测试类为 TestFoo,最后命名测试方法为 test_foo_bar,这很奇怪?特别是在几乎所有的 tests/ 里面的代码都是测试的情况下?

此pytest插件借鉴了Python的其他部分,其中您不需要显式注明公共模块/类成员,而只需要暗示哪些是私有的。默认情况下,pytest被告知要扫描的所有文件和对象都将被视为测试;要标记某物不是测试,只需在其前加上下划线。

轻松发现

默认情况下,除非文件名下划线开头,否则使用“it’s a test”方法适用于文件。

tests
    ├── _util.py
    ├── one_module.py
    └── another_module.py

它应用于模块成员。

def _helper():
    pass

def one_thing():
    assert True

def another_thing():
    assert False

def yet_another():
    assert _helper() == 'something'

以及类成员。

class SomeObject:
    def behavior_one(self):
        assert True

    def another_behavior(self):
        assert False

    def _helper(self):
        pass

    def it_does_things(self):
        assert self._helper() == 'whatever'

特殊案例

正如您所预料的,还有一些特殊案例围绕发现来避免混淆常见的测试扩展。

  • 名为 conftest.py 的文件不被视为测试,因为它们执行特殊的 pytest 功能;

  • 名为 setup_(module|class|method|function) 的模块和类成员不被视为测试,因为这是 pytest 实现经典/xunit 风格的设置和清理方式;

  • @pytest.fixture 装饰的 fixtures 对象当然也会被跳过。

向后兼容性

如果您喜欢 pytest-relaxed 的想法,但拥有大量的测试套件,一次性“升级”所有内容可能会令人生畏。实现一个“混合”测试套件相对简单,其中您的遗留测试仍然正常运行(只要它们已经是 pytest 兼容的,大多数 unittest 套件都符合这一条件),而“relaxed”风格的测试也能按预期工作。

  • 您唯一需要做的更改是重命名“辅助”文件(任何不以 test_ 开头的文件),使它们的名称以下划线开头;然后当然要搜索并替换此类文件的任何导入。

  • pytest-relaxed 明确绕过了所有看似“经典”测试文件(即以 test_* 命名的文件),允许 pytest 的原生收集生效。此类文件无需任何修改。

  • 我们的报告器(显示)功能仍然可以很好地与遗留风格测试一起工作;测试前缀和后缀在显示时会被移除,因此 TestMyThing.test_something 仍然会显示为如果它是按照 relaxed 风格编写的:MyThing 嵌套 something

    • 然而,因为我们没有 收集 这样的测试,直到您将文件重命名为不以 test_ 开头,并更改任何类以便它们不继承自 unittest.TestCase 或类似类,我们提供的嵌套和其他功能都不会工作。

嵌套类组织

在 relaxed 发现算法的基础上,pytest-relaxed 还允许您以嵌套方式组织测试,就像 spec nose 插件或受其启发的工具(如 Ruby 的 rspec)一样。

这是一个纯选择性的功能,但我们发现它是在文件数量过多或测试命名空间过大(使得难以看到哪些功能区域受到了影响)之间的一个很好的折中方案。

该功能可以通过使用嵌套/内部类启用,如下所示

class SomeObject:
    def basic_behavior(self):
        assert True

    class init:
        "__init__"

        def no_args_required(self):
            assert True

        def accepts_some_arg(self):
            assert True

        def sets_up_config(self):
            assert False

    class some_method:
        def accepts_whatever_params(self):
            assert False

        def base_behavior(self):
            assert True

        class when_config_says_foo:
            def it_behaves_like_this(self):
                assert False

        class when_config_says_bar:
            def it_behaves_like_this(self):
                assert True

这些内部类的测试发现是递归的,因此您可以像喜欢一样嵌套它们。当然,就像所有 Python 代码一样,有时候好事可能过多……但这取决于您。

嵌套类属性

如果您正在通过嵌套类对测试进行命名空间划分,您可能希望引用包含它们的“外部”类“范围”,例如类属性。pytest-relaxed 在测试收集阶段自动将这些属性复制到内部类,允许您编写如下代码

class Outer:
    behavior_one = True

    def outer_test(self):
        assert self.behavior_one

    class Inner:
        behavior_two = True

        def inner_test(self):
            assert self.behavior_one and self.behavior_two

值得注意的是

  • 行为是无限嵌套的,正如您所预料的;

  • 看起来像是测试类或方法的属性不会被复制(尽管其他属性,例如以下划线开头的属性,会被复制);

  • 只有那些不在内部类中已存在的属性会被复制;因此内部类可以自然地“覆盖”属性,就像类继承一样。

其他测试辅助工具

pytest-relaxed 提供了一些其他随机的轻量级测试相关实用工具,它们不值得在 PyPI 上单独列出(大多数来自 spec),例如:

  • trap,一个用于测试函数和/或测试助手/子例程的装饰器,类似于 pytest 自己的 capsys/capfd 修复程序,因为它允许捕获 stdout/err。

    • 它提供了一种稍微简单的 API:它用 IO 对象替换了 sys.(stdout|stderr),这些对象可以根据需要调用 getvalue()

    • 更重要的是,它可以包装任意的可调用对象,这对于不易适应 fixture 设计的代码共享用例很有用。

  • raises,它是 pytest.raises 的包装器,作为一个装饰器使用,类似于同名的 Nose 测试工具。

嵌套输出显示

在“移植 spec / 受 RSpec 和同类启发”的精神下,pytest-relaxed 极大地增强了 pytest 的详细显示模式

  • 测试以嵌套、树状的方式显示,为模块、类(包括嵌套类)等显示“标题”行。

  • 因此,每个测试结果的行只包含测试名称,并根据成功/失败/跳过进行着色(类似于内置的详细模式)。

  • 标题和测试名称经过调整,以便更易于阅读,例如用空格替换下划线。

spec 不同,此功能根本不影响正常/非详细输出,并且可以完全禁用,允许您使用轻松的测试发现功能与正常的 pytest 详细显示或您喜欢的 pytest 输出插件(如 pytest-sugar)一起使用。

安装 & 使用

与大多数 pytest 插件一样,这很简单

  • pip install pytest-relaxed;

  • 通过 testpaths 选项告诉 pytest 您的测试所在位置;否则,pytest-relaxed 会导致 pytest 将您的所有非测试代码都加载为测试!

  • 不是必需的,但强烈建议:配置 pytest 的默认文件名模式(python_files)为一个无限定通配符(*)。

    • 这不会影响(我们的)测试发现,但 pytest 的断言“重写”(在错误显示期间将 assert var == othervar 转换为 assert 17 == 2 的功能)在确定要处理的文件时重复使用此设置。

  • 因此,推荐的 setup.cfg(或 pytest.ini,不带标题)是

    [tool:pytest]
    testpaths = tests
    python_files = *
  • 编写一些测试,如上例所示;

  • 运行测试的 pytest,您就完成了!

项目详情


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于 安装包 的信息。

源分布

pytest-relaxed-2.0.2.tar.gz (27.9 kB 查看散列)

上传于

构建分发版

pytest_relaxed-2.0.2-py3-none-any.whl (15.8 kB 查看哈希值)

上传于 Python 3

由以下支持