• Python下unittest框架的核心组件使用


            前言:在接口/UI自动化中,unittest框架或多或少也听到过,流行的框架我们需要重点去学习及掌握,接下来就一起来学习下吧

     

    一、unittest核心组件

    1、TestCase:测试用例类,用来定义测试用例函数的

    2、TestSuite:测试套件,用来收集测试用例的

    3、TestRunner:测试用例运行类,用来执行测试用例的,以测试套件维度去执行

    4、TestFixture:测试脚手架,前置条件,后置处理

    二、测试流程--unittest你是如何做自动化测试的

    1、TestCase:先定义测试用例类,在测试用例类中写测试方法

    2、TestSuite:收集你要执行的测试用例类或者文件里面的测试方法,放到测试套件

    3、TestRunner:将收集好的测试条件放到测试用例运行器去执行,并收集测试结果

    4、TestFixture:做好前置条件和后置处理

    三、如何写测试用例(TestCase)

    1、导入模块:import unittest,继承TestCase类

    2、定义一个测试用例类:类名称必须Test开头

    3、定义测试方法:测试方法也必须是test开头,必须写在测试用例类里面

    4、框架执行入口:unittest.main(),自动收集当前py文件的测试用例,然后执行

    四、测试用例包含哪些东西

    1、前置条件(如果没有可以不写):sql语句执行、数据库连接创建、工具类的实例化

    2、测试步骤(业务逻辑):数据替换、数据驱动

    3、测试结果断言:响应结果断言、数据库数据断言

    4、后置处理(如果没有可以不写):数据清理、数据库连接关闭

    五、前置后置(TestFixture)

    自动化中什么是前置后置?

    答:前置:sql语句执行、数据库连接创建、工具类的实例化
           后置:数据清理、数据库连接关闭

    a) 类级别(以类级别的运行)

    1. 一、类级别(以类级别的运行)
    2. 前置:测试用例执行之前执行一次(当前测试用例类) ——
    3. @classmethod
    4. def setUpClass(cls) -> None:(固定写法,必须加@classmethod,源码就是加了)
    5. 后置:测试用例执行之后执行一次(当前测试用例类)——
    6. @classmethod
    7. def tearDownClass(cls) -> None: (固定写法,必须加@classmethod,源码就是加了)
    8. 解释:
    9. 类级别的前后置就是,比如你的测试用例有3条,那就每一条用例都会去执行前后置,
    10. 执行顺序:前置,第一条用例,第二条用例,后置

    a) 示例:类级别

    1. #例子:
    2. class Test_class_setup(unittest.TestCase): #前置后置都需要类继承unittest.TestCase
    3. @classmethod #类级别的前置 必须加@classmethod
    4. def setUpClass(cls) -> None:
    5. print("我是类级别的前置")
    6. @classmethod
    7. def tearDownClass(cls) -> None: #类级别的后置 必须加@classmethod 这里后置放哪里都可以 你也可以放到最后一条用例后面去。
    8. print("我是类级别的后置")
    9. def test_01(self):
    10. print("用例001")
    11. def test_02(self):
    12. print("用例002")
    13. def test_03(self):
    14. print("用例003")
    15. if __name__ == '__main__':
    16. unittest.main()

    b) 函数级别(以函数级别的运行)

    1. 二、函数级别(以函数级别的运行)
    2. 前置:每个测试用例执行之前执行一次 —— def setUp(self) -> None: (固定写法)
    3. 后置:每个测试用例执行之后执行一次 —— def tearDown(self) -> None:(固定写法)
    4. 解释:
    5. 函数级别的前后置就是,比如你的测试用例有3条,那就每一条用例都会去执行前后置,
    6. 执行顺序:前置,第一条用例,后置;前置 ,第二条用例,后置

    b) 示例:函数级别

    1. 例子:
    2. class Test_setp(unittest.TestCase): #前置后置都需要类继承unittest.TestCase
    3. def setUp(self) -> None:#这里-> None是表示前置是没有返回值的
    4. print("我是函数级别的前置")
    5. def test_01(self): #中间可以放测试用例
    6. print("我是测试用例01")
    7. def tearDown(self) -> None:#这里-> None是表示后置是没有返回值的
    8. print("我是函数级别的后置")
    9. if __name__ == '__main__':
    10. unittest.main()

    六、前置后置(TestFixture)

    1、用例执行按照Ascii码顺序:0-9

     

    #打印对应字符的ascii码
    print(ord("a"))  #97

    #将ascii转换为对应的字符
    print(chr(102))

    七、用例断言(继承TestCase类的断言方法)

    断言的特点:
    1、unittest以程序运行过程中是否抛出异常来判断用例是否执行成功
    2、如果断言失败程序会抛出异常,框架就会把这个用例标记为失败
    3、只要你的程序中执行出现了其他异常,框架也会去捕获异常并将用例标记为失败

    例:self.assertEqual(1,1) 断言是否相等

    unitest常见断言:

    1. 常见断言(unitest独有,pytest没有):
    2.     1、assertEqual(a, b)
    3.     # a == b
    4.     '''self.assertEqual(1 + 1, 2)#实际结果、预期结果是否相等'''
    5.     2、assertNotEqual(a, b)
    6.     # a != b
    7.     '''self.assertNotEqual(1, 2)#实际结果、预期结果是否不相等'''
    8.     3、assertTrue(x)
    9.     # bool(x) is True
    10.     '''self.assertTrue([1,2,3])#任何为真的表达式 非0 非空 true'''
    11.     4、assertFalse(x)
    12.     # bool(x) is False
    13.     '''self.assertFalse(0)#任何为假的表达式 0 空 false'''
    14.     5、assertIs(a, b)
    15.     # a is b
    16.     '''self.assertIs(1,1)#is身份运算符,a 是和 b引用自同一个对象'''
    17.     6、assertIsNot(a, b)
    18.     # a is not b
    19.     '''self.assertIsNot(1,2)#is not身份运算符,a 和 b不是引用自同一个对象'''
    20.     7、assertIn(a, b)
    21.     # a in b
    22.     '''self.assertIn(1,[1,2,3])#in成员运算符,a是b中一员,a在b中'''
    23.     8、assertNotIn(a, b)
    24.     # a not in b
    25.     '''self.assertNotIn(2,[1,3,4])#in成员运算符,a不是b中一员,a不在b中'''
    26.     9、assertIsInstance(a, b)
    27.     # isinstance(a, b)
    28.     '''self.assertIsInstance(123,int)#isinstance判断一个对象是否属于某个类或类型'''
    29.     10、assertNotIsInstance(a, b)
    30.     # not isinstance(a, b)
    31.     '''self.assertNotIsInstance([1,2,3],dict)#not isinstance判断一个对象不是否属于某个类或类型'''
    32.     11、assertGreater(a, b)
    33.     # a > b
    34.     '''self.assertGreater(5,2)#Greater判断a是否大于b'''
    35.     12、assertGreaterEqual(a, b)
    36.     # a >= b
    37.     '''self.assertGreaterEqual(5,5)#GreaterEqual判断a是否大于等于b'''
    38.     13、assertLess(a, b)
    39.     # a < b
    40.     '''self.assertLess(1,4)#less判断a是否小于b'''
    41.     14、assertLessEqual(a, b)
    42.     # a <= b
    43.     self.assertLessEqual(2,2)#less判断a是否小于等于b

    unitest断言示例:

    1. 例子:
    2. 测试用例中:
    3. def test_03(self):
    4. print("用例003")
    5. self.assertEqual(1+1,3)#实际结果、预期结果是否相等,如:1+1的值 是否 等于3——这里错了后,会报错,用例执行就会不通过

    八、异常捕获与异常抛出

    try...except 捕获到的异常一定要抛出来给框架,否则框架就会认为用例执行成功的

    异常捕获示例:

    1. 2、手动抛异常:raise AssertionError(e)
    2. def test_03(self):
    3. try:
    4. time.sleep(1)
    5. self.assertEqual(1,2)
    6. print("测试用例03")
    7. except Exception as e:
    8. # print("错误原因:",e)
    9. raise AssertionError(e)
    10. def test_03(self):
    11. try:
    12. self.assertEqual(1,2)
    13. print("用例003")
    14. except Exception as e:
    15. raise AssertionError(e)

    九、用例的收集(TestSuite)

    a) 测试用例维度【了解】

    1. 添加一个测试用例
    2. suite.addTest(TestDemo("test_04"))
    3. 添加多个测试用例
    4. tests = [TestDemo("test_04"),TestDemo("test_02")]
    5. suite.addTests(tests)

    a) 示例:测试用例维度

    1. 添加单条用例:
    2. from day16.unnitest_demo1 import Test_class_setup #先导入测试用例
    3. import unittest#导入unitest库
    4. suite = unittest.TestSuite() #创建测试套件进行收集用例
    5. suite.addTest(Test_class_setup("test_01")) #添加测试用例到套件内,这里是测试用例为单位
    6. run_now = unittest.TextTestRunner() #创建执行器
    7. run_now.run(suite) #执行器中添加测试套件后 进行运行
    8. 添加多条用例:
    9. from day16.unnitest_demo1 import Test_class_setup #先导入测试用例
    10. import unittest#导入unitest库
    11. suite = unittest.TestSuite() #创建测试套件进行收集用例
    12. case = [Test_class_setup("test_01"),Test_class_setup("test_02")] #多条测试用例,用[]装起来也可以
    13. suite.addTests(case) # 多条用addTests
    14. run_now = unittest.TextTestRunner() #创建执行器
    15. run_now.run(suite) #执行器中添加测试套件后 进行运行

    b) 测试类维度【了解】

    添加某个测试类(类里面所有的测试用例都会被执行)
    suite.addTest(unittest.makeSuite(TestDemo))

    当只要执行py文件中多个测试用例中的几个,而不是全部执行时,那么使用testsuite的addtest方法加载指定的测试用例

    当执行所有的py文件中的所有的测试用例时,那么使用TestLoader

    b) 示例:测试类维度

    1. 添加测试类级别的用例:
    2. from day17.wjh_test import Test_wjh
    3. import unittest
    4. suite = unittest.TestSuite() #实施例套件
    5. test_case = unittest.TestLoader().loadTestsFromTestCase(Test_wjh)
    6. #用这个方法,Python3不能用unittest.makeSuite(TestDemo)
    7. #TestLoader:可以从指定目录查找指定的py文件中的所有测试用例,自动加载到TestSuite中
    8. suite.addTest(test_case)
    9. run1 = unittest.TextTestRunner()
    10. run1.run(suite)

    c) 模块为维度【掌握】

    start_dir:测试文件目录
    pattern='test*.py':测试用例文件名称,默认以test开头的py文件
    case_dir = os.path.dirname(__file__)
    suite = unittest.defaultTestLoader.discover(start_dir=case_dir)#指定某个目录下的某一类py文件进行运行,且运行所有测试用例

    c) 示例:模块为维度

    1. 添加测试模块(用例文件)维度的用例————重点重点重点:
    2. # 3、模块为维度【掌握】
    3. # start_dir:测试文件目录
    4. # pattern='test*.py':测试用例文件名称,默认以test开头的py文件
    5. # case_dir = os.path.dirname(__file__)
    6. # suite = unittest.defaultTestLoader.discover(start_dir=case_dir)
    7. import os
    8. from day17.wjh_test import Test_wjh #导入测试用例
    9. from day17.wjh_test import Test_wjh01#导入测试用例
    10. import unittest
    11. case_dir = os.path.dirname(__file__) #当前目录路径
    12. suite = unittest.defaultTestLoader.discover(start_dir=case_dir,pattern='wjh_start*.py')
    13. #start_dir是函数中的参数,指:start_dir
    14. #pattern是函数中的参数,指的:如(pattern='test*.py':测试用例文件名称,默认以test开头的py文件)
    15. #默认可以不加pattern的参数,如果不加。他就默认找目录中 test文件开头py文件中的测试用例执行
    16. run1 = unittest.TextTestRunner()#TextTestRunner执行的是TestSuite
    17. run1.run(suite)

    c) TextTestRunner  和 TestRunner()  区别

    TextTestRunner  和 TestRunner()  区别,因为这里很多人以为这两者都是unitest的执行器

    TextTestRunner:是执行TestSuite,也就是测试套件的用例
    TestRunner():执行生成测试报告

    十、数据驱动:DDT

    数据驱动

    一、什么叫数据驱动?
    1、业务流程是固定的,变化的是业务中的数据
    2、使用场景:业务流程一样,只是请求数据不一样

    准备工作:

    安装ddt(unitest自带的ddt驱动方式)
    pip install ddt

    安装ddt(unittestreport第三库(木森大佬写的))
    pip install unittestreport

    a)unitest自带的ddt驱动方式

    1. unitest自带的ddt驱动方式——例子:
    2. import unittest
    3. from ddt import ddt,data #导入ddt和data
    4. test_cases = [{"api":"/api/login","user":"admin"},{"api":"/api/login","user":"test"}] #列表嵌套字典
    5. @ddt #语法糖,使用ddt装饰器
    6. class Test_login(unittest.TestCase):#同样需要继承unittest.TestCase
    7. @data(*test_cases) #这里@data()表示需要添加数据进去,@data(*test_cases) 之所以加*号,是因为要解包,test_cases是列表嵌套字典
    8. def test_01(self,data): #这里一定主要 需要把数据驱动的变量添加进来,比如这里的data
    9. print("驱动")
    10. print(data["api"])#这里随便插一句,所有运行时,鼠标光标放在类外面去,不然会报错,这是个大坑,unitest垃圾!
    11. if __name__ == '__main__':
    12. unittest.main()

    b)unittestreport第三库(木森大佬写的)驱动方式

    1. unittestreport(森哥)三方库的数据驱动
    2. import unittest
    3. from unittestreport import ddt,list_data #list_data是这个库的专门名字,主要就是为了省去解包的步骤,下面我们有讲解
    4. test_cases = [{"api":"/api/login","user":"admin"},{"api":"/api/login","user":"test"}] #列表嵌套字典
    5. @ddt #语法糖,使用ddt装饰器
    6. class Test_login(unittest.TestCase):#同样需要继承unittest.TestCase
    7. @list_data(test_cases) #@list_data()表示需要添加数据进去,这里不需要再解包上面的数据,因为@list_data有解包动作
    8. def test_01(self,data): #这里一定主要 需要把数据驱动的变量添加进来,比如这里的data
    9. print("驱动")
    10. print(data["api"])#这里随便插一句,所有运行时,鼠标光标放在类外面去,不然会报错,这是个大坑,unitest垃圾!
    11. if __name__ == '__main__':
    12. unittest.main()

    十一、unittestreport测试报告,并发送邮件

    a) unitest自带测试报告——不推荐,丑,不好用

    1、BeautifulReport(unitest官网自带的报告)
          pip install BeautifulReport==0.1.3

    b) unittestreport :木森自研(重点掌握)

       unittestreport 使用文档unittestreport 使用文档unittestreport 使用文档:https://unittestreport.readthedocs.io/en/latest/doc8_thread/
       安装unittestreport:pip install unittestreport

    b) 示例:unittestreport

    1. 实例:
    2. import unittest
    3. from unittestreport import TestRunner#导入测试报告模块
    4. case_dir = os.path.dirname(__file__) #当前目录路径
    5. suite = unittest.defaultTestLoader.discover(start_dir=case_dir)#pattern='wjh_start*.py' #收集用例
    6. runner = TestRunner( #实例化测试报告模块,填写相关信息
    7. suite=suite,
    8. filename="my_report.html",
    9. report_dir="./reports",
    10. title='测试报告',
    11. tester='小阿卷',
    12. desc="接口自动化项目测试报告",
    13. templates=3
    14. )
    15. runner.run()
    16. runner.send_email(
    17. host="smtp.qq.com",
    18. port=465,
    19. user="123456@qq.com",
    20. password="123123",
    21. to_addrs=["123456@qq.com"]
    22. )
  • 相关阅读:
    远距离WiFi模组方案,实现移动设备之间高效通信,无人机远程图传应用
    混合馈能悬架的设计与仿真(MATLAB)
    vue3 + antd + typeScript 封装一个高仿的ProTable
    【Win10】windows time(w32time)服务自启动不起作用的解决方法
    学会Redis这一篇就够了(1)
    应届生该怎么学习Java,如何快速通过面试?
    uniapp微信小程序_拍照从相册选择
    亚马逊、wish、temu如何掌握自养号测评技术?
    电子元器件的结温壳温与环境温度经验总结
    【概率论与数理统计(研究生课程)】知识点总结4(随机变量的数字特征)
  • 原文地址:https://blog.csdn.net/qq_41130705/article/details/126328576