• Selenium3+python自动化010-UnitTest框架简介和单元测试框架使用


    一、UnitTest介绍

    unittest单元测试框架不仅可以适用于单元测试,还可以适用WEB自动化测试用例的开发与执行,该测试框架可组织执行测试用例,并且提供了丰富的断言方法,判断测试用例是否通过,最终生成测试结果。

    1.1、为什么使用UnitTest框架?

    1. 能够组织多个用例去执行。

    2. 提供丰富的断言方法。

    3. 提供丰富的日志与测试结果。

    1.2、如何使用UnitTest框架

    1. 导包:import unittest             --> 导入unitest框架。

    2. 继承:unittest.TestCase             --> 新建测试类需继承unittest.TestCase。

    3.如果需要使用unittest的方法,需要重写该方法,如:setUp()、teraDown()、setUpClass()、tearDownClass。

     

    二、unittest单元测试框架使用

    1、TestCase类中定义的几个特殊方法

    (1)setUp():每个测试方法运行前运行,测试前的初始化工作。

        def setUp(self):
            self.a = 3
            self.b = 1
            print("查看setUp()方法执行顺序")
    # @Author:lsj
    # @version V1.0
    # -*- coding:UTF-8 -*-
    
    import unittest
    # 被测试类
    class myclass(object):
        @classmethod  # 装饰器
        def sum(cls,a,b):
            return a + b  # 将两个传入参数进行加粗操作
        @classmethod
        def sub(cls,a,b):
            return a - b  # 将两个传入参数进行相减
    
    # 测试类
    class mytest(unittest.TestCase):
        def setUp(self):
            self.a = 3
            self.b = 1
            print("查看setUp()方法执行顺序")
        def testsum(self):
            # 断言:两个数之和是否为4
            self.assertEqual(myclass.sum(self.a,self.b),4,'test sum fail')
            print("testsum方法")
        def testsub(self):
            # 断言两个数之差的结果是否为2
            self.assertEqual(myclass.sub(self.a,self.b),2,'test sub fail')
            print('testsub方法')
    if __name__=='__main__':
        unittest.main()
    setUp()的执行顺序
    "D:Program FilesPython36python.exe" D:/pycharm/qianyan/test_case/unitestshili.py
    查看setUp()方法执行顺序
    testsub方法
    查看setUp()方法执行顺序
    testsum方法
    ..
    ----------------------------------------------------------------------
    Ran 2 tests in 0.000s
    
    OK
    
    Process finished with exit code 0
    执行结果

     

    (2)tearDown():每个测试方法运行结束后运行,测试后的清理工作。

     1 # @Author:lsj
     2 # @version V1.0
     3 # -*- coding:UTF-8 -*-
     4 
     5 import unittest
     6 # 被测试类
     7 class myclass(object):
     8     @classmethod  # 装饰器
     9     def sum(cls,a,b):
    10         return a + b  # 将两个传入参数进行加粗操作
    11     @classmethod
    12     def sub(cls,a,b):
    13         return a - b  # 将两个传入参数进行相减
    14 
    15 # 测试类
    16 class mytest(unittest.TestCase):
    17     def setUp(self):
    18         self.a = 3
    19         self.b = 1
    20         print("查看setUp()方法执行顺序")
    21     def tearDown(self):
    22         print("查看tearDown()方法执行顺序")
    23     def testsum(self):
    24         # 断言:两个数之和是否为4
    25         self.assertEqual(myclass.sum(self.a,self.b),4,'test sum fail')
    26         print("testsum方法")
    27     def testsub(self):
    28         # 断言两个数之差的结果是否为2
    29         self.assertEqual(myclass.sub(self.a,self.b),2,'test sub fail')
    30         print('testsub方法')
    31 if __name__=='__main__':
    32     unittest.main()
    查看tearDown()状态
     1 "D:Program FilesPython36python.exe" D:/pycharm/qianyan/test_case/unitestshili.py
     2 ..
     3 ----------------------------------------------------------------------
     4 Ran 2 tests in 0.001s
     5 
     6 OK
     7 查看setUp()方法执行顺序
     8 testsub方法
     9 查看tearDown()方法执行顺序
    10 查看setUp()方法执行顺序
    11 testsum方法
    12 查看tearDown()方法执行顺序
    13 
    14 Process finished with exit code 0
    执行结果

     

    (3)setUpClass():所有的测试方法运行前运行,单元测试前期准备,必须使用 @classmethod装饰器进行修饰(装饰器的使用详见python),setUp()函数之前执行,整个测试过程只执行一次。比如:实例化浏览器、浏览器最大化、隐式等待设置

    (4)tearDownClass():所有的测试方法运行结束后执行,单元测试后期清理,必须使用 @classmethod装饰器进行修饰,tearDown()之后执行,整个测试过程只执行一次。

     1 # @Author:lsj
     2 # @version V1.0
     3 # -*- coding:UTF-8 -*-
     4 
     5 import unittest
     6 # 被测试类
     7 class myclass(object):
     8     @classmethod  # 装饰器
     9     def sum(cls,a,b):
    10         return a + b  # 将两个传入参数进行加粗操作
    11     @classmethod
    12     def sub(cls,a,b):
    13         return a - b  # 将两个传入参数进行相减
    14 
    15 # 测试类
    16 class mytest(unittest.TestCase):
    17     @classmethod
    18     def setUpClass(cls):
    19         print("查看setUpClass()方法执行顺序")
    20     @classmethod
    21     def tearDownClass(cls):
    22         print("查看tearDownClass()方法执行顺序")
    23     def setUp(self):
    24         self.a = 3
    25         self.b = 1
    26         print("查看setUp()方法执行顺序")
    27     def tearDown(self):
    28         print("查看tearDown()方法执行顺序")
    29     def testsum(self):
    30         # 断言:两个数之和是否为4
    31         self.assertEqual(myclass.sum(self.a,self.b),4,'test sum fail')
    32         print("testsum方法")
    33     def testsub(self):
    34         # 断言两个数之差的结果是否为2
    35         self.assertEqual(myclass.sub(self.a,self.b),2,'test sub fail')
    36         print('testsub方法')
    37 if __name__=='__main__':
    38     unittest.main()
    setUpClass和tearDownClass
    "D:Program FilesPython36python.exe" D:/pycharm/qianyan/test_case/unitestshili.py
    查看setUpClass()方法执行顺序
    查看setUp()方法执行顺序
    testsub方法
    查看tearDown()方法执行顺序
    查看setUp()方法执行顺序
    testsum方法
    查看tearDown()方法执行顺序
    查看tearDownClass()方法执行顺序
    ..
    ----------------------------------------------------------------------
    Ran 2 tests in 0.000s
    
    OK
    
    Process finished with exit code 0
    执行结果

      

    2、用例执行

     

    2.1、单一测试模块执行用例

    2.1.1、启动单元测试:使用unittest.main()方法 ,用例执行顺序是按照方法名的ASCII码升序排列的

     

     

    2.1.2、测试集合

    1)将功能相关的测试用例组合到一起成为一个测试用例集,unittest框架中通过TestSuite类来组装所有的测试用例集。(也就是说,使用测试集合可以同时执行同一个py文件中的多个测试用例类)

    2)TestLoader类:测试用例加载器,返回一个测试用例集合

    3)loadTestsFromTestCase类:根据给定的测试类,获取其中的所有以‘test’开头的测试方法,并返回一个测试集合

    4)TestSuite类:组装测试用例的实例,支持添加和删除用例,最后将传递给test runner进行测试执行

    5)TextTestRunner类:测试用例执行类,其中Text 表示以文本形式输出测试结果

     

    unittest运行错误:类名尽量不要用test/Test  

    问题:在执行文件的时候明明要执行一个类,却发现所有的类都被执行了。

    针对这一问题如下解决办法:edit configurations-->选中python-->增加或修改一条记录

     

     

    2.1.3、按照特定顺序执行测试用例

    1)获取 TestSuite的实例对象:suite=unittest.TestSuite()
    2)将测试用例添加到测试容器中
      suite.addTest(mytest("test_1sub"))
      suite.addTest(mytest("test_2sum"))
    3)创建TextTestRunner类的实例对象
      runner=unittest.TextTestRunner()
      runner.run(suite)

     1 # @Author:lsj
     2 # @version V1.0
     3 # -*- coding:UTF-8 -*-
     4 
     5 import unittest
     6 # 被测试类
     7 class myclass(object):
     8     @classmethod  # 装饰器
     9     def sum(cls,a,b):
    10         return a + b  # 将两个传入参数进行加粗操作
    11     @classmethod
    12     def sub(cls,a,b):
    13         return a - b  # 将两个传入参数进行相减
    14 
    15 # 测试类
    16 class mytest(unittest.TestCase):
    17     a = 3
    18     b = 1
    19     def test_2sum(self):
    20         # 断言:两个数之和是否为4
    21         self.assertEqual(myclass.sum(self.a,self.b),4,'test sum fail')
    22         print("test_2sum方法")
    23     def test_1sub(self):
    24         # 断言两个数之差的结果是否为2
    25         self.assertEqual(myclass.sub(self.a,self.b),2,'test sub fail')
    26         print('test_1sub方法')
    27 
    28 class aa(unittest.TestCase):
    29     def testaa(self):
    30         print('testaa')
    31 
    32 if __name__=='__main__':
    33     # 上面的代码可以替换成如下
    34     # 1)获取    TestSuite的实例对象:将多个测试类加载到集合中
    35     suite = unittest.TestSuite()
    36     # 2)将测试用例添加到测试容器中
    37     suite.addTest(mytest("test_2sum"))
    38     #  查看其执行顺序
    39     suite.addTest(aa('testaa'))
    40     suite.addTest(mytest("test_1sub"))
    41     # 3)创建TextTestRunner类的实例对象
    42     runner = unittest.TextTestRunner()
    43     runner.run(suite)
    View Code

     

     

    2.2、批量执行测试模块

     

    # 批量执行测试模块(一)
    # 加载当前目录下所有有效的测试模块,'.'表示当前目录
    # 默认加载以test开头的py模块
    # testSuite=unittest.TestLoader().discover('.')
    # unittest.TextTestRunner(verbosity=2).run(testSuite)

    # 批量执行测试模块(二)
    # 指定路径及模块关键字 (举例: ../report:表示上一级目录中的report文件夹)
    # 代码路径下,加载以lebo开头的py文件(*.py表示指定目录下所有以.py为后缀的文件)
    testSuite = unittest.TestLoader().discover(start_dir='.', pattern='lebo_*.py')
    unittest.TextTestRunner(verbosity=2).run(testSuite)

     

    目录下需要被执行的测试脚本文件名必须以“test”字符串开头,比如 testEqual.py

     

     

    2.3、忽略测试

    2.3.1、无条件忽略:@unittest.skip('skipping')

    2.3.2、有条件忽略:@unittest.skipIf(a>5,"condition is not satisfied!") 如果变量a大于5,则忽略该测试方法【表达式满足就跳过】

             @unittest.skipUnless(sys.platform=="linux","requires linux")如果执行测试用例的平台不是linux,则忽略测试方法【表达式不满足就跳过】

    class aa(unittest.TestCase):
        # num=2
        # @unittest.skip('skipping')
        # @unittest.skipIf(num>1,'num已经大于1')
        @unittest.skipUnless(sys.platform == "linux", "requires linux")
        def testaa(self):
            print('testaa')
    View Code

     

    3、测试结果

    3.1、. (点):执行成功,一个点表示一个测试方法。

     

    3.2、F:执行失败,如断言失败(输出日志中 failures=1表示一条用例执行失败)。

     

    3.3、E:用例本身有异常,如除数为零(输出日志中 errors=1表示一条用例异常)。

     

    3.4、skipped:有几条用例被跳过执行,verbosity=0,

     

    verbosity=1

    verbosity=2

     

    3.5、verbosity,日志输出情况

    3.5.1、verbosity<=0 ,输出结果中不提示执行成功的用例数。

     

    3.5.2、verbosity=1,输出结果中仅以点(.)表示执行成功的用例数。

     

    3.5.3、verbosity>=2,可以输出每条用例执行的详细信息,特别是在大批量执行测试用例时,可以根据这些信息判断哪些用例执行失败。

     

     

    4、断言

    # @Author:lsj
    # @version V1.0
    # -*- coding:UTF-8 -*-
    
    import unittest
    # print(unittest)
    # 被测试类
    class myclass(object):
        @classmethod  # 装饰器
        def sum(cls,a,b):
            return a + b  # 将两个传入参数进行加粗操作
        @classmethod
        def sub(cls,a,b):
            return a - b  # 将两个传入参数进行相减
    
    # 测试类
    class mytest(unittest.TestCase):
        a = 3
        b = 1
        # 具体的测试用例一定要以testk开头
        def testsum(self):
            # 断言:两个数之和是否为4
            myclass.sum(self.a,self.b)
            self.assertEqual(myclass.sum(self.a,self.b),4,'test sum fail')
            # 判断3和4是否相等,不相等报错test sum fail
            # self.assertEqual(3,4,'test sum fail')
            print("testsum方法")
        def testsub(self):
            # 断言两个数之差的结果是否为2
            self.assertEqual(myclass.sub(self.a,self.b),2,'test sub fail')
            print('testsub方法')
    
    if __name__=='__main__':
        unittest.main()
    View Code
    import unittest
    import random
    
    #被测试类
    class MyClass(object):
        @classmethod
        def sum(cls,a,b):
            return a + b   #将两个传入参数进行相加操作
        @classmethod
        def div(cls, a, b):
            return a / b   #将两个传入参数进行相除操作
    
        @classmethod
        def return_None(cls):
            return None
    
    # 单元测试类
    class MyTest(unittest.TestCase):
        # assertEqual 方法实例
        def test_assertEqual(self):
            # 断言两数之和的结果
            try:
                a,b=1,2
                sum=13
                # assertEqual断言相等
                self.assertEqual(a+b,sum,'断言失败,%s + %s !=%s' %(a,b,sum))
            except AssertionError as e:
                print(e)
    
        # assertNotEqual 方法实例
        def test_assertNotEqual(self):
            # 断言两数之差的结果
            try:
                a, b = 5,2
                res = 3
                # assertNotEqual断言不相等
                self.assertNotEqual(a - b, res, '断言失败,%s - %s =%s' % (a, b, res))
            except AssertionError as e:
                print(e)
    
        # assertTrue 方法实例
        def test_assertTrue(self):
            # 断言表达式为真
            try:
                self.assertTrue(1==2, "表达式为假")
            except AssertionError as e:
                print(e)
    
    
        # assertFalse 方法实例
        def test_assertFalse(self):
            # 断言表达式为假
            try:
                self.assertFalse(3==3, "表达式为真")
            except AssertionError as e:
                print(e)
    
        # assertIs 方法实例
        def test_assertIs(self):
            # 断言两个变量类型属于同一个对象
            try:
                a = 12
                b = a
                self.assertIs(a , b,'%s 与 %s 不属于同一个对象' % (a, b))
            except AssertionError as e:
                print(e)
    
        # assertIsNot 方法实例
        def test_assertIsNot(self):
            # 断言两个变量类型不属于同一个对象(同一个内存空间)
            try:
                a = 12
                b = 'test'
                self.assertIsNot(a , b,'%s 与 %s 属于同一个对象' % (a, b))
            except AssertionError as e:
                print(e)
    
        # assertIsNone 方法实例
        def test_assertIsNone(self):
            # 断言表达式结果为None
            try:
                result=MyClass.return_None()
                self.assertIsNone(result,'not is None')
            except AssertionError as e:
                print(e)
    
        # assertIsNotNone 方法实例
        def test_assertIsNotNone(self):
            # 断言表达式结果不为None
            try:
                result=MyClass.sum(2,5)
                self.assertIsNotNone(result,'is None')
            except AssertionError as e:
                print(e)
    
        # assertIn 方法实例
        def test_assertIn(self):
            # 断言对象A是否包含在对象B中
            try:
                strA="this is a test"
                strB="is"
                self.assertIn(strB,strA,'%s 不包含在 %s中' %(strB,strA))
            except AssertionError as e:
                print(e)
    
        # assertNotIn 方法实例
        def test_assertNotIn(self):
            # 断言对象A不包含在对象B中
            try:
                strA="this is a test"
                strB="Selenium"
                self.assertNotIn(strB,strA,'%s 包含在 %s中' %(strB,strA))
            except AssertionError as e:
                print(e)
    
    
    
    
    
    if __name__=="__main__":
        # 执行单元测试
        # unittest.main()
        testCase = unittest.TestLoader().loadTestsFromTestCase(MyTest)
        # 将多个测试类加载到测试集合中
        suite = unittest.TestSuite([testCase])
        unittest.TextTestRunner(verbosity=1).run(suite)
    View Code

     

     

     

     

  • 相关阅读:
    vim for python配置
    Python学习的一些好资料
    【Python开发实战】Python环境的配置
    【Python开发实战】Windows7+VirtualBox+Ubuntu环境配置
    linux下shapely的安装
    【python常用模块】os.path
    linux下gdal的python包的安装
    由二叉树的前序遍历和中序遍历,求其后序遍历
    ASCII码表
    C++标准库函数之排列函数
  • 原文地址:https://www.cnblogs.com/liunaixu/p/11096611.html
Copyright © 2020-2023  润新知