繁体   English   中英

如何在pytest中测试类层次结构?

[英]How to test a class hierarchy in pytest?

我已经使用了pytest一段时间,并学会了喜欢参数化和固定装置。 我第一次想要测试一些具有分支继承结构的类。 当然,我想重用子类的测试用例。 说我有以下包结构:

mock
├── pkg
│   ├── child.py
│   ├── grandchild.py
│   └── parent.py
└── tests
    ├── test_child.py
    ├── test_grandchild.py
    └── test_parent.py

正如在这个SO问题中所概述的,我可以使用fixture来提供被测试类的实例。 但是,当我从另一个测试模块导入测试类时,它(a)感觉它不是pytest方式,(b)pytest将运行导入类的所有测试方法,并再次作为继承测试类的一部分运行它们。 例如,文件test_child.py包含以下内容:

from test_parent import TestParent


class TestChild(TestParent):

    def test_foo(self):
        pass

    def test_bar(self):
        pass

这导致pytest运行在测试方法TestParent一次(由于在模块中被导入)加上另一个时间作为其一部分TestChild (由于它的方法被继承)。

所以我看到两种方法:(1)不要继承基础测试类,而只是创建一个fixture,以便当前实例同时用于TestParentTestChild

import pytest

from pkg.child import Child
from test_parent import TestParent


@pytest.fixture(scope="class")
def instance():
    return Child()


class TestChild(object):

    def test_foo(self, instance):
        pass

    def test_bar(self, instance):
        pass

(2)我看到的另一种方法是不导入任何测试类,而只是在test_parent.py中创建一个参数化夹具,它将所有相关类的实例插入到这些测试方法中。 就像是:

import pytest

from pkg.parent import Parent
from pkg.child import Child
from pkg.grandchild import GrandChild


@pytest.fixture(scope="class", params=[Parent, Child, GrandChild])
def instance(request):
    return request.param()


class TestParent(object):

    def test_base(self, instance):
        pass

考虑到这一点,我更喜欢选项(2),因为它避免了导入,我甚至可以完全跳过测试类。 但是有更好的方法吗?

您对class TestChild(TestParent):原始建议class TestChild(TestParent):应该可以正常工作。 只是避免在pytest收集的名称下导入它。 例如:

# test_parent.py
class TestParent:

    def test_parent(self):
        assert True

# test_child.py
import test_parent as parent  # renaming not required

class TestChild(parent.TestParent):

    def test_child(self):
        assert True

运行这个:

> pytest -v
======================== test session starts =========================
platform linux -- Python 3.6.5rc1, pytest-3.5.0, py-1.5.3, pluggy-0.6.0 -- /home/flub/.virtualenvs/a713d56197da3b03/bin/python3
cachedir: .pytest_cache
rootdir: /tmp/sandbox, inifile:
collected 3 items                                                                                                                                                                                    

test_child.py::TestChild::test_child PASSED                     [ 33%]
test_child.py::TestChild::test_parent <- test_parent.py PASSED  [ 66%]
test_parent.py::TestParent::test_parent PASSED                  [100%]

=================== 3 passed in 0.01 seconds =========================

请注意,不需要重命名,因为test_仅在函数或方法时被视为测试。 但为了避免混淆,这样做很好。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM