Mid*_*ter 2 python inheritance pytest
我已经使用 pytest 一段时间了,并且学会了喜欢参数化和夹具。第一次,我想测试多个具有分支继承结构的类。当然,我想为子类重用测试用例。假设我有以下包结构:
mock
??? pkg
? ??? child.py
? ??? grandchild.py
? ??? parent.py
??? tests
??? test_child.py
??? test_grandchild.py
??? test_parent.py
Run Code Online (Sandbox Code Playgroud)
如this SO question中所述,我可以使用夹具来提供正在测试的类的实例。但是,当我从另一个测试模块中导入测试类时,它 (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
Run Code Online (Sandbox Code Playgroud)
这会导致 pytest 运行TestParent一次测试方法(由于在模块中导入)加上另一次运行TestChild(由于其方法被继承)。
所以我看到两种方法:(1)不要继承基础测试类,而只是创建一个夹具,以便当前实例同时用于TestParent和TestChild,本质上:
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
Run Code Online (Sandbox Code Playgroud)
(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
Run Code Online (Sandbox Code Playgroud)
考虑一下,我更喜欢选项 (2),因为它避免了导入,我什至可以完全跳过测试类。有没有更好的方法呢?
您最初的建议class TestChild(TestParent):应该可以正常工作。只是避免以 pytest 收集的名称导入它。例如:
# test_parent.py
class TestParent:
def test_parent(self):
assert True
Run Code Online (Sandbox Code Playgroud)
和
# test_child.py
import test_parent as parent # renaming not required
class TestChild(parent.TestParent):
def test_child(self):
assert True
Run Code Online (Sandbox Code Playgroud)
运行这个:
> 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 =========================
Run Code Online (Sandbox Code Playgroud)
请注意,重命名不是必需的,因为test_它仅在函数或方法时被视为测试。但是为了避免混淆,这样做很好。