zoukankan      html  css  js  c++  java
  • unitTest单元测试框架

    一、单元测试的定义:
    1:什么是单元测试?
      还记不记得我们软件测试学习的时候,按照定义:单元测试就是对单个模块或者是单个类或者单个函数进行测试,一般是开发做的,按照阶段来分,一般就是单元测试、集成测试(接口测试)、系统测试(系统之间的联调测试)、验收测试
    2:为什么要做单元测试?
      1)单元测试之后,才是集成测试,单个单个的功能模块测试通过之后,才能把单个功能模块集成起来做集成测试,为了从底层发现bug,减少合成后出现的问题。
      2)越早发现bug越好,这样可以早点发现问题,不然问题累计到后面,如果做错了就要推倒重来-对于时间和经费来说,是非常浪费的!
      3)对于我们测试来说:我们就单元测试是为了执行测试用例!校验程序代码之间的运行逻辑

    说白了也就是一句话:单元测试是测代码,相当于白盒测试,检查代码的逻辑以及功能有没有出问题!!!

    比如:看接下来的一个例子,测某一个账号密码登录的功能,检查代码有没有问题

    def login_check(username=None, password=None):
        """
        登录校验的函数
        :param username: 账号
        :param password:  密码
        :return: dict type
        """
        if username != None and password != None:
            if username == 'python31' and password == 'lemonban':
                return {"code": 0, "msg": "登录成功"}
            else:
                return {"code": 1, "msg": "账号或密码不正确"}
        else:
            return {"code": 1, "msg": "所有的参数不能为空"}

    这段代码是开发人员写的,我们作为测试人员仅仅是去测这些代码有没有问题,怎么去测呢?需要我们自己亲自手写代码

    像这个简单的登录案例,一般有这几种情况:

    1,账号密码均正确
    2,账号正确,密码错误
    3,账号错误,密码正确
    4,账号为空
    5,密码为空

    if __name__ == '__main__':
        # ------------------测试函数正常登录-----------------------------------
        
        # 第一步:准备用例数据
        expected = {"code": 0, "msg": "登录成功"}
        data = ("python31", "lemonban")
        # 第二步:传入参数,获取实际结果
        res = login_check(*data)
        # 第三步:判断用例是否通过(比对预期结果和实际结果)
        if res == expected:
            print("用例执行通过!")
        else:
            print("用例执行不通过!!!")
               
        # ---------------------------测试函数传入错误密码的情况--------------------------------------------
        
        # 第一步:准备用例数据
        expected = {"code": 0, "msg": "登录成功"}
        data = ("python31", "lemonban123")
        # 第二步:传入参数,获取实际结果
        res = login_check(*data)
        # 第三步:判断用例是否通过(比对预期结果和实际结果)
        if res == expected:
            print("用例执行通过!")
        else:
            print("用例执行不通过!!!")

    # 这些代码是散的,一般不会这样去写,所以我们后面会有更完整的模块代码

    unittest四大核心概念:

    1,TestCase:测试用例
    测试用例类:测试用例以类的形式去定义,并且一定要继承unittest中的unittest.TestCase
    测试用例方法:用例类里面的每一个以test开头的方法,就是一条测试用例

    2,TestSuite:测试套件 (用来存放测试用例的,相当于一个用例的集合)

    3,TestRunner:测试运行程序

    4,fixture:测试夹具(测试的前置后置条件处理)

    一、TestCase:测试用例

     请看下面一段代码:

    import unittest
    from day_13.login import login_check
    
    
    class TestLogin(unittest.TestCase):
        """登录的测试用例类"""
    
        def test_login_pass(self):
            """登录成功的用例"""
    
            # 第一步:准备用例数据
            # 1.1用例输入的数据
            data = {"username": "python31", "password": "lemonban"}
            # 1.2预期结果
            expected = {"code": 0, "msg": "登录成功"}
    
            # 第二步:调入被测的功能函数(请求接口),传入参数
            res = login_check(**data)
    
            # 第三步:比对预期结果和实际结果(断言)
            self.assertEqual(expected, res)  # 比较第一个参数和第二个参数
    
    
    if __name__ == '__main__':
        unittest.main()

     

     上面这段代码运行截图:

     因为,我只写了一个测试用例的函数,所以只有1条执行用例显示出来了结果,接下来,我来补充后面几个用例,看看运行跑一下会有什么样的结果:

    注意:如果你的代码报错,无法导入unittest,unittest那里标记红色波浪线,那就说明你一开始没有导入,现在教你一个快速安装的方法:看下面的截图:

     好的,继续,接下来,我来补充后面几个用例,看看运行跑一下会有什么样的结果:

    class TestLogin(unittest.TestCase):
        """登录的测试用例类"""
    
        def test_login_pass(self):
            """账号密码均正确,登录成功"""
    
            # 第一步:准备用例数据
            # 1.1用例输入的数据
            data = {"username": "python31", "password": "lemonban"}
            # 1.2预期结果
            expected = {"code": 0, "msg": "登录成功"}
    
            # 第二步:调入被测的功能函数(请求接口),传入参数
            res = login_check(**data)
    
            # 第三步:比对预期结果和实际结果(断言)
            self.assertEqual(expected, res)
    
        def test_login_pwd_error(self):
            """密码错误"""
    
            # 第一步:准备用例数据
            # 1.1用例输入的数据
            data = {"username": "python31", "password": "lemonban123"}
            # 1.2预期结果
            expected = {"code": 1, "msg": "账号或密码不正确"}
    
            # 第二步:调入被测的功能函数(请求接口),传入参数
            res = login_check(**data)
    
            # 第三步:比对预期结果和实际结果(断言)
            self.assertEqual(expected, res)
    
        def test_login_user_error(self):
            """账号错误"""
    
            # 第一步:准备用例数据
            # 1.1用例输入的数据
            data = {"username": "python999", "password": "lemonban"}
            # 1.2预期结果
            expected = {"code": 1, "msg": "账号或密码不正确"}
    
            # 第二步:调入被测的功能函数(请求接口),传入参数
            res = login_check(**data)
    
            # 第三步:比对预期结果和实际结果(断言)
            self.assertEqual(expected, res)
    
        def test_login_user_is_none(self):
            """账号为空"""
    
            # 第一步:准备用例数据
            # 1.1用例输入的数据
            data = {"username": "", "password": "lemonban"}
            # 1.2预期结果
            expected = {"code": 1, "msg": "所有的参数不能为空"}
    
            # 第二步:调入被测的功能函数(请求接口),传入参数
            res = login_check(**data)
    
            # 第三步:比对预期结果和实际结果(断言)
            self.assertEqual(expected, res)
    
        def test_login_pwd_is_none(self):
            """密码为空"""
    
            # 第一步:准备用例数据
            # 1.1用例输入的数据
            data = {"username": "python31", "password": ""}
            # 1.2预期结果
            expected = {"code": 1, "msg": "所有的参数不能为空"}
    
            # 第二步:调入被测的功能函数(请求接口),传入参数
            res = login_check(**data)
    
            # 第三步:比对预期结果和实际结果(断言)
            self.assertEqual(expected, res)
    
    
    if __name__ == '__main__':
        unittest.main()

    我一共写了5条用例,在上面的代码中,那看看运行结果截图:

     那具体怎么看没通过的用例?点击即可

     说明开发人员写的这段代码是有问题的,可有的人会问,是哪段代码有问题,我怎么看不出,这个不必深究,反正咱们测试人员已经测出bug了,代码的逻辑问题,需开发人员自己去修改,

    附上那段有问题的代码,也就是最前面的那段:

     二、TestSuite:测试套件

    TestSuite:测试套件 (用来存放测试用例的,相当于一个用例的集合)

    如果用例一旦数量较多,比如20个,30个,那还会像上面这样一个一个去写吗?不会,此时,我们可以用到Testsuite这个测试套件,具体的步骤接下来看我慢慢讲解:

    首先我们需要在项目中建一个文件夹File-->dirctory,命名为testcase,然后在这个专门存放测试用例的文件夹下,把用例按照模块去写进去,比如,我们要测试登录这个功能模块,那我们命名为test_login

    如果要测试注册功能,就命名为test_register,如果要测试退出功能,就命名为test_exit,这里的每一个命名都必须以test开头,然后,比如在测试登录模块中,我们写了5个用例,当然,在实际的项目中,可以根据不同的需求

    来在每一个你要测试的模块中写多个用例,我们这里是相当于把功能先分开,再在每个功能里写多个用例,如果需要执行用例,后面可以直接调用来跑程序看结果

    当然,我们也得单独在项目中新建一个run.py文件,这个是专门用来运行程序的

     再来看看run.py文件中的代码:

    import unittest
    from unittestreport import TestRunner
    # 第一步:创建一个测试套件
    suite = unittest.TestSuite()
    
    # 第二步:将测试用例添加到套件中
    # 2.1 创建加载器:
    loader = unittest.TestLoader()
    # 2.2加载用例到套件中
    # 第一种:通过测试用例类去加载
    from day_13.testcase.test_login import TestLogin
    suite.addTest(loader.loadTestsFromTestCase(TestLogin))
    
    # 第三步:执行测试用例类
    runner = TestRunner(suite)
    runner.run()

     其中第二步:将测试用例加载到套件中,一共有三种方式,这里我先讲第一种,但是第一种用的不多,待会我3种都会讲,其中第三种用的是最多的,工作种也常用的。

    那么运行一下,看看截图效果:

     再点击.report.html,运行看测试报告:

     

     因为这份测试报告,有点长,不方便一次截图成功,所以我就截图3次,展示出来,这样看起来,是不是感觉高大上的样子,没错,这就是用unittest这个测试框架的好处,很秀很秀!!!

     这仅仅是其中一种风格,还有另外一种风格,

     看看另外一种的风格:

     

     所以,我们在run.py文件中,可以自由设置这些生成报告的参数。

     继续,上面只讲了一种方式,另外两种方式去加载用例,先上代码,再看截图解析:

    """
    用例加载的过程:
    1、先找指定路径中test开头的python文件
    2、再找Test开头文件中继承unittest.TestCase的用例类
    3、再去找用例类中以test开头的方法
    
    测试用例执行的顺序
    1、模块按照ASCII码排序
    2、类名按照ASCII码排序
    3、方法名按照ASCII码排序
    """
    
    import unittest
    # 第一步:创建一个测试套件
    suite = unittest.TestSuite()
    
    # 第二步:将测试用例添加到套件中
    # 2.1 创建加载器:
    loader = unittest.TestLoader()
    
    # 2.2加载用例到套件中
    # 第一种:通过测试用例类去加载
    # from day_13.testcase.test_login import TestLogin
    # suite.addTest(loader.loadTestsFromTestCase(TestLogin))
    
    # 第二种:通过测试用例模块去加载
    # from day_13.testcase import test_login
    # suite.addTest(loader.loadTestsFromModule(test_login))
    
    # 第三种:指定用例所在文件路径去加载(工作中常用!!!)
    suite.addTest(loader.discover(r"C:UsersAdministratorPycharmProjectsexampleday_13	estcase"))
    
    # 第三步:执行测试用例
    runner = unittest.TextTestRunner()
    runner.run(suite)

     

     三、TestRunner: 测试运行程序

     这部分的内容,主要是用来执行测试用例和生成测试报告的,先看代码,再看截图:

    import unittest
    from unittestreport import TestRunner
    # 第一步:创建一个测试套件
    suite = unittest.TestSuite()
    # 第二步:将测试用例添加到套件中
    # 2.1 创建加载器:
    loader = unittest.TestLoader()
    # 2.2加载用例到套件中
    # 第一种:通过测试用例类去加载
    from day_13.testcase.test_login import TestLogin
    suite.addTest(loader.loadTestsFromTestCase(TestLogin))
    # 第三步:执行测试用例类
    runner = TestRunner(suite,
                        filename="report.html",
                        report_dir=".",
                        title='测试报告',
                        tester='excellent',
                        desc="excellent执行测试生成的报告",
                        templates=1   # 这里可以生成两个风格不同的报告,待会给大家看一下
                        )
    runner.run()

     这个run.py主要是和测试套件suite一起用,用来运行程序,

    四、fixture测试夹具

    fixture:测试用例环境的搭建与销毁,测试前准备环境的搭建(setUp),执行测试代码(run),以及测试后环境的还原(tearDown)

    setUpClass(只执行一次)
    setUp
    tearDown
    tearDownClass(只执行一次)

    import unittest
    
    
    class TestRegister(unittest.TestCase):
    
        def test_01(self):
            """比对1和100"""
            print("-----------执行test_01------------")
            self.assertEqual(100, 100)
    
        def test_02(self):
            """比对1000和1000"""
            print("-----------执行test_02------------")
            self.assertEqual(1000, 1000)
    
        def setUp(self):
            # 每条测试用例执行之前都会调用该方法(有多少用例执行多少次)
            print("-------------setup----------")
    
        def tearDown(self):
            # 每条测试用例执行之后都会调用该方法(有多少用例执行多少次)
            print("-------------tearDown----------")
    
        @classmethod
        def setUpClass(cls):
            # 测试类里面的用例执行之前会调用该方法(只会执行一次)
            print("-------------setUpClass----------")
    
        @classmethod
        def tearDownClass(cls):
            # 测试类里面的用例执行之后会调用该方法(只会执行一次)
            print("-------------tearDownClass----------")
    
    if __name__ == '__main__':
        unittest.main()

    未完待续。。。。。。。。。。。。。。。。。。。。。。。

     
  • 相关阅读:
    Spring boot 整合 Mybatis + Thymeleaf开发web(一)
    JAVA截取字符串的几种方式
    【转】JAVA异常报错大全
    Linux中允许远程用户登录访问mysql的方法
    Ubuntu系统下将默认的python2.7升级到3.5
    Ubuntu+Django+Nginx+uWSGI+Mysql搭建Python Web服务器
    python将数据写入excel代码,python与office交互
    pyqt4桌面软件各种画布组合结构实例
    python之pyqt4的简单窗口布局以及信号和槽(上代码)
    python 005 正则表达式
  • 原文地址:https://www.cnblogs.com/xj-excellent/p/13443295.html
Copyright © 2011-2022 走看看