UnitTest框架 :是Python自带的一个单元测试框架 ,不仅仅可以用来做单元测试,测试人员也经常用来做自动化测试
2. 如何定义测试用例?
3. 如何定义测试套件?
4. 如何执行测试套件?
5. TestLoader与TestSuite的区别?
6. Fixture控制级别有哪些类型?
7. 方法级别的Fixture与类级别的Fixture有什么区别?
为什么使用UnitTest框架?
1. 能够组织多个⽤例去执⾏
2. 提供丰富的断⾔⽅法
3. 能够⽣成测试报告
默认规则
- 模块名必须以
test_ 开头或者_test 结尾 - 类名必须以
Test 开头 - 测试方法必须以
test 开头
核⼼要素(组成)
1. TestCase
测试⽤例, 这个测试⽤例是 unittest 的组成部分,作⽤是 ⽤来书写真正的⽤例代码(脚本)
# 1. 导包 unittestimport unittest# 2. 定义测试类, 只要继承 unittest.TestCase 类, 就是 测试类class TestDemo(unittest.TestCase):# 3. 书写测试方法, 方法中的代码就是真正用例代码, 方法名必须以 test 开头def test_method1(self):print('测试方法一')def test_method2(self):print('测试方法二')# 4. 执行# 4.1 在类名或者方法名后边右键运行(pycharm中此方法)# 4.1.1 在类名后边, 执行类中的所有的测试方法# 4.1.2 在方法名后边, 只执行当前的测试方法# 4.2 在主程序使用使用 unittest.main() 来执行,if __name__ == '__main__':unittest.main()# 1. 导包 unittest import unittest # 2. 定义测试类, 只要继承 unittest.TestCase 类, 就是 测试类 class TestDemo(unittest.TestCase): # 3. 书写测试方法, 方法中的代码就是真正用例代码, 方法名必须以 test 开头 def test_method1(self): print('测试方法一') def test_method2(self): print('测试方法二') # 4. 执行 # 4.1 在类名或者方法名后边右键运行(pycharm中此方法) # 4.1.1 在类名后边, 执行类中的所有的测试方法 # 4.1.2 在方法名后边, 只执行当前的测试方法 # 4.2 在主程序使用使用 unittest.main() 来执行, if __name__ == '__main__': unittest.main()# 1. 导包 unittest import unittest # 2. 定义测试类, 只要继承 unittest.TestCase 类, 就是 测试类 class TestDemo(unittest.TestCase): # 3. 书写测试方法, 方法中的代码就是真正用例代码, 方法名必须以 test 开头 def test_method1(self): print('测试方法一') def test_method2(self): print('测试方法二') # 4. 执行 # 4.1 在类名或者方法名后边右键运行(pycharm中此方法) # 4.1.1 在类名后边, 执行类中的所有的测试方法 # 4.1.2 在方法名后边, 只执行当前的测试方法 # 4.2 在主程序使用使用 unittest.main() 来执行, if __name__ == '__main__': unittest.main()
2. Testsuite
测试套件, 作⽤是⽤来组装(打包)TestCase(测试⽤例) 的,即 可以将多个⽤例脚本⽂件组装到⼀起
3. TestRunner
测试执⾏(测试运⾏), 作⽤ 是⽤例执⾏TestSuite(测试套件)的
4. TestLoader
测试加载, 是对 TestSuite(测试套件) 功能的补充, 作⽤是⽤来组装(打包) TestCase(测试⽤例) 的
方法一:一个用例一个用例的添加。 suite.addTest(ClassName(“MethodName”))
方法二:一次添加一个类所有用例。suite.addTest(unittest.makeSuite(ClassName))
方法三:自动搜索所有用例,全部填充。suite = unittest.TestLoader().discover(‘.’, ‘hm_02*.py’)
# 1. 导包 unittestimport unittestfrom hm_02_testcase1 import TestDemo1from hm_02_testcase2 import TestDemo2# 2. 实例化套件对象 unittest.TestSuite()suite = unittest.TestSuite()# 3. 添加用例方法# 3.1 套件对象.addTest(测试类名('测试方法名')) # 建议复制suite.addTest(TestDemo1('test_method1'))suite.addTest(TestDemo1('test_method2'))# 3.2 添加整个测试类# 套件对象.addTest(unittest.makeSuite(测试类名)) # 在不同的 Python 版本中,可能没有提示suite.addTest(unittest.makeSuite(TestDemo2))# 3.3一次搜寻并添加所有用例# suite = unittest.TestLoader().discover('用例所在的目录', '用例代码文件名*.py')# 4. 实例化 执行对象 unittest.TextTestRunner()runner = unittest.TextTestRunner()# 5. 执行对象执行 套件对象 执行对象.run(套件对象)runner.run(suite)# 1. 导包 unittest import unittest from hm_02_testcase1 import TestDemo1 from hm_02_testcase2 import TestDemo2 # 2. 实例化套件对象 unittest.TestSuite() suite = unittest.TestSuite() # 3. 添加用例方法 # 3.1 套件对象.addTest(测试类名('测试方法名')) # 建议复制 suite.addTest(TestDemo1('test_method1')) suite.addTest(TestDemo1('test_method2')) # 3.2 添加整个测试类 # 套件对象.addTest(unittest.makeSuite(测试类名)) # 在不同的 Python 版本中,可能没有提示 suite.addTest(unittest.makeSuite(TestDemo2)) # 3.3一次搜寻并添加所有用例 # suite = unittest.TestLoader().discover('用例所在的目录', '用例代码文件名*.py') # 4. 实例化 执行对象 unittest.TextTestRunner() runner = unittest.TextTestRunner() # 5. 执行对象执行 套件对象 执行对象.run(套件对象) runner.run(suite)# 1. 导包 unittest import unittest from hm_02_testcase1 import TestDemo1 from hm_02_testcase2 import TestDemo2 # 2. 实例化套件对象 unittest.TestSuite() suite = unittest.TestSuite() # 3. 添加用例方法 # 3.1 套件对象.addTest(测试类名('测试方法名')) # 建议复制 suite.addTest(TestDemo1('test_method1')) suite.addTest(TestDemo1('test_method2')) # 3.2 添加整个测试类 # 套件对象.addTest(unittest.makeSuite(测试类名)) # 在不同的 Python 版本中,可能没有提示 suite.addTest(unittest.makeSuite(TestDemo2)) # 3.3一次搜寻并添加所有用例 # suite = unittest.TestLoader().discover('用例所在的目录', '用例代码文件名*.py') # 4. 实例化 执行对象 unittest.TextTestRunner() runner = unittest.TextTestRunner() # 5. 执行对象执行 套件对象 执行对象.run(套件对象) runner.run(suite)
5. Fixture
对一个测试用例环境的初始化和销毁。测试夹具, 是⼀种代码结构, 书写 前置⽅法(执⾏⽤例之前的⽅法)代码 和后置⽅法(执⾏⽤例之后的⽅法) 代码 ,即⽤例执⾏顺序 前置 —> ⽤例 —> 后置
方法级别
def setUp(self): # 前置# 每个⽤例执⾏之前都会⾃动调⽤passdef tearDown(self): # 后置# 每个⽤例执⾏之后 都会⾃动调⽤pass# ⽅法前置 ⽤例 ⽅法后置# ⽅法前置 ⽤例 ⽅法后置def setUp(self): # 前置 # 每个⽤例执⾏之前都会⾃动调⽤ pass def tearDown(self): # 后置 # 每个⽤例执⾏之后 都会⾃动调⽤ pass # ⽅法前置 ⽤例 ⽅法后置 # ⽅法前置 ⽤例 ⽅法后置def setUp(self): # 前置 # 每个⽤例执⾏之前都会⾃动调⽤ pass def tearDown(self): # 后置 # 每个⽤例执⾏之后 都会⾃动调⽤ pass # ⽅法前置 ⽤例 ⽅法后置 # ⽅法前置 ⽤例 ⽅法后置
类级别
# 类级别的 Fixture 需要写作类⽅法@classmethoddef setUpClass(cls): # 类前置pass@classmethoddef tearDownClass(cls): # 后置pass# 类前置 ⽅法前置 ⽤例 ⽅法后置 ⽅法前置 ⽤例 ⽅法后置类后置# 类级别的 Fixture 需要写作类⽅法 @classmethod def setUpClass(cls): # 类前置 pass @classmethod def tearDownClass(cls): # 后置 pass # 类前置 ⽅法前置 ⽤例 ⽅法后置 ⽅法前置 ⽤例 ⽅法后置类后置# 类级别的 Fixture 需要写作类⽅法 @classmethod def setUpClass(cls): # 类前置 pass @classmethod def tearDownClass(cls): # 后置 pass # 类前置 ⽅法前置 ⽤例 ⽅法后置 ⽅法前置 ⽤例 ⽅法后置类后置
模块级别
# 在类外部定义函数def setUpModule():passdef tearDownModule():pass# 在类外部定义函数 def setUpModule(): pass def tearDownModule(): pass# 在类外部定义函数 def setUpModule(): pass def tearDownModule(): pass
案例实现:
import unittestclass TestLogin(unittest.TestCase):def setUp(self) -> None:print('2. 打开网页, 点击登录')def tearDown(self) -> None:print('4. 关闭网页')@classmethoddef setUpClass(cls) -> None:print('1. 打开浏览器')@classmethoddef tearDownClass(cls) -> None:print('5. 关闭浏览器')def test_1(self):print('3. 输入用户名密码验证码1,点击登录 ')def test_2(self):print('3. 输入用户名密码验证码2,点击登录 ')def test_3(self):print('3. 输入用户名密码验证码3,点击登录 ')import unittest class TestLogin(unittest.TestCase): def setUp(self) -> None: print('2. 打开网页, 点击登录') def tearDown(self) -> None: print('4. 关闭网页') @classmethod def setUpClass(cls) -> None: print('1. 打开浏览器') @classmethod def tearDownClass(cls) -> None: print('5. 关闭浏览器') def test_1(self): print('3. 输入用户名密码验证码1,点击登录 ') def test_2(self): print('3. 输入用户名密码验证码2,点击登录 ') def test_3(self): print('3. 输入用户名密码验证码3,点击登录 ')import unittest class TestLogin(unittest.TestCase): def setUp(self) -> None: print('2. 打开网页, 点击登录') def tearDown(self) -> None: print('4. 关闭网页') @classmethod def setUpClass(cls) -> None: print('1. 打开浏览器') @classmethod def tearDownClass(cls) -> None: print('5. 关闭浏览器') def test_1(self): print('3. 输入用户名密码验证码1,点击登录 ') def test_2(self): print('3. 输入用户名密码验证码2,点击登录 ') def test_3(self): print('3. 输入用户名密码验证码3,点击登录 ')
用例执行顺序
是按test*后面的字符排序。比如a-b1-9这样,不是按照编写顺序执行。
下面用例,test_a02比test_b01先执行。