代码编写与用例组织
欢迎加入测试交流群:夜行者自动化测试(816489363)进行交流学习QAQ
–成都-阿木木
再使用unittest编写你的测试代码时,测试类必须继承TestCase或者FunctionTestCase.
TestCase的子类的实例是可以完全运行单个测试方法以及可选的设置和整理代码的对象。
TestCase实例的测试代码应完全独立,以使它可以独立运行或与任意数量的其他测试用例任意组合运行。
官网有一段组织测试用例的描述,为什么会衍生出setup/teardown/setUpClass/tearDownClass,用比较直白的话来表述,就是我们不会在每一个test method中去实例化测试对象等公共操作,这些重复的操作会导致代码看起来很难看,所以提供了夹具test fixture来进行设置这一类需要在每个测试类或者测试方法前后进行环境初始化,或者环境清理的对象或公共操作。
当用例执行发现setup/setUpClass方法执行失败时,不会再运行后面的test method,当teardown/tearDownClass执行失败时,test_method方法仍然会运行。
一条测试用例是如何标记为失败呢?使用基类assert*()提供的方法对于用例中的结果进行断言,如果断言失败,就会引发异常。也就是说unittest框架通过识别异常将用例标记为fail。其他不属于assert抛出的异常,都会被识别成ERROR。
#!/user/bin/env python# -*- coding: utf-8 -*-"""
------------------------------------
@Project : mysite
@Time : 2020/8/28 11:32
@Auth : chineseluo
@Email : 848257135@qq.com
@File : unittest_demo.py
@IDE : PyCharm
------------------------------------
"""importunittestclassTestStringMethods(unittest.TestCase):defsetUp(self):print("运行于测试方法前,主要用于环境初始化")deftearDown(self):print("运行于测试方法后,主要用户环境数据清理")deftest_upper(self):print("this is a test_upper method")self.assertEqual('foo'.upper(),'FOO')deftest_isupper(self):print("this is a test_isupper method")self.assertTrue('FOO'.isupper())self.assertFalse('Foo'.isupper())deftest_split(self):print("this is a test_split method")s='hello world'self.assertEqual(s.split(),['hello','world'])# check that s.split fails when the separator is not a stringwithself.assertRaises(TypeError):s.split(2)if__name__=='__main__':unittest.main()
运行结果:运行于测试方法前,主要用于环境初始化thisisa test_isupper method运行于测试方法后,主要用户环境数据清理运行于测试方法前,主要用于环境初始化thisisa test_split method运行于测试方法后,主要用户环境数据清理运行于测试方法前,主要用于环境初始化thisisa test_upper method运行于测试方法后,主要用户环境数据清理...----------------------------------------------------------------------Ran3testsin0.000sOK
在下面的例子中修改test_upper方法中的self.assertEqual('foo'.upper(), 'FOO')为self.assertEqual('foo'.upper(), 'FO'),查看断言异常运行结果,可以看到FAILED(failures=1),属于unittest可识别的断言异常。
importunittestclassTestStringMethods(unittest.TestCase):defsetUp(self):print("运行于测试方法前,主要用于环境初始化")deftearDown(self):print("运行于测试方法后,主要用户环境数据清理")deftest_upper(self):print("this is a test_upper method")self.assertEqual('foo'.upper(),'FO')deftest_isupper(self):print("this is a test_isupper method")self.assertTrue('FOO'.isupper())self.assertFalse('Foo'.isupper())deftest_split(self):print("this is a test_split method")s='hello world'self.assertEqual(s.split(),['hello','world'])# check that s.split fails when the separator is not a stringwithself.assertRaises(TypeError):s.split(2)if__name__=='__main__':unittest.main()
运行结果为:C:\Users\luozhongwen\AppData\Local\Programs\Python\Python38\python.exe D:/TestScriptDir/python_web/mysite/unittest_demo.py..F======================================================================FAIL:test_upper(__main__.TestStringMethods)----------------------------------------------------------------------Traceback(most recent call last):File"D:/TestScriptDir/python_web/mysite/unittest_demo.py",line26,intest_upper self.assertEqual('foo'.upper(),'FO')AssertionError:'FOO'!='FO'-FOO?-+FO----------------------------------------------------------------------Ran3testsin0.001sFAILED(failures=1)运行于测试方法前,主要用于环境初始化thisisa test_isupper method运行于测试方法后,主要用户环境数据清理运行于测试方法前,主要用于环境初始化thisisa test_split method运行于测试方法后,主要用户环境数据清理运行于测试方法前,主要用于环境初始化thisisa test_upper method运行于测试方法后,主要用户环境数据清理Process finishedwithexit code1
在下面的例子的test_isupper中添加一个非断言异常,索引越界异常,查看运行结果,可以看到这是一个非assert的异常,被标记为了error。
importunittestclassTestStringMethods(unittest.TestCase):defsetUp(self):print("运行于测试方法前,主要用于环境初始化")deftearDown(self):print("运行于测试方法后,主要用户环境数据清理")deftest_upper(self):print("this is a test_upper method")self.assertEqual('foo'.upper(),'FOO')deftest_isupper(self):print("this is a test_isupper method")a=[1,2,3]print(a[4])self.assertTrue('FOO'.isupper())self.assertFalse('Foo'.isupper())deftest_split(self):print("this is a test_split method")s='hello world'self.assertEqual(s.split(),['hello','world'])# check that s.split fails when the separator is not a stringwithself.assertRaises(TypeError):s.split(2)if__name__=='__main__':unittest.main()
结果为:======================================================================ERROR:test_isupper(__main__.TestStringMethods)----------------------------------------------------------------------Traceback(most recent call last):File"D:/TestScriptDir/python_web/mysite/unittest_demo.py",line31,intest_isupperprint(a[4])IndexError:listindex out ofrange----------------------------------------------------------------------Ran3testsin0.001sFAILED(errors=1)运行于测试方法前,主要用于环境初始化thisisa test_isupper method运行于测试方法后,主要用户环境数据清理运行于测试方法前,主要用于环境初始化thisisa test_split method运行于测试方法后,主要用户环境数据清理运行于测试方法前,主要用于环境初始化thisisa test_upper method运行于测试方法后,主要用户环境数据清理Process finishedwithexit code1
执行用例:
unittest框架建议在进行测试用例编写时,按照功能进行测试用例分组,unittest提供了一种机制:测试套件,由unittest的TestSuite类表示。通常使用unittest.main(),它会自动收集所有模块的测试用例并执行它们。
有时候我们需要自定义测试套件的构建,需要自己进行测试套的添加。
测试套可以放在相同的模块(例如:unittest_demo.py),针对当前测试模块,测试用例,测试方法
测试套也可以放在一个脚本的入口模块中,例如run.py中,进行各个测试模块中细分的方法的执行
放在相同脚本的当中:
#!/user/bin/env python# -*- coding: utf-8 -*-"""
------------------------------------
@Project : mysite
@Time : 2020/8/28 11:32
@Auth : chineseluo
@Email : 848257135@qq.com
@File : unittest_demo.py
@IDE : PyCharm
------------------------------------
"""importunittestclassTestStringMethods(unittest.TestCase):defsetUp(self):print("运行于测试方法前,主要用于环境初始化")deftearDown(self):print("运行于测试方法后,主要用户环境数据清理")deftest_upper(self):print("this is a test_upper method")self.assertEqual('foo'.upper(),'FOO')deftest_isupper(self):self.assertTrue('FOO'.isupper())self.assertFalse('Foo'.isupper())deftest_split(self):print("this is a test_split method")s='hello world'self.assertEqual(s.split(),['hello','world'])# check that s.split fails when the separator is not a stringwithself.assertRaises(TypeError):s.split(2)defsuite():suite=unittest.TestSuite()suite.addTest(TestStringMethods('test_upper'))suite.addTest(TestStringMethods('test_isupper'))returnsuiteif__name__=='__main__':runner=unittest.TextTestRunner()runner.run(suite())
运行结果:..----------------------------------------------------------------------Ran2testsin0.000sOK运行于测试方法前,主要用于环境初始化thisisa test_upper method运行于测试方法后,主要用户环境数据清理运行于测试方法前,主要用于环境初始化运行于测试方法后,主要用户环境数据清理Process finishedwithexit code0
放在不同的脚本中,通过导入需要进行自定义测试套件的模块下的测试类:
#!/user/bin/env python# -*- coding: utf-8 -*-"""
------------------------------------
@Project : mysite
@Time : 2020/8/28 11:32
@Auth : chineseluo
@Email : 848257135@qq.com
@File : unittest_demo.py
@IDE : PyCharm
------------------------------------
"""importunittestclassTestStringMethods(unittest.TestCase):defsetUp(self):print("运行于测试方法前,主要用于环境初始化")deftearDown(self):print("运行于测试方法后,主要用户环境数据清理")deftest_upper(self):print("this is a test_upper method")self.assertEqual('foo'.upper(),'FOO')deftest_isupper(self):self.assertTrue('FOO'.isupper())self.assertFalse('Foo'.isupper())deftest_split(self):print("this is a test_split method")s='hello world'self.assertEqual(s.split(),['hello','world'])# check that s.split fails when the separator is not a stringwithself.assertRaises(TypeError):s.split(2)
run.py
#!/user/bin/env python# -*- coding: utf-8 -*-"""
------------------------------------
@Project : mysite
@Time : 2020/8/31 9:29
@Auth : chineseluo
@Email : 848257135@qq.com
@File : run.py
@IDE : PyCharm
------------------------------------
"""importunittestfromunittest_demoimportTestStringMethodsdefsuite():suite=unittest.TestSuite()suite.addTest(TestStringMethods('test_upper'))suite.addTest(TestStringMethods('test_isupper'))returnsuiteif__name__=='__main__':runner=unittest.TextTestRunner()runner.run(suite())