欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

python自动化测试—unittest框架四大核心概念学习

程序员文章站 2022-03-11 15:11:01
自动化测试:代码实现用例、代码执行用例、代码判断结果、代码生成测试报告自动化用例的实现需要用到单元测试框架unittest,在测试类当中,以test_开头,定义测试函数每一个test_开头的函数,就是一个测试用例用例编写步骤:1 导入unittest模块2 创建一个测试类,并继承unittest.TestCase、3 定义测试函数,函数名以test_开头(表示一个测试用例)4 在测试用例中:4.1 测试数据、期望结果4.2 用例步骤4.3 断言:预期结果与实际结果的对比下面用一个例子...

unittest框架最核心的四个概念:
python自动化测试—unittest框架四大核心概念学习
一、unittest中测试用例的编写规范

在测试类当中,以test_开头,定义测试函数
每一个test_开头的函数,就是一个测试用例

用例编写步骤:
1 导入unittest模块,被测文件或者其中的类
2 创建一个测试类,并继承unittest模块中的TestCase类
3 定义测试函数,函数名以test_开头(一个test开头的方法就是一条测试用例

4 将测试用例执行的代码逻辑写到对应的测试方法中:
第一步:准备用例数据
第二步: 调用被测的功能函数(发送请求调用接口),获取实际结果
第三步: 断言,预期结果与实际结果的对比

下面编写测试登陆功能的测试用例:

登录的功能逻辑定义在login模块里
python自动化测试—unittest框架四大核心概念学习

import unittest  # 引入 unittest
from python01.python02.login import login_check  # 导入login模块的登录函数


class TestLogin(unittest.TestCase):  # 定义测试类,继承unittest.TestCase
    def test_login_ok(self):  # 用例1
        # 第一步:准备用例数据
        params = {'username': "cyy", "password": 123456}
        expected = {"code":0,"msg":"登录成功"}
        # 第二步:调用被测的功能函数(发送请求调用接口),获取实际结果
        result = login_check(**params)
        # 第三步:断言
        self.assertEqual(result, expected)

上述只是执行了一条用例,下面再看下五条用例的:

用例1 账号密码正确
入参:账号cyy,密码:123456
预期结果:{“code”:0,“msg”:“登录成功”}
实际结果:

用例2 账号正确,密码错误
入参:账号cyy,密码:fdgg
预期结果:{“code”:1,“msg”:“账号或密码不正确”}
实际结果:

用例3 账号错误,密码正确
入参:账号cyy1,密码:123456
预期结果:{“code”:1,“msg”:“账号或密码不正确”}
实际结果:

用例4 账号为空
入参:账号,密码:123456
预期结果:{“code”:1,“msg”:“所有的参数不能为空”}
实际结果:

用例5 密码为空
入参:账号cyy,密码:
预期结果:{“code”:1,“msg”:“所有的参数不能为空”}
实际结果:

import unittest  # 引入 unittest
from python01.python02.login import login_check  # 导入login模块的登录函数


class TestLogin(unittest.TestCase):  # 定义测试类,继承unittest.TestCase
    def test_login_ok(self):  # 用例1
        # 第一步:准备用例数据
        params = {'username': "cyy", "password": 123456}
        expected = {"code":0,"msg":"登录成功"}
        # 第二步:调用被测的功能函数(发送请求调用接口),获取实际结果
        result = login_check(**params)
        # 第三步:断言
        self.assertEqual(result, expected)

    def test_login_password_wrong(self):  # 用例2
        params = {'username': "cyy", "password": "fdgg"}
        expected = {"code": 1, "msg": "账号或密码不正确"}
        result = login_check(**params)
        self.assertEqual(result, expected)

    def test_login_user_wrong(self):  # 用例3
        params = {'username': "cyy1", "password": 123456}
        expected = {"code": 1, "msg": "账号或密码不正确"}
        result = login_check(**params)
        self.assertEqual(result, expected)

    def test_login_no_user(self):  # 用例4
        params = {'username': None, "password": 123456}
        expected = {"code": 1, "msg": "所有的参数不能为空"}
        result = login_check(**params)
        self.assertEqual(result, expected)

    def test_login_no_password(self):  # 用例5
        params = {'username': "cyy", "password": None}
        expected = {"code": 1, "msg": "所有的参数不能为空"}
        result = login_check(**params)
        self.assertEqual(result, expected)

# 以上代码存于 test_case_01.py模块       

执行结果:
python自动化测试—unittest框架四大核心概念学习

这里要注意,每个用例之间都是互相独立,如果其中一个用例报错了,不会影响其他用例的执行。

其中,我们断言用到的是assertEqual(a,b),作用是判断a和b是否相等,如果不相等则断言失败,报错AssertionError,而AssertionError是unittest框架识别用例失败的标识之一
另外unittest还有很多常用的断言方法如下:
python自动化测试—unittest框架四大核心概念学习

二、收集用例TestSuite(测试套件),TestLoader加载用例

import unittest
# 1、创建套件
s = unittest.TestSuite()
# 2、创建一个用例加载器,并加载测试用例到套件(一般用TestLoader加载用例(收集用例))
s = unittest.TestLoader().discover("D:\pythoncharm01\python01")
print(type(s))# 打印出是一个TestSuite类(把发现的测试用例丢到TestSuite类里面)

# 以上代码存于 run.py模块,与test_case_01.py模块同级目录
   
 unittest.TestLoader().discover(搜索目录),搜索用例的方式:discover
 从start_directory这个目录下开始,搜索所有的测试用例,并加载到测试套件中。遵循以下原则:
 1、指定搜索目录
 2、文件过滤规则:以文件名匹配(test*.py),以test开头,.py结尾
 3、在文件当中过滤用例:继承了unittest.TestCase类的测试类,类当中以test_开头的测试函数。
这种方式方便以后的更改,因为是从目录中获取的


还有其他的用例收集方法,例如:
 实例化测试套件TestSuite
 s = unittest.TestSuite()
 1 添加一个用例 addTest(类名(”用例名“))
 s.addTest()
 2 添加多个用例 addTest(类名(”用例名1),类名(”用例名2),类名(”用例名3))
 s.addTests()
 3 TestLoader还可以通过类名、模块名,方式去收集用例
 
 这些收集用例方法比较费劲一般不用,了解即可。

三、执行用例+测试报告

为了验证第二点收集用例功能,同级目下再创建一个测试用例模块(定义了两条用例,一条是错的),看执行用例时是否会和test_case_01.py模块的用例一起加载出来
python自动化测试—unittest框架四大核心概念学习

接下来我们要运行测试用例,并生成结果

这里我们用一个今年7月份发布的一个资源包unittestreport,关于它的详细介绍可以到PYPI了解
安装:pip install unittestreport

import unittest
# 1、创建套件
s = unittest.TestSuite()
# 2、创建一个用例加载器,并加载测试用例到套件(一般用TestLoader加载用例(收集用例))
s = unittest.TestLoader().discover("D:\pythoncharm01\python01")

##########################################################################

from unittestreport import TestRunner #从unittestreport中导入TestRunner类
#先实例化TestRunner,
runner = TestRunner(s,filename = "python01.html",tester='小菜',desc="小菜项目测试报告")
# 再执行用例,生成报告
runner.run()

#以上代码存于 run.py模块

关于括号里面填写的参数意思,可以进入源码进行查看:
python自动化测试—unittest框架四大核心概念学习

执行后,生成如下测试报告:
python自动化测试—unittest框架四大核心概念学习
python自动化测试—unittest框架四大核心概念学习

一共7条用例,其中5条是test_case_01.py模块的,还有两条是test_case_02.py模块的

再介绍一个方法,这种方式生成的报告也还不错
#安装:pip install BeautifulReport
from BeautifulReport import BeautifulReport

br = BeautifulReport(s)
br.report("12月1号测试报告","python02.html")

## 都是一样的套路:先实例化,再运行用例,生成html报告

再扩展个可以减少代码的写法
python自动化测试—unittest框架四大核心概念学习

四、前置后置条件fixture

有时候会遇到一些特殊情况,如果要在用例执行前做一些环境的准备工作,在用例执行后做一些清理工作该怎么办?
这就涉及到我们编写用例用到的前置后置(fixture),就是平常我们功能用例编写用到的前置/后置条件(可有可无)
1 setUp(前置条件),tearDown(后置条件) -类下面的每一个用例在执行之前,会执行setUp, 在每一个用例执行之后,会执行teardown。

import unittest
from python01.python02.login import login_check


class TestLogin(unittest.TestCase):
    def setUp(self) -> None:
        print('前置条件')

    def tearDown(self) -> None:
        print("后置条件")

    def test_login_ok(self):  # 用例1
        res = login_check("cyy", 123456)
        self.assertEqual(res, {"code": 0, "msg": "登录成功"})

    def test_login_password_wrong(self):  # 用例2
        res = login_check("cyy", 789465)
        self.assertEqual(res, {"code": 1, "msg": "账号或密码不正确"})
执行如下:
Ran 2 tests in 0.002s
OK
前置条件
后置条件
前置条件
后置条件

2 setUpClass,tearDownClass,类里面的第一个用例执行之前会执行setUpClass,类里面的最后一个用例执行之后才执行tearDownClass

import unittest
from python01.python02.login import login_check


class TestLogin(unittest.TestCase):
    @classmethod
    def setUpClass(cls) -> None:
        print("前置条件")

    @classmethod
    def tearDownClass(cls) -> None:
        print("后置条件")

    def test_login_ok(self):  # 用例1
        res = login_check("cyy", 123456)
        self.assertEqual(res, {"code": 0, "msg": "登录成功"})

    def test_login_password_wrong(self):  # 用例2
        res = login_check("cyy", 789465)
        self.assertEqual(res, {"code": 1, "msg": "账号或密码不正确"})

执行结果如下:

Ran 2 tests in 0.001s
OK
前置条件
后置条件

以上unittest框架四大核心概念介绍完毕,接下来,再介绍点其他知识

五、用例执行顺序:ASCII码

ASCII吗的大小规则:0-9<A-Z<a-z

例如文件名,test_c.py和test_a.py,就会先执行test_a.py模块
然后进入到文件内部,测试用例执行的顺序也是识别每个函数名,从函数名不同的地方开始识别
若想自己指定顺序,在文件名或者用例名称上做改动

六、ddt数据驱动测试 data driven test

假如有一个测试流程是不变的,针对这个流程设计了几十条测试用例(流程不变,变的是测试数据),就可以用ddt数据驱动模块。数据驱动思想。

注意:由于现在好多人理解的数据驱动思想不一致,所以我们不能说特别掌握,只能说这个场景可以用数据驱动思想去实现。

首先要安装 pip install ddt
1、引入ddt-------import ddt
2、在测试类名的上面,用@ddt.ddt,
3、在测试函数上面,用@ddt.data(*列表)
4、在测试函数的参数中,定义一个参数用来接收每一组测试数据

import unittest  # 引入 unittest
from python01.python02.login import login_check  # 导入login模块的登录函数

datas = [{"username": "cyy", "password": 123456, "check": {"code": 0, "msg": "登录成功"}},
         {"username": "cyy", "password": 12345, "check": {"code": 1, "msg": "账号或密码不正确"}},
         {"username": "cy", "password": 123456, "check": {"code": 1, "msg": "账号或密码不正确"}},
         {"username": None, "password": 123456, "check": {"code": 1, "msg": "所有的参数不能为空"}},
         {"username": "cyy", "password": None, "check": {"code": 1, "msg": "所有的参数不能为空"}},

         ]
import ddt  #导入ddt


@ddt.ddt  # 在测试类名的上面,用@ddt.ddt
class TestLogin(unittest.TestCase):
    @ddt.data(*datas)  #在测试函数上面,用@ddt.data(*列表)  #拆包后将多组测试数据依次传递给一个测试流程
    def test_login_ok(self, case):  #在测试函数的参数中,定义一个case参数用来接收每一组测试数据
        result = login_check(case["username"], case["password"])

        self.assertEqual(result, case["check"])

这就是数据驱动测试,就可不用每条数据写一条用例了

本文地址:https://blog.csdn.net/cai217/article/details/110356685