Unittest概述:
Unittest是Python中有一个自带的单元测试框架,用它可以来做单元测试,同时也是一个测试框架,unittest也属于XUnit系列,符合XUnit的一些规则。下面代码是用Python写的一个建议的计算器。
案例1-1:用unittest框架实现测试简易计算器。
#!/usr/bin/envpython
#coding:utf-8
__metaclass_=type
classcalculator:
def__init__(self,a,b):
self.a=int(a)
self.b=int(b)
defmyadd(self):
returnself.a+self.b
defmysubs(self):
returnself.a-self.b
defmymultiply(self):
returnself.a*self.b
defmydivide(self):
try:
returnself.a/self.b
exceptZeroDivisionError:
print("除数不能为零")
return0
calculator类包含了两个类变量:a和b,分别为计算器的两个操作对象。方法myadd、musub、mymultiply和mydivide方法分别实现加、减、乘、除四个功能。现在来测试这几个功能,代码如下。
#!/usr/bin/envpython
#coding:utf-8
#pipinstallcoverage
#coveragereport-m
importunittest
fromCalculatorimportcalculator
classcalculatortest(unittest.TestCase):
defsetUp(self):
print("Teststart!")
#最简单的加减乘除测试
deftest_base(self):
j=calculator(4,2)
self.assertEqual(j.myadd(),6)
self.assertEqual(j.mysubs(),2)
self.assertEqual(j.mymultiply(),8)
self.assertEqual(j.mydivide(),2)
#测试大的数字,为最大的longlong有符号数字
deftest_max_number(self):
j=calculator(9223372036854775808,9223372036854775808)
self.assertEqual(j.mymultiply(),85070591730234615865843651857942052864)
#专门测试减法,结果分别为正数、负数和0,这里用列表作为测试数据,列表中每一个元素也为列表,子列表中包括三个参数,分别为被减数、减数和期待的差值
deftest_subs(self):
mydata=[[4,2,2],[2,4,-2],[4,4,0]]
n=0
foriinmydata:
j=calculator(mydata[n][0],mydata[n][1])
self.assertEqual(j.mysubs(),mydata[n][2])
n+=1
#专门测试乘法,分别为正数乘正数、正数乘负数、负数乘正数、负数乘负数,参数同test_subs
deftest_multiply(self):
mydata=[[4,2,8],[4,-2,-8],[-4,2,-8],[-4,-2,8]]
n=0
judge=True
foriinmydata:
j=calculator(mydata[n][0],mydata[n][1])
self.assertEqual(j.mymultiply(),mydata[n][2])
n+=1
#测试除法中除数等于0
deftest_divide(self):
j=calculator(4,0)
self.assertEqual(j.mydivide(),0)
deftearDown(self):
print("Testend!")
if__name__=='__main__':
#构造测试集
suite=unittest.TestSuite()
suite.addTest(calculatortest("test_base"))
suite.addTest(calculatortest("test_max_number"))
suite.addTest(calculatortest("test_subs"))
suite.addTest(calculatortest("test_multiply"))
suite.addTest(calculatortest("test_divide"))
#运行测试集合
runner=unittest.TextTestRunner()
runner.run(suite)
使用unittest在程序开始importunittest引入unittest类。由于unittest是继承与unittest.TestCase基类的,所以class后面括号内必须为unittest.TestCase。unittest类似于JUnit3,没有@Before、@After等标签,而是通过方法名来表示。等价于@Before的方法为setUp(),等价于@After的方法为tearDown(),等价于@test的方法为test_XXX()(以“test_”开始的方法名)。同样的方法还有如下装饰器,见表所示。

下面方法是利用@parameterized.expand参数化来改造案例1-1中的test_multiply和test_subs。使用parameterized前必须先用pip3把parameterized下载下来。
C:\Users\xiang>pip3installparameterized
Collectingparameterized
Installingcollectedpackages:parameterized
Successfullyinstalledparameterized-0.7.0
代码如下。
案例:利用parameterized参数化unittest测试用例。
fromparameterizedimportparameterized
…
@parameterized.expand([
(4,2,2,),
(2,4,-2,),
(4,4,0,),
])
deftest_mysubs(self,a,b,p):
self.assertEqual(calculator(a,b).mysubs(),p)
@parameterized.expand([
(4,2,8,),
(4,-2,-8,),
(-4,2,-8,),
(-4,-2,8,),
])
deftest_mymultiply(self,a,b,p):
self.assertEqual(calculator(a,b).mymultiply(),p)
…
if__name__=='__main__':
#构造测试集
suite=unittest.TestSuite()
#使用参数话必须要用makeSuite,而不能用suite.addTest,否则会报错
suite=unittest.makeSuite(calculatortest)
#运行测试集合
runner=unittest.TextTestRunner()
runner.run(suite)
由此可见,parameterized.expandlist中的每个括号内的元素对应测试入参的相应的变量,这里与JUnit4参数化有些类似。(注意:由于list中每个元素是一个元祖,所以最后一个参数后必须有一个逗号,比如“(4,2,8,)”)。
下一篇跟大家讲解:unittest的测试覆盖率分析。