zoukankan      html  css  js  c++  java
  • python之unittest框架使用

    一、unittest框架

    unittest属于python内置的单元测试框架。

    二、unittest框架的核心概念

    test case:指测试用例。unittest中提供了一个基本类TestCase,可以用来创建新的测试用例;

    ​test fixture:测试夹具,用于测试用例环境的搭建和销毁。即用例测试前准备环境的搭建(SetUp前置条件),测试后环境的还原(TearDown后置条件),比如测试前需要登录获取token等就是测试用例需要的环境,运行完后执行下一个用例前需要还原环境,以免影响下一条用例的测试结果。(以及数据库的连接和断开等)

    test suite:测试套件,用来把需要一起执行的测试用例集中放到一块执行,相当于一个篮子。我们可以使用TestLoader来加载测试用例到测试套件中。

    test runner:用来执行测试用例的,并返回测试用例的执行结果。它还可以用图形或者文本接口,把返回的测试结果更形象的展现出来,如:HTMLTestRunner。

    三、unittest断言

    python中的assert断言,使用方法比较简单,即assert(表达式, 提示信息)

    而unittest框架中也提供了一个自带的断言方式,主要有以下几种:

    方法检查
    assertEqual(a, b,msg) a ==b
    assertNotEqual(a, b) a !=b
    assertTrue(x) bool(x) is True
    assertFalse(x) Bool(x) is False
    assertIs(a, b) a is b
    assertIsNot(a, b) a is not b
    assertIsNone(x) x is None
    assertIsNotNone(x) x is not None
    assertIn(a, b) a in b
    assertNotIn(a, b) a not in b
    assertIsInstance(a, b) isinstance(a,b)
    assertNotIsInstance(a, b) not isinstance(a,b)

    四、unittest核心概念详解

    1、TestCase测试用例:

    使用unittest编写用例,必须遵守以下规则:

    (1)测试类必须继承unittest.TestCase;

    (2)测试方法必须以“test”开头,且执行顺序会按照方法名的ASCII值排序,所以,写多个有关联的测试用例的时候请一定注意方法名称。

    2、TestFixture测试固件:

    unittest的测试固件有两种:

    (1)setUp()tearDown():在每条测试用例执行时都会先后执行一次该方法。

    (2)setUpClass()tearDownClass():在整个测试类中的所有用例执行前后,只执行一次该方法必须使用@classmethod 装饰器)。

    3、TestSuite测试套件

    (1)unittest.TestSuite()

    • addTest():添加单个测试用例方法。
    • addTests([..]):添加多个测试用例方法,方法名存在一个列表,用逗号隔开。
    (2)unittest.TestLoader()
    • loadTestsFromTestCase(测试类名):添加一个测试类。
    • loadTestsFromModule(模块名):添加一个模块。
    • discover(测试用例的所在目录):指定目录去加载,会自动寻找这个目录下所有符合命名规则的测试用例。
     
    if __name__ == "__main__":
        # verbosity参数可以控制输出结果的详细程度,默认为1.若为0,则简化输出;若为2,则详细输出。
        # unittest.main():搜索该模块下所有以test开头的测试用例方法,并自动执行
        # unittest.main(verbosity=1)
        suite = unittest.TestSuite()
    
        # 方式1:添加单个或多个测试用例
        # case1 = MyTest('test_register_success')
        # case2 = MyTest('test_pwd_not_cpwd')
        # case3 = MyTest('test_username_lt6')
        # suite.addTest(case3)
        # suite.addTests([case1, case2])
    
        # 方式2:添加一个测试类
        # loader = unittest.TestLoader()
        # suite.addTest(loader.loadTestsFromTestCase(test_register.TestRegister))
    
    
        # 方式3:添加一个模块(不过试了不可以,按照提示也不行。。。)
        # loader = unittest.TestLoader()
        # suite.addTests(loader.loadTestsFromModule(test_register))
    
        # 方式4:指定测试用例所在的路径,进行加载(默认是寻找目录下test*.py文件)
        # pattern正则表达式匹配测试用例的文件名
        loader = unittest.TestLoader()
        suite.addTest(loader.discover(r"E:", pattern="test_*.py"))
    
     
    4、TestRunner执行测试
    test runner是用来执行测试用例的,并且可以生成相应的测试报告。测试报告有两种展示形式,一种是text文本,一种是html格式(前提:安装HTMLTestRunner模块)。
    runner = HTMLTestRunner.HTMLTestRunner(
            stream=open("report.html", 'wb'),
            description="注册接口测试详情",
            title="注册接口测试报告"
        )
        # 使用启动器去执行测试套件里的用例
        runner.run(suite)

    相关参数说明:

    • stream:指定输出的方式
    • tester:报告中要显示的测试人员的名字
    • description:报告中要显示的面熟信息
    • title:测试报告的标题
    • verbosity :表示测试报告信息的详细程度,一共三个值,默认是2
      • 0 (静默模式):你只能获得总的测试用例数和总的结果,如:总共100个 失败10 成功90
      • 1 (默认模式):类似静默模式,只是在每个成功的用例前面有个. 每个失败的用例前面有个F
      • 2 (详细模式):测试结果会显示每个测试用例的所有相关的信息
     
    五、@unittest.skip():装饰器,用来暂时屏蔽特定的测试用例。

    @unittest.skip(reason):无条件跳过装饰的测试,并说明跳过测试的原因。

    @unittest.skipIf(reason):条件为真时,跳过装饰的测试,并说明跳过测试的原因。

    @unittest.skipUnless(reason):条件为假时,跳过装饰的测试,并说明跳过测试的原因。

    @unittest.expectedFailure():标记该测试预期为失败 ,如果该测试方法运行失败,则该测试不算做失败。

     
    实践:
    # get_unittest.py
    import unittest from Test1 import Register import HTMLTestRunner import test_register # 继承unittest.TestCase class MyTest(unittest.TestCase):
      a = 10
    def setUp(self): self.Reg = Register() # print("测试开始") def tearDown(self): pass # print("测试完成") @classmethod def setUpClass(cls): print("注册接口模块 -- 测试开始") @classmethod def tearDownClass(cls): print("注册接口模块 -- 测试完成") # 测试方法必须以"test"开头
      @unittest.skip("跳过该用例")
    def test_register_success(self): '''注册成功''' data = ("hahaha15", "Bc123456", "Bc123456") expected = {"error_code": 0, "msg": "注册成功!"} result = self.Reg.register(*data) self.assertEqual(expected, result)
      @unittest.skipIf(3>2, "跳过该用例")
    def test_pwd_not_cpwd(self): ''' 注册失败,两次输入密码不一样 data: 测试数据 expected: 预期结果 result: 实际结果 ''' data = ("hahaha14", "Bc123456", "Bc12345") expected = {"error_code": 3004, "msg": "两次输入密码不一致!"} result = self.Reg.register(*data) self.assertEqual(expected, result)

    @unittest.skipUnless(3<2, "跳过该用例")
    def test_username_lt6(self): '''注册失败,用户名长度小于6位''' data = ("haha", "Bc123456", "Bc123456") expected = {"error_code": 3002, "msg": "用户名长度为6-10位!"} result = self.Reg.register(*data) self.assertEqual(expected, result) if __name__ == "__main__": # unittest.main():搜索该模块下所有以test开头的测试用例方法,并自动执行 # unittest.main(verbosity=1) suite = unittest.TestSuite() # 方式1:添加单个或多个测试用例 # case1 = MyTest('test_register_success') # case2 = MyTest('test_pwd_not_cpwd') # case3 = MyTest('test_username_lt6') # suite.addTest(case3) # suite.addTests([case1, case2]) # 方式2:添加一个测试类 # loader = unittest.TestLoader() # suite.addTest(loader.loadTestsFromTestCase(test_register.TestRegister)) # 方式3:添加一个模块(不过试了不可以,按照提示也不行。。。) # loader = unittest.TestLoader() # suite.addTests(loader.loadTestsFromModule(test_register)) # 方式4:指定测试用例所在的路径,进行加载 # pattern匹配了加载的测试用例文件 loader = unittest.TestLoader() suite.addTest(loader.discover(r"E:", pattern="test_*.py")) runner = HTMLTestRunner.HTMLTestRunner( stream=open("report.html", 'wb'), description="注册接口测试详情", title="注册接口测试报告" ) # 使用启动器去执行测试套件里的用例 runner.run(suite)
    # test_register.py
    
    import unittest
    from Test1 import Register
    
    class TestRegister(unittest.TestCase):
    
        def setUp(self):
            self.Reg = Register()
            # print("测试开始")
    
        def tearDown(self):
            pass
            # print("测试完成")
    
        @classmethod
        def setUpClass(cls):
            print("注册接口模块 -- 测试开始")
    
        @classmethod
        def tearDownClass(cls):
            print("注册接口模块 -- 测试完成")
    
        # 测试方法必须以"test"开头
        def test_register_success(self):
            '''注册成功'''
            data = ("hahaha15", "Bc123456", "Bc123456")
            expected = {"error_code": 0, "msg": "注册成功!"}
            result = self.Reg.register(*data)
            self.assertEqual(expected, result)
    
        def test_pwd_not_cpwd(self):
            '''
            注册失败,两次输入密码不一样
            data: 测试数据
            expected: 预期结果
            result: 实际结果
            '''
    
            data = ("hahaha14", "Bc123456", "Bc12345")
            expected = {"error_code": 3004, "msg": "两次输入密码不一致!"}
            result = self.Reg.register(*data)
            self.assertEqual(expected, result)
    
        def test_username_lt6(self):
            '''注册失败,用户名长度小于6位'''
            data = ("haha", "Bc123456", "Bc123456")
            expected = {"error_code": 3002, "msg": "用户名长度为6-10位!"}
            result = self.Reg.register(*data)
            self.assertEqual(expected, result)
    # Test1.py
    
    import requests
    import json
    
    class Register():
    
        def register(self, username, pwd, cpwd):
            url = "http://api.nnzhp.cn/api/user/user_reg"
            method = "post"
            form_body = {
                "username": username,
                "pwd": pwd,
                "cpwd": cpwd
            }
            response = requests.request(url=url, method=method, data=form_body).text
            return json.loads(response)
    
    if __name__ == "__main__":
        reg = Register()
        data = ("hahaha1", "Bc123456", "Bc123456")
        expected = {"error_code": 0, "msg": "注册成功!"}
        result = reg.register(*data)
        print(result)
        print(type(result))
    参考:https://www.cnblogs.com/miki-peng/p/12501341.html
  • 相关阅读:
    POCO库——Foundation组件之日期时间DateTime
    POCO库——Foundation组件之加解密Crypt
    POCO库——Foundation组件之缓存Cache
    POCO库——Foundation组件之核心Core
    POCO库——Foundation组件概述
    HP-SOCKET TCP/UDP通信框架库解析
    Notepad++ 使用nppexec插件配置简易开发环境
    Duilib源码分析(五)UI布局—Layout与各子控件
    Breakpad Google的crash捕获、抓取开源库
    Pugixml一种快速解析XML文件的开源解析库
  • 原文地址:https://www.cnblogs.com/Maruying/p/13528230.html
Copyright © 2011-2022 走看看