大多数测试框架都假定“1 个测试 = 1 个 Python 方法/函数”, 并在函数执行时认为测试通过 提出断言。
我正在测试一个类似编译器的程序(一个读取 *.foo
的程序
文件并处理它们的内容),为此我想对许多输入(*.foo
)文件执行相同的测试。 IOW,我的测试看起来像:
class Test(unittest.TestCase):
def one_file(self, filename):
# do the actual test
def list_testcases(self):
# essentially os.listdir('tests/') and filter *.foo files.
def test_all(self):
for f in self.list_testcases():
one_file(f)
我当前的代码使用
unittest从
Python 的标准库,即 one_file
使用 self.assert...(...)
检查测试是否通过的语句。
这是可行的,因为我确实得到了一个成功/失败的程序 当我的代码没问题/有问题时,但我失去了很多优点 测试框架:
我没有收到相关报告,例如“Y 项测试失败 X 次”,也没有 通过/失败测试的列表。 (我打算使用这样的系统 不仅要测试自己的开发还要给学生的代码打分 作为一名教师,所以报告对我来说很重要)
我没有测试独立性。第二次测试运行在 第一个留下的环境,依此类推。第一次失败停止 测试套件:失败后出现的测试用例根本不会运行。
我觉得我在滥用我的测试框架:只有 一种测试功能,因此可以自动测试发现 unittest 声音 例如矫枉过正。同样的代码可以(应该?)写成 带有基本
assert
的纯 Python。
一个明显的替代方法是将我的代码更改为类似
class Test(unittest.TestCase):
def one_file(self, filename):
# do the actual test
def test_file1(self):
one_file("first-testcase.foo")
def test_file2(self):
one_file("second-testcase.foo")
然后我得到了 unittest 的所有优点,但是:
还有很多代码要写。
“忘记”测试用例很容易,即在
tests/
忘记将其添加到 Python 测试中。
我可以想象一个解决方案,我会动态地为每个测试用例生成一个方法(沿着 setattr(self, 'test_file' + str(n), ...)
行),以生成无需手动编写第二个解决方案的代码。但对于一个看起来并不复杂的用例来说,这听起来确实有点过分了。
我怎样才能兼顾两者,即
自动测试用例发现(列出 tests/*.foo
文件),测试
独立性和适当的报告?
最佳答案
如果可以使用pytest作为您的测试运行器,那么使用 parametrize
decorator 实际上非常简单:
import pytest, glob
all_files = glob.glob('some/path/*.foo')
@pytest.mark.parametrize('filename', all_files)
def test_one_file(filename):
# do the actual test
这也会以有用的方式自动命名测试,这样您就可以看到哪些文件失败了:
$ py.test
================================== test session starts ===================================
platform darwin -- Python 3.6.1, pytest-3.1.3, py-1.4.34, pluggy-0.4.0
[...]
======================================== FAILURES ========================================
_____________________________ test_one_file[some/path/a.foo] _____________________________
filename = 'some/path/a.foo'
@pytest.mark.parametrize('filename', all_files)
def test_one_file(filename):
> assert False
E assert False
test_it.py:7: AssertionError
_____________________________ test_one_file[some/path/b.foo] _____________________________
filename = 'some/path/b.foo'
@pytest.mark.parametrize('filename', all_files)
def test_one_file(filename):
[...]
关于python - 每个输入文件单独的测试用例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45751607/