如何合理组织每个测试用例都有数据文件的测试用例?
我正在写一个模块,这个模块需要解析HTML来提取数据,并根据这些数据创建一个对象。简单来说,我想创建一组测试用例,每个用例都是一个HTML文件和一个对应的“标准”对象文件。
当我对解析器进行修改时,我希望能运行这个测试套件,以确保每个HTML页面的解析结果都和“标准”文件一致(这其实就是一个回归测试套件)。
我知道怎么把这个写成一个单一的测试用例,方法是从某个目录加载所有的文件对,然后逐个处理它们。但是我觉得这样最终会被报告为一个单一的测试用例,要么通过,要么失败。但我希望能得到一个报告,比如说,45个页面成功解析,47个页面中。
我该怎么安排这个呢?
2 个回答
3
这个nose测试框架支持这个功能。你可以在这里找到更多信息:http://www.somethingaboutorange.com/mrl/projects/nose/
另外,你也可以看看这个链接:如何在Python中生成动态(参数化)单元测试?
以下是我会做的事情(未经测试):
files = os.listdir("/path/to/dir")
class SomeTests(unittest.TestCase):
def _compare_files(self, file_name):
with open('/path/to/dir/%s-golden' % file_name, 'r') as golden:
with open('/path/to/dir/%s-trial' % file_name, 'r') as trial:
assert golden.read() == trial.read()
def test_generator(file_name):
def test(self):
self._compare_files(file_name):
return test
if __name__ == '__main__':
for file_name in files:
test_name = 'test_%s' % file_name
test = test_generator(file_name)
setattr(SomeTests, test_name, test)
unittest.main()
4
我之前用 unittest
这个框架做过类似的事情,写了一个函数来创建并返回一个测试类。这个函数可以接收你想要的任何参数,然后根据这些参数来定制测试类。你还可以定制测试函数的 __doc__
属性,这样在运行测试时就能显示自定义的信息。
我快速写了下面这个示例代码来说明这个过程。这个代码并没有进行实际的测试,而是使用 random
模块故意让一些测试失败,以便演示。当这些类被创建后,它们会被放入全局命名空间,这样调用 unittest.main()
时就能找到它们。根据你运行测试的方式,你可能会想对生成的类做一些不同的处理。
import os
import unittest
# Generate a test class for an individual file.
def make_test(filename):
class TestClass(unittest.TestCase):
def test_file(self):
# Do the actual testing here.
# parsed = do_my_parsing(filename)
# golden = load_golden(filename)
# self.assertEquals(parsed, golden, 'Parsing failed.')
# Randomly fail some tests.
import random
if not random.randint(0, 10):
self.assertEquals(0, 1, 'Parsing failed.')
# Set the docstring so we get nice test messages.
test_file.__doc__ = 'Test parsing of %s' % filename
return TestClass
# Create a single file test.
Test1 = make_test('file1.html')
# Create several tests from a list.
for i in range(2, 5):
globals()['Test%d' % i] = make_test('file%d.html' % i)
# Create them from a directory listing.
for dirname, subdirs, filenames in os.walk('tests'):
for f in filenames:
globals()['Test%s' % f] = make_test('%s/%s' % (dirname, f))
# If this file is being run, run all the tests.
if __name__ == '__main__':
unittest.main()
一个示例运行:
$ python tests.py -v
Test parsing of file1.html ... ok
Test parsing of file2.html ... ok
Test parsing of file3.html ... ok
Test parsing of file4.html ... ok
Test parsing of tests/file5.html ... ok
Test parsing of tests/file6.html ... FAIL
Test parsing of tests/file7.html ... ok
Test parsing of tests/file8.html ... ok
======================================================================
FAIL: Test parsing of tests/file6.html
----------------------------------------------------------------------
Traceback (most recent call last):
File "generic.py", line 16, in test_file
self.assertEquals(0, 1, 'Parsing failed.')
AssertionError: Parsing failed.
----------------------------------------------------------------------
Ran 8 tests in 0.004s
FAILED (failures=1)