其他分享
首页 > 其他分享> > unittest简要解析

unittest简要解析

作者:互联网

一、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