ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

unittest简要解析

2022-06-29 18:36:17  阅读:189  来源: 互联网

标签:10 简要 unittest 用例 suite 解析 self def


一、unittest是什么?

  unittest是python内置的单元测试框架,具备编写用例、组织用例、执行用例、输出报告等自动化框架的条件。
  使用unittest前需要了解该框架的几个概念:
  即TestCase、TestSuite、TestLoader、TestRunner、TestFixture等

 

  1、TestCase

    一个完整的测试单元,执行该测试单元可以完成对某一个问题的验证,是所有用例类的父类,用例类需继承它才可被 unittest 发现并执行,例:

 1 import unittest
 2 
 3 
 4 def compare(a, b):  # 待测试方法
 5     return a > b
 6 
 7 
 8 def divide(a, b):  # 待测试方法
 9     return a / b
10 
11 
12 
13 class TestA(unittest.TestCase):  # 用例类需继承TestCase
14 
15     def setUp(self) -> None:
16         print('用例执行前的处理')
17 
18     def tearDown(self) -> None:
19         print('用例执行后的处理')
20 
21     def test_1(self):  # 测试用例
22         self.assertTrue(compare(10, 10))
23 
24     def test_2(self):  # 测试用例
25         self.assertFalse(10, 0)
26 
27 
28 if __name__ == '__main__':  
29     unittest.main()  # 执行当前类的所有测试用例

 

  2、TestSuite

    测试套件,看作是多个用例的集合(容器),例:

    

1 def create_suite():
2     suite = unittest.TestSuite()    # 创建suite
3     suite.addTest(TestA("test_1"))  # 往suite里添加用例
4     suite.addTest(TestA("test_2"))  # 往suite里添加用例
5 
6     return suite    # 返回添加完用例的suite

    如何执行这个容器下文介绍

 

  3、TestLoader

    测试加载,该类用来寻找 test case 并将其加载到 test suite 中,提供了以下几种方法寻找(发现)test case,如下:

    

    unittest.TestLoader().loadTestsFromTestCase(testCaseClass)
      
testCaseClass: 必须是 TestCase 的子类或孙类

    unittest.TestLoader().loadTestsFromModule(module, pattern)
      model:TestCase(用例)所在模块
      pattern:str 类型,发现用例的规则,默认发现 test 开头的用例

    unittest.TestLoader().loadTestsFromName(name)
      name:str 类型,格式要求为 "model.class.method"

    unittest.TestLoader().loadTestsFromNames(names)
      names:list 类型, 格式要求同上

    unittest.TestLoader().discover(path_dir, pattern, top_level_dir)
      path_dir:str 类型,TestCase 文件路径
      pattern:同上
      top_level_dir:str 类型,TestCase 的顶层目录,默认为 None

    实际运用:
 1 def create_suite():
 2     path = r'D:\pythonworkspace\unittest_exercise'
 3 
 4     suite = unittest.TestSuite()    # 创建suite
 5 
 6     # 发现指定路径的用例, 并返回一个 testCaseClass
 7     discover = unittest.defaultTestLoader.discover(path)  # 等同于 discover = unittest.TestLoader().discover(path)
 8 
 9     # 将 discover 中的用例循环添加到 suite 中
10     for testCases in discover:
11         for testCase in testCases:
12             suite.addTest(testCase)
13 
14     return suite    # 返回添加完用例的suite

 

  4、TestRunner

     测试执行器,执行 suite 中的用例,并将结果保存到 TextTestResult 实例中,例:

1 if __name__ == '__main__':  # 执行当前类的所有测试用例
2     suite = unittest.TestSuite()
3     cases = unittest.TestLoader().loadTestsFromName("unittest_exercise.unit_exercise.TestA")
4 
5     for case in cases:
6         suite.addTest(case)
7 
8     runner = unittest.TextTestRunner()  # 创建 runner 实例
9     runner.run(suite)  # 执行 suite 中的用例

 

 

  5、TestFixture

    测试夹具,用于测试用例执行前后的位置,根据适用范围,分为以下级别:

    方法级:

      def  setUp(self):  -->会在每个测试用例方法前自动执行

      def  tearDown(self):  -->会在每个测试用例方法后执行

      例:

 1 import unittest
 2 
 3 
 4 def compare(a, b):  # 待测试方法
 5     return a > b
 6 
 7 
 8 def divide(a, b):  # 待测试方法
 9     return a / b
10 
11 
12 class TestA(unittest.TestCase):
13 
14     def setUp(self) -> None:
15         print('用例执行前的处理')
16 
17     def tearDown(self) -> None:
18         print('用例执行后的处理')
19 
20     def test_1(self):  # 测试用例
21         self.assertTrue(compare(10, 10))
22 
23     def test_2(self):  # 测试用例
24         self.assertFalse(divide(10, 0))
25 
26 
27 if __name__ == '__main__':  # 执行当前类的所有测试用例
28     unittest.main()

    

  执行结果:可看到执行了两次,因为有两个测试用例

 

 

 

    类级:

      表示每个测试类只会执行一次 TestFixture 方法,例:

 1 class TestA(unittest.TestCase):
 2 
 3     @classmethod
 4     def setUpClass(cls) -> None:
 5         print('用例执行前的处理')
 6 
 7     @classmethod
 8     def tearDownClass(cls) -> None:
 9         print('用例执行后的处理')
10 
11     def test_1(self):  # 测试用例
12         self.assertTrue(compare(10, 10))
13 
14     def test_2(self):  # 测试用例
15         self.assertFalse(divide(10, 0))

  

     执行后的结果:可见该测试类执行时,只执行一次TestFixture 方法

 

 

 

    模块级:

      def setUpModule()  

      def setUpModule()

      和上述一样的用法,这里不再赘述

 

  6、其他

    (1)HTML版的测试报告

        具体实现如下:(因 HTMLTestRunner 比较麻烦,这里采用的是 BeautifulReport 

        ① 先导入 BeautifulReport (BeautifulReport要先下载,不过也可以先写上如下代码,然后凭借 pycharm 下载即可)

         1 from BeautifulReport import BeautifulReport 

  

        ②  result = BeautifulReport(createSuite()) # 创建测试套件容器   这里的 creatSuite() 返回的是 suite 实例

           result.report(filename=now + 'GAD_smoke', description='GAD冒烟测试', report_dir=filename) # 生成测试报告 

        参数:

          filename:生成报告的文件名

          description:生成报告的注释

          report_dir:生成报告的存储路径

 

    (2)测试用例执行顺序:

          默认按照 ASCII 码值排序

          也可以写一个类继承 TestLoader 类,重写其中的排序方法,以达到排序的目的(没试过,记录一下,哈哈)

 

    (3)断言

        一种检查实际结果与期望结果关系的方式,常见的几种断言方式如下:

        assertEqual(a, b)    a=b 则返回 True

        assertNotEqual(a, b)    a=b 则返回 False

        assertTrue(exp)    表达式为True 则返回 True

        assertFalse(exp)    表达式为True 则返回 False

        assertIs(a, b)    a is b 则返回 True

        assertIsNot(a, b)    a is b 则返回 Fasle

        ......更多可以查看 TestCase 类的源码

        

    (4)装饰器 skip、skipIf、skipUnless

        skip 使用方式:在用例方法上使用以下装饰器

          @unittest.skip(reason='')    # 表示跳过该测试用例,reason:跳过原因
             def test_1(self):  # 测试用例
                self.assertTrue(compare(10, 10))

  

        skipIf :

          @unittest.skipIf(condition='布尔表达式', reason='')  # 表达式为 True 则跳过该用例
              def test_1(self):  # 测试用例
                  self.assertTrue(compare(10, 10))

  

        skipUnless: 

          @unittest.skipUnless(condition='布尔表达式', reason='')  # 表达式为 True 则执行该用例
             def test_1(self):  # 测试用例
                self.assertTrue(compare(10, 10))

  

        扩展:expectedFailure

          @unittest.expectedFailure    # 预期失败,即该用例执行失败时不会算作失败
              def test_1(self):  # 测试用例
                  self.assertTrue(compare(10, 10))

  

    (5)参数驱动 ddt(亲测可行)

          老规矩第一步先引入 ddt,

            from ddt import file_data, ddt    # file_data 接收外部 yaml 文件会用到

  

          第二步,在测试类上使用 @ddt, 如:

            @ddt
            class test_Login(unittest.TestCase):

  

          第三步,在测试用例方法上使用 file_data,如:

1 @file_data(UniversalMethod.get_path() + 'data\\user_login.yaml')    # 括号内是 yaml 文件的路径
2     def test_login(self, **kwargs):
3         print(kwargs)
4         error_text = self.login_page.login_GAD(kwargs['username'], kwargs['password'])  # 接收 yaml 文件内的参数
5         self.assertFalse(error_text is not None, msg=error_text)  # 如果错误信息存在,则登录失败,输出错误提示信息

 

          yaml文件格式:

       

 

 

    

二、实例

  实例可参见我另一篇文章,地址

 

  各方收集加上自己的理解,若有不正之处,欢迎指出

标签:10,简要,unittest,用例,suite,解析,self,def
来源: https://www.cnblogs.com/cicadaLuo/p/16424161.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有