unittest原名为PyUnit,是由java的JUnit衍生而来。对于单元测试,需要设置预先条件,对比预期结果和实际结果。
整体结构:
unittest库提供了test cases, test suites, test fixtures,test runner:
1、test case : 通过继承TestCase类,我们可以创建一个test,或者一组tests,包括测试前准备环境的搭建(setUp),执行测试代码(run),以及测试后环境的还原(tearDown)。 2、test suites : 测试套件,多个测试用例集合在一起,TestSuite也可以嵌套TestSuite。 3、test fixtures : setup + test case + teardown结构 4、TestLoader: 用来加载TestCase到TestSuite中,其中的方法从各个地方寻找TestCase,创建它们的实例,然后add到TestSuite中,返回一个TestSuite实例。 5、test runner: 执行测试用例,其中的run()会执行TestSuite/TestCase。 6、TextTestResult: 测试的结果会保存到TextTestResult实例中,包括运行用例数,成功数,失败数等。
写好TestCase,然后由TestLoader加载TestCase到TestSuite,然后由TextTestRunner来运行TestSuite,运行的结果保存在TextTestResult中,整个过程集成在unittest.main模块中。
注:
所有的测试函数以test开头,test_XXX。
简单的示例:
import unittest
class TestStringMethods(unittest.TestCase):
def test_upper(self):
self.assertEqual('foo',upper(),'FOO')
def test_isupper(self):
self.assertEqualTure('FOO'.isupper())
self.assertFalse('Foo'.isupper())
def test_split(self):
s = 'hello world'
self.assertEqual(s.split(),['hello','world'])
with self.assertEqualRaise(TypeError):
s.slipt(2)
if __name__ == '__main__': #unittest.main:为测试提供了入口。
unittest.main()
#运行结果:
...
----------------------------------------------------------------------
Ran 3 tests in 0.064s
OK
其他与unittest类似的单元测试库: nose, pytest。
二 命令行
从命令行中可以运行单元测试的模块,类,甚至单独的测试方法。
python -m unittest test_module1 test_module2 #同时测试多个module
python -m unittest test_module.TestClass
python -m unittest test_module.TestClass.test_method
显示更详细的测试结果的说明使用-vflag:
python -m unittest -v test_module
查看所有的命令行选项使用命令python -m unittest -h
三 TestCaseTestcase类class unittest.TestCase(methodName='runTest')
TestCase的实例是最小的可测试单元。 testcase 是由unittest的TestCase类的实例表示的。要编写自己的测试用例必须继承TestCase类,或者使用FunctionTestCase。且Testcase类提供了各种assert的方法来检测预期结果和实际结果。
看下面的例子(创建一个测试类DefaultWidgetSizeTestCase):
import unittest
class DefaultWidgetSizeTestCase(unittest.TestCase): #unittest.TestCase表示某个测试函数
def runTest(self):
widget = Widget('The widget')
self.assertEqual(widget.size(), (50, 50), 'incorrect default size')
创建实例
建立这样一个测试用例的一个实例,使用该类的构造函数,且不带参数(这样会执行所有的测试方法):
testCase = DefaultWidgetSizeTestCase()
我们也可以创建多个实例,且每个实例之间都是独立的。
当我们需要对不同的实例执行不同的测试方法时,我们可以将要执行的测试用例方法在创建实例时通过类参数传入。
#建了两个WidgetTestCase的实例,每个实例只运行WidgetTestCase类中的一个测试方法(通过参数传入)
defaultSizeTestCase = WidgetTestCase('test_default_size')
resizeTestCase = WidgetTestCase('test_resize')
常用断言方法
unittest库提供了很多实用方法来检测程序运行的结果和预期。
包括三种类型的方法,每一种都覆盖了典型的类型,比如:
- 检查相等值
- 逻辑比较
- 异常
如果给定的assertion通过了,那么测试会执行下一行代码。
如果给定的assertion没有通过,测试会暂停并且生成错误信息。
unittest库提供所有标准的xUnit assert方法。下面列出较重要方法的一部分:
检测元素是否相等:
assertEqual(a,b [,msg]): 检测a==b,这个方法检查a是否等于b,常用语检测元素属性等。如:
assertEqual(element.text, "10")
assertNotEqual(a,b [,smg]):检测a!==b.
检测表达式是否为Ture,或者 False:
assertTrue(x [,msg]) #检测bool(x) is True.
#如:检测某个元素是否在页面上
#assertTrue(element.is_dispalyed())
assertFalse(x [,msg]) #检测bool(y) is Flase.
assertIsNot(a, b [,msg]) #检测 a is not b.
检测异常
assertRaises(exc, fun, *args, **kwds)
assertRaiseRegexp(exc, r, fun, *args, **kwds)
最有可能使用这些方法的是NoSuchElementFoundexception
检测数字,先四舍五入到指定的小数位数后再进行比较
assertAlmostEqual(a, b) #检测round(a-b,7)==0
assertNotAlmostEqual(a, b) #检测round(a-b,7)!=0
逻辑运算
assertGreater(a, b) # 检测a > b.
assertGreaterEqual(a ,b) # 检测a >= b.
assertLess(a, b) #检测a import helpin
>>> help(helpin)
Help on module helpin:
NAME
helpin - 这是help能够显示的帮助信息
FILE
e:\python27\lib\helpin.py
FUNCTIONS
add(a)
这个函数用来输入a的值
2 报告中显示用例的注释
给报告中的每个测试用例添加注释,来说明该测试用例是用来干什么的,非常有必要。
通过help()函数来查看HTMLTestRunner类的详细说明:
>>> import HTMLTestRunner
>>> help(HTMLTestRunner)
可以看到该类的注释说明,一个好的开源的框架应该有这样的规范。
这里在每个测试函数的下方添加上注释:
def test_equal(self):
u'''这里是测试a和b的两个值是否相等'''
a = 1
b = 2
self.assertEqual(a,b)
运行后,打开生成的html文件可以看到,每个测试用例函数的后面有该用例的注释。 点击查看代码示例
3 动态生成需要多次执行的测试报告文件名称
如果一个测试套件需要多次执行,如果每次执行不去修改测试报告.html的文件名,则每次执行后会将之前的报告覆盖。如果想要保存每次执行的结果而不手动修改报告名称。这里可以使用动态生成文件名的方法。具体的生成可以根据需要来写动态生成的代码。
动态时间 python 时间函数:
- time.time() 获取当前时间戳。
- time.ctime() 当前时间的字符串形式。
- time.localtime() 当前时间的 struct_time 形式。
- time.strftime() 用来获得当前时间,可以将时间格式化为字符串。
修改之前的代码,将文件名字中添加上当前获取到的时间:
#获取当前时间
now = time.strftime("%Y-%m-%d %H_%M_%S")
#定义报告文件存放位置,这里将结果放在桌面
outfile = open('C:\\Users\Administrator\\Desktop\\'+ now + '_result.html', "w")
生成的文件名称以2016-03-09_17_37_26_result.html格式出现。
4 集成多个测试结果
目前测试报告只集成到了单个测试文件中,我们的最终目的是将其集成到一个文件中。
之前是通过testunit.addTests()函数逐个添加。
现在通过unittest.defaultTestLoader.discover()方法循环遍历添加测试用例。
最后通过runner.run()方法运行整个测试用例集。
另外,欢迎加入软件测试技术交流群 313782132 ~进群可领取免费软件测试资料以及群内测试大牛解惑!
测试工程师职业发展路线图
功能测试 — 接口测试 — 自动化测试 — 测试开发 — 测试架构师
加油吧,测试人!如果你需要提升规划,那就行动吧,在路上总比在起点观望的要好。事必有法,然后有成。
资源不错就给个推荐吧~