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

时间:2018-04-10 09:09:50

标签: python inheritance pytest

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

public class OnDeleteIconClicked implements View.OnClickListener {

private int position;

@Override
public void onClick(View v) {
 this.position = getAdapterPosition();   
 context.OnDeleteItemClicked(Integer.parseInt(v.getTag().toString()), position);
}

public int getPosition() {
 return position;
}

this SO question中所述,我可以使用fixture来提供正在测试的类的实例。但是,当我从另一个测试模块中导入测试类时,它(a)感觉它不是pytest方式,(b)pytest将运行导入类的所有测试方法并再次运行它们作为继承的测试类。比方说,文件mock ├── pkg │   ├── child.py │   ├── grandchild.py │   └── parent.py └── tests ├── test_child.py ├── test_grandchild.py └── test_parent.py 包含以下内容:

test_child.py

这导致pytest在from test_parent import TestParent class TestChild(TestParent): def test_foo(self): pass def test_bar(self): pass 中运行测试方法一次(由于在模块中导入)加上另一个时间作为TestParent的一部分(由于其方法被继承)。

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

TestChild

(2)我看到的另一种方法是不导入任何测试类,只是在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 中创建一个参数化夹具,将所有相关类的实例插入到这些测试方法中。类似的东西:

test_parent.py

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

1 个答案:

答案 0 :(得分:3)

您对class TestChild(TestParent):的原始建议应该可以正常使用。只是避免在pytest收集的名称下导入它。 E.g:

# 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_仅在函数或方法时被视为测试。但为了避免混淆,这样做很好。