2.4 TestNG的装饰器
前面介绍了TestNG的使用,下面来看一下TestNG的装饰器,如表2所示。
表2 TestNG的装饰器
注解 |
描述 |
@BeforeSuite |
注解的方法将只运行一次,运行所有测试前此套件中。 |
@AfterSuite |
注解的方法将只运行一次,此套件中的所有测试都运行之后。 |
@BeforeClass |
注解的方法将只运行一次先行先试在当前类中的方法调用。 |
@AfterClass |
注解的方法将只运行一次后已经运行在当前类中的所有测试方法。 |
@BeforeTest |
注解的方法将被运行之前的任何测试方法属于内部类的 <test>标签的运行。 |
@AfterTest |
注解的方法将被运行后,所有的测试方法,属于内部类的<test>标签的运行。 |
@BeforeGroups |
组的列表,这种配置方法将之前运行。此方法是保证在运行属于任何这些组第一个测试方法,该方法被调用。 |
@AfterGroups |
组的名单,这种配置方法后,将运行。此方法是保证运行后不久,最后的测试方法,该方法属于任何这些组被调用。 |
@BeforeMethod |
注解的方法将每个测试方法之前运行。 |
@AfterMethod |
被注释的方法将被运行后,每个测试方法。 |
@DataProvider |
标志着一个方法,提供数据的一个测试方法。注解的方法必须返回一个Object[][],其中每个对象[]的测试方法的参数列表中可以分配。 该@Test 方法,希望从这个DataProvider的接收数据,需要使用一个dataProvider名称等于这个注解的名字。 |
@Factory |
作为一个工厂,返回TestNG的测试类的对象将被用于标记的方法。该方法必须返回Object[]。 |
@Listeners |
定义一个测试类的监听器。 |
@Parameters |
介绍如何将参数传递给@Test方法。 |
@Test |
标记一个类或方法作为测试的一部分。 |
3 Python单元测试框架unittest
3.1 unittest概述
unittest是Python中有一个自带的单元测试框架,用它可以来做单元测试,unittest也属于XUnit系列,符合XUnit的一些规则。下面代码是用Python写的类似计算器。
案例5:用unittest框架实现测试简易计算器。
#!/usr/bin/env python #coding:utf-8 __metaclass_=type class calculator: def__init__(self, a, b): self.a=int(a) self.b=int(b) defmyadd(self): return self.a+self.b defmysubs(self): return self.a-self.b defmymultiply(self): return self.a*self.b defmydivide(self): try: return self.a/self.b except ZeroDivisionError: print ("除数不能为零") return 0
calculator类包含了两个类变量,a和b,分别为计算器的两个操作对象。方法myadd、musub、 mymultiply和mydivide方法分别实现加、减、乘、除功能。现在来测试这几个功能,代码如下。
#!/usr/bin/env python #coding:utf-8 # pip install coverage # coveragerun Calculatortest.py # coveragereport -m import unittest from Calculator import calculator class calculatortest(unittest.TestCase): defsetUp(self): print ("Test start!") #最简单的加减乘除测试 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) #测试大的数字,为最大的long long有符号数字 def test_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 for i in mydata: 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 for i in mydata: 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 ("Test end!") 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。class的参数必须为unittest.TestCase 。unittest类似于JUnit 3,没有@Before、@After等标签,而是通过方法名来表示。等价于@Before的方法为setUp(),等价于@After的方法为tearDown (),等价于@test的方法为test_XXX ()(以“test_”开始的方法名)。同样的方法还有如下装饰器,见表3所示。
表3 unittest的装饰器
装饰器 |
介绍 |
@classmethod def setUpClass(cls): |
在整个类运行前执行只执行一次 |
@classmethod def tearDownClass(cls) : |
在整个类运行后执行只执行一次 |
@unittest.skip(reason): skip(reason) |
无条件跳过装饰的测试,并说明跳过测试的原因 |
@unittest.skipIf(reason): skipIf(condition,reason) |
条件为真时,跳过装饰的测试,并说明跳过测试的原因 |
@unittest.skipUnless(reason): skipUnless(condition,reason) |
条件为假时,跳过装饰的测试,并说明跳过测试的原因 |
@unittest.expectedFailure(): expectedFailure() |
测试标记为失败 |
@parameterized.expand |
测试参数化 |
下面方法是利用@parameterized.expand来改造案例5中的test_multiply和test_subs。使用parameterized前必须先用pip把parameterized下载下来。
C:\Users\Jerry>pip3 install parameterized
Collecting parameterized
Downloadinghttps://files.pythonhosted.org/packages/d6/9b/5830b778f213ada36528d1c54fdc0a67178e6edd7c44ed59074851ebb2e7/parameterized-0.7.0-pypy3-none-any.whl
Installing collected packages: parameterized
Successfully installed parameterized-0.7.0
代码如下。
案例6:利用parameterized参数化unittest测试用例。
from parameterized import parameterized … @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.expand中每个list的每个括号内的元素对应测试入参的响应变量,这里与JUnit4参数化有些类似。
星云测试
奇林软件
联合通测
顾翔凡言:
k=(p+m)t
其中:
k为常数。
p:团队人员质量水平,为单位小时内产生的有效质量,单位为/h;
m:团队方法质量水平,为单位小时内产生的有效质量,单位为/h;
t:为单位质量产品的交付时间,单位为h。
在团队方法质量水平不变,团队人员质量水平提高的情况下,交付时间变短;
在团队人员质量水平不变,团队方法质量水平提高的情况下,交付时间变短;
团队人员质量水平与方法质量水平乘积决定了软件的质量水平,如果这个值变小,则t变大;反之t变小。
例如,当k=4时:
当人员质量水平为1/小时、方法水平为1/小时时,交付时间为2小时。
当人员质量水平为2/小时、方法水平为1/小时时,交付时间为4/3小时。
当人员质量水平为1/小时、方法水平为2/小时时,交付时间为4/3小时。
当人员质量水平为0.5/小时、方法水平为0.5/小时时,交付时间为4小时。