众所周知, 在单元测试框架中引入 ddt, 可以将一组数据分解为多组数据, 从而实现一条数据对应一个测试用例. 但是除此之外, 有没有别的办法来实现这个目的呢?
一. 代码部分
1. 创建一个被测函数 math_method.py
- class MethMethod():
- def add_test(self,a,b):
- return (a+b)
2. 创建测试用例 test_math_method.py
- import unittest
- from homework.math_method import MethMethod
- # 测试类
- class TestMathMethod(unittest.TestCase):
- def __init__(self, methodName, a, b, expected):
- super(TestMethMethod, self).__init__(methodName)
- self.a = a
- self.b = b
- self.expected = expected
- #测试用例
- def test_add(self):
- try:
- self.assertEqual(result, self.expected)
- except Exception:
- print("出错了")
- else:
- print("计算结果是:{}".format(result))
3. 创建测试数据 test_data.txt
[{"a":2,"b":3,"expected":5},{"a":-1,"b":-2,"expected":-3},{"a":3,"b":-1,"expected":-2},{"a":-3,"b":-1,"expected":-4}]
4. 创建测试集 test_suite.py
- import unittest
- from homework.test_math_method import TestMathMethod
- import htmlTestRunnerNew
- fs= open("test_data.txt")
- datas = fs.read()
- datas = eval(datas)
- print(type(datas))
- if __name__ == '__main__':
- suite=unittest.TestSuite()
- for item in datas:
- suite.addTest(TestMathMethod("test_add", item['a'], item['b'], item['expected']))
- file=open("test_report.html","wb+")
- runner=HTMLTestRunnerNew.HTMLTestRunner(file,title="加法单元测试报告",tester="july")
- runner.run(suite)
二. 代码分析
1. 测试用例类中需要定义一个构造函数, 这个构造函数继承了父类的属性, 也就是 unittest.TestCase 的 methodName 参数
同时, 在子类中也重写了构造函数, 添加了参数 a, b, expected, 而这三个则是测试用例函数 test_add 需要用到的
- class TestMethMethod(unittest.TestCase):
- def __init__(self, methodName, a, b, expected):
- super(TestMethMethod, self).__init__(methodName)
- self.a = a
- self.b = b
- self.expected = expected
请看 TestCase 的源码
- class TestCase(object):
- failureException = AssertionError
- longMessage = True
- maxDiff = 80*8
- # If a string is longer than _diffThreshold, use normal comparison instead
- # of difflib. See #11763.
- _diffThreshold = 2**16
- # Attribute used by TestSuite for classSetUp
- _classSetupFailed = False
- def __init__(self, methodName='runTest'):
- """Create an instance of the class that will use the named test
- method when executed. Raises a ValueError if the instance does
- not have a method with the specified name.
- """
- self._testMethodName = methodName
- self._outcome = None
- self._testMethodDoc = 'No test'
- try:
- testMethod = getattr(self, methodName)
- except AttributeError:
- if methodName != 'runTest':
- # we allow instantiation with no explicit method name
- # but not an *incorrect* or missing method name
- raise ValueError("no such test method in %s: %s" %
- (self.__class__, methodName))
- else:
- self._testMethodDoc = testMethod.__doc__
- self._cleanups = []
- self._subtest = None
2. 此时回到测试集中, 看下面一段, TestMathMethod 类中本来只有一个参数, methodName, 也就是测试用例名, 但此时的 TestMathMethod 已经被我们改写了: 不仅继承了父类的 methodName 方法, 而且构造函数中新增了三个参数 a, b, expected, 这样我们在收集测试用例时, 可以为 TestMathMethod 类添加四个参数: methodName, a, b, expected. 通过 for 循环遍历一组数据, 这样可以将多组数据作为多个测试用例添加到测试集中
- for item in datas:
- suite.addTest(TestMathMethod("test_add", item['a'], item['b'], item['expected']))
三. 比较
ddt 的方法: 简单, 因为涉及到装饰器, 不易理解
构造函数: 略显繁琐, 但容易理解
来源: http://www.bubuko.com/infodetail-2735704.html