学习python自动化——pytest单元测试框架

一、什么是pytest

单元测试框架,unittest(python自带的),pytest(第三方库)。

用于编写测试用例、收集用例、执行用例、生成测试结果文件(html、xml)

1.1、安装pytest

pip install pytest

1.2、导入

import pytest

二、步骤

  2.1、TestCase(测试用例)

    2.1.1、创建测试类      

      1)类名要以Test开头

class TestData:
    2.1.2、测试用例函数      

      1)可以直接用函数、类的形式
      2)函数名必须是test_开头
      3)执行顺序,按照从上到下的代码顺序执行

def test_data():        #测试函数print("test_data")class TestData:def test_hello(self):    #测试函数print("test_hello")
    2.1.3、前置后置(fixture)
      前置:环境准备、数据准备后置:清理工作、数据清理

    pytest的fixture有2种实现方式:

      2.1.3.1、xunit-style

        跟unittest框架的机制非常相似,即setup/teardown系列

        1、测试函数/方法级别:每一个测试函数都会执行的前置和后置。

          1)测试类内部的测试方法:

            前置函数名称:setup_method

            后置函数名称:teardown_method

          2)模块下的测试函数:

            前置函数名称:setup_function

            后置函数名称:teardown_function

        2、测试类级别:一个测试类只执行一次前置和后置。

          前置函数名称:setup_class

          后置函数名称:teardown_class

          注意:用@classmethod装饰

        3、测试模块级别:一个测试模块只执行一次前置和后置。

          前置函数名称:setup_module

          后置函数名称:teardown_module

from selenium import webdriver
from time import sleep
from random import randintdef setup_module():print("====  模块级的 setup 操作  ====")def teardown_module():print("====  模块级的 teardown 操作  ====")def test_random():assert randint(1, 5) == 3class TestWeb:@classmethoddef setup_class(cls):print("====  测试类级的 setup 操作  ====")@classmethoddef teardown_class(cls):print("====  测试类级的 teardown 操作  ====")def setup_method(self):print("====  测试用例级的 setup 操作  ====")self.driver = webdriver.Chrome()def teardown_method(self):print("====  测试用例级的 teardown 操作  ====")self.driver.quit()def test_search(self):self.driver.get("https://www.baidu.com/")self.driver.find_element_by_id("kw").send_keys("柠檬班")self.driver.find_element_by_id("su").click()sleep(1)
      2.1.3.2、fixture机制

        通过@pytest.fixture装饰器来定义fixture

         1、fixture定义

          1)fixture通过函数实现

          2)使用@pytest.fixture进行装饰

          3)前置和后置都放在同一个函数当中,通过yeild关键字区分前置和后置,yeild前面的为前置,yeild后面的为后置

import pytest@pytest.fixture
def init():print("用例执行之前,执行的代码")  # 前置代码 yieldprint("用例执行之后,执行的代码")  # 后置代码@pytest.fixture
def init2():print("用例执行之前,执行的代码")  # 只有用例执行之前的前置准备代码@pytest.fixture
def init3():yieldprint("用例执行之后,执行的代码")  # 只有用例执行之后的后置清理代码

          4)fixture有4个作用域:测试会话(session)、测试模块(module)、测试类(class)、测试用例(function)

           设置fixture的作用域,通过@pytest.fixture(scope=作用域)来设置。默认情况下,scope=function

import pytest# 没有设置scope,默认为测试函数级别。即调用此fixture的测试类/模块/函数下,每个测试函数都会执行一次这个fixture
@pytest.fixture
def init():print("用例执行之前,执行的代码")  # 前置代码yieldprint("用例执行之后,执行的代码")  # 后置代码# 设置scope为class。调用此fixture的测试类下,只执行一次这个fixture.
@pytest.fixture(scope="class")
def init2():print("用例执行之前,执行的代码")  # 只有用例执行之前的前置准备代码# 设置scope为session。autouse表示自动使用。
# 那么在pytest收集用例后,开始执行用例之前会自动化执行这个fixture当中的前置代码,
# 当所有用例执行完成之后,自动化执行这个fixture的后置代码。
@pytest.fixture(scope="session",autouse=True)
def init3():yieldprint("用例执行之后,执行的代码")  # 只有用例执行之后的后置清理代

          5)fixture的返回值设置:yeild 返回值

            如果前置准备工作当中,有变量要传递给测试用例去使用的话,那么就需要返回这个变量,可以有多个返回值,返回值是个元组。

            yeild 返回值,返回值2,返回值3    

yield mysql_obj,True,123

        2、fixture调用

           2.1、自动调用:定义fixture有个参数:autouse,默认autouse=False

              自动调用时,所有的测试函数都会调用一次,所以只有session作用域时才适用。

import pytest@pytest.fixture(autouse=True)           #自动调用
def init():print("===我是前置准备工作===")yieldprint("***我是后置清理工作***")@pytest.fixture(scope="class")
def init_class():print("===我是测试类  前置准备工作===")yieldprint("***我是测试类  后置清理工作***")def test_hello():print("hello pytest!!")class Test_demo:def test_bey(self):print("bey pytest!!")

           2.2、主动调用:测试函数/测试类上加上:@pytest.mark.usefixtures("fixture的函数名称"),可以调用多个。

             当调用两个同级别的fixture函数时,按就近原则调用

            1)无需接收fixture返回值

import pytest
from random import randint#测试类级别
@pytest.fixture(scope="class")
def init_class():print("===我是 测试类  前置准备工作===")mysql_obj = "fixture要返回出去的数据库对象"yield mysql_obj,True,123  # 返回一个变量/对象print("***我是 测试类  后置清理工作***")# 测试函数级别
@pytest.fixture()
def init():print("===我是前置准备工作===")yieldprint("***我是后置清理工作***")# 测试函数级别
@pytest.fixture()
def init2():print("===我是前置准备工作2===")yieldprint("***我是后置清理工作2***")@pytest.mark.usefixtures("init")        #去执行名为init的fixture函数
@pytest.mark.usefixtures("init2")       #当调用两个同级别的fixture函数时,就近原则,先调用init2,再调用init
def test_hello():print("hello pytest!!")def test_demo():                        #无前置后置print("hello world")@pytest.mark.usefixtures("init_class")      #执行名为init_class测试类级别的前置后置
@pytest.mark.usefixtures("init")            #当调用两个不同级别的fixture函数时,先调用init_class,再每个函数调用init
class TestDemo:def test_random(self):assert randint(3, 3) == 3def test_abc(self):assert True@pytest.mark.usefixtures("init2")           #当类内部函数有调用时,就近原则,先调用init2,再调用initdef test_bey(self):print("bey pytest!!")

             2)要接收fixture返回值:fixture的函数名作为用例的参数,相当于fixture函数名 = fixture调用的返回值

              当fixture函数名作为测试用例参数时,在执行用例时,会自动寻找该函数的fixture,并执行。

              ps:pytest当中的测试用例,如果有参数,分为2种:

                1、fixture的名字

def test_random(self,init_class)pass

                2、参数化要传的参数

@pytest.mark.parametrize("case",datas)
def test_read_datas(case):pass
 
import pytest
from random import randint# 测试类级别
@pytest.fixture(scope="class")
def init_class():print("===我是 测试类  前置准备工作===")mysql_obj = "fixture要返回出去的数据库对象"yield mysql_obj,True,123  # 返回一个变量/对象print("***我是 测试类  后置清理工作***")#@pytest.mark.usefixtures("init_class")  # 当fixture函数名作为测试用例参数时,在执行用例时,会自动寻找该函数名并执行,所以这个可以不写
class TestDemo2:def test_random(self,init_class): # fixture的名字作为用例的参数,相当于fixture名字 = fixture调用的返回值mysql_obj, bool_obj, int_obj = init_classprint("从fixture当中接收的变量为:{}".format(init_class))assert randint(1, 5) == 3def test_abc(self):assert True

      2.1.3.3、conftest.py共享机制

       1、共享实现

        1)在项目根目录下,创建一个conftest.py文件。

        2)文件名必须是conftest.py,大小写敏感,不可改名字。

        3)conftest.py当中,可以编写多个fixture

        4)在测试用例文件当中,不需要引入conftest.py文件。直接调用fixture的函数名,会自动去conftest.py当中查找的。

        2、conftest.py层级作用域

         conftest.py在项目根目录下,则项目下的所有测试用例,均可使用conftest.py中定义的fixture。即项目根目录下的conftest.py,作用域是整个项目。

         根目录下的conftest.py里的fixture,无论项目下的哪个用例,都可以使用。

         子目录day3-login下的conftest.py里的fixture,只有day3-login下的用例可以使用。

         子目录day3-register下的conftest.py里的fixture,只有day3-register下的用例可以使用。

           测试用例在执行时,调用fixture的顺序,按 就近原则 调用。

           测试用例文件中的fixture > 当前目录中的fixture > 上级目录中的fixture > 根目录中的fixture

       2.1.3.4、fixture嵌套

        嵌套使用即:一个fixture,可以做另外一个fixture的参数,自动调用参数的fixture。

        注意:由于参数里的fixture要先执行,所以参数里的fixture的作用域 >= fixture的作用域。

@pytest.fixture
def init_class():print(" %%%% 我是 day3-login包下test_random模块的测试类  前置准备工作 %%%% ")yieldprint(" %%%% 我是 day3-login包下test_random模块的测试类  后置清理工作 %%%% ")@pytest.fixture
def init_case(init_class):      #init_class作为init_case的参数,当用例调用init_case时,init_case会自动调用init_classprint("测试用例级别 的前置")print("=================================")yieldprint("测试用例级别 的后置")print("===============用例  完结==================")

      2.1.3.5、session 和 module 级别的 fixture

       1)session 级别的 fixture

         从 pytest 开始收集用例,到执行用例完成的整个过程,为一次会话,可以设置 autouse=True 

import pytest@pytest.fixture(scope="session",autouse=True)
def fix_session():print("===  session级别的前置 ,只执行1次 ============")yield Trueprint("===  session级别的后置 ,只执行1次 ============")

                

       2)module 级别的 fixture

         module 是指测试 py 文件,夹具夹的是整个 test_*.py 文件里的测试用例。

         在 test_*.py 里,哪一行代码调用了 module 级别的 fixture,那么夹的就是那行代码之后的所有测试用例。

import pytest@pytest.fixture(scope="module")
def fix_module():print("===  module级别的 前置 ======")yieldprint("===  module级别的 后置 ======")

    2.1.4、断言

      将预期结果与实际结果进行对比
      assert 表达式(True表示断言为真,False表示断言失败)

assert a==b

  2.2、用例收集:自动收集

    1)pytest自动收集用例规则:在当前文件所在的目录下,收集文件名为test_*.py或*_test.py的测试文件中,以test_开头的测试用例或Test开头的测试类。

    2)pytest.main():以当前文件所在的目录下,收集用例并执行。

pytest.main(["-s","-v"])

    3)用例分类执行

pytest.main(["day1/test_case1.py"])      #只执行day1目录下test_case1.py文件的测试用例

  2.3、TestRunner(用例执行)

    1)需要配置执行器:File>>>Settings>>>Tools>>>Python Integrated Tools>>>Default test runner:pytest
    2)执行顺序:测试文件顺序按ASCII码,文件内部测试用例按代码顺序执行

    3)若py文件执行过一次后,会保留上一次执行的方式,需要清除上一次执行记录。右上角——Edit Configurations——Remove掉该py文件。

   2.4、生成测试报告

    2.4.1、生成JunitXML 格式的测试报告

      命令:--junitxml=path     

    2.4.2、生成result log格式的测试报告

      命令:--resultlog=report\log.txt     

    2.4.3、生成Html格式的测试报告 

      1)安装pytest-html插件

pip install pytest-html

      2)在pytest.main()的参数当中添加:--html=报告路径

pytest.main(["-s","-v","--html=report.html"])      #生成html格式的测试报告
    2.4.4、生成allure的测试文件 

      2.4.4.1、allure是依据测试结果文件,呈现更好看的更多维度的测试报告。
      注意:它不执行用例也不生成测试结果文件。所以,要使用allure的时候,一定要先生成测试结果文件。allure需要依赖测试框架,执行测试用例后,根据测试结果再生成测试报告。

      2.4.4.2、allure的使用

        1、安装allure命令行工具
          1)下载allure安装包。下载地址:https://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline/

          2)下载完成之后,解压到任意目录
          3)配置环境变量:allure的bin目录。比如D:\allure-2.12.1\bin

          4)在cmd当中,执行allure命令,不报错即allure安装成功。

        2、pytest在执行用例之后,要生成allure可以识别的测试结果文件。
          1)安装插件

pip install allure-pytest

          2)在pytest.main()的参数当中添加:--alluredir=allure生成的文件目录(手动创建一个)

pytest.main(["-s","-v","--alluredir=allure_file"])

pytest.main(["--alluredir=allure_file","--clean-alluredir"])      #每次运行前清除allure_file中的文件,为防止数据重复

        3、使用allure去解析2中的测试结果文件,再呈现最终的测试报告
          1)在cmd当中首先跳转到rootdir下面

          2)在cmd当中执行命令:allure serve 2中的测试结果文件目录

   2.5、参数化(数据驱动)

    1、@pytest.mark.parametrize("参数名",列表数据)

datas={"api":"login","url":"http://api.lemoban.com/futureloan/login","api":"register","url":"http://api.lemoban.com/futureloan/register","api":"recharge","url":"http://api.lemoban.com/futureloan/recharge","api":"withdraw","url":"http://api.lemoban.com/futureloan/withdraw"}@pytest.mark.parametrize("case",datas)
def test_read_datas(case):pass

    2、组合参数化:多组参数,依次组合。
      使用多个@pytest.mark.parametrize

#示例:用例有4个:0,2/0,3/1,2/1,3 迪卡尔积
@pytest.mark.parametrize("x", [0, 1])
@pytest.mark.parametrize("y", [2, 3])
def test_foo(x, y):pass

   2.6、重试机制(rerun)

1)安装插件:pytest-rerunfailures

pip install pytest-rerunfailures

2)命令

pytest --reruns 次数

pytest --reruns-delay  重运行次数之间的间隔时间(以秒为单位)

pytest.main(["--reruns","2","--reruns-delay","5"])

   2.7、筛选用例,mark一下

当我们想只运行诸多py文件当中的部分用例,需要过滤用例时,可以使用pytest.mark一下。

1)注册标签名

通过pytest.ini配置文件注册。在pytest.ini文件当中:

[pytest]   # 固定的section名

markers= # 固定的option名称

  标签名1: 标签名的说明内容。

  标签名2

  标签名N

 2)在测试用例/测试类中给用例打标记(只能使用已注册的标记名)

 在测试用例的前面加上:@pytest.mark.已注册标签名

 3)运行时,根据用例标签过滤(-m 标签名)

调用pytest.main()函数,将运行时的参数以列表传进去,同样也可以达到命令行运行的效果。可以使用逻辑运算符。

pytest.main(["-m","demo"])      #执行标签为demo的测试用例
pytest.main(["-m not demo"])    #执行标签不是demo的测试用例
pytest.main(["-m demo and test"])  #执行标签是demo又是test的测试用例

  【已更新】B站讲的最详细的Python接口自动化测试实战教程全集(实战最新版)
》,以及配套的接口文档/项目实战【网盘资源】,需要的朋友可以下方视频的置顶评论获取。肯定会给你带来帮助和方向。

【已更新】B站讲的最详细的Python接口自动化测试实战教程全集(实战最新版)

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/444723.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring AI 介绍与入门使用 -- 一个Java版Langchain

Langchain 是什么? Langchain 是一个Python 的AI开发框架,它集成了模型输入输出、检索、链式调用、内存记忆(Memory)、Agents以及回调函数等功能模块。通过这些模块的协同工作,它能够支持复杂的对话场景和任务执行流程…

C语言 | Leetcode C语言题解之第460题LFU缓存

题目: 题解: /* 数值链表的节点定义。 */ typedef struct ValueListNode_s {int key;int value;int counter;struct ValueListNode_s *prev;struct ValueListNode_s *next; } ValueListNode;/* 计数链表的节点定义。 其中,head是数值链表的头…

多点低压差分(M-LVDS)线路驱动器和接收器——MS2111

MS2111 是多点低压差分 (M-LVDS) 线路驱动器和接收器。经过 优化,可运行在高达 200Mbps 的信号速率下。所有部件均符合 M LVDS 标准 TIA / EIA-899 。该驱动器的输出支持负载低至 30Ω 的多 点总线。 MS2111 的接收器属于 Type-2 , 可在 -1…

【GESP】C++一级练习BCQM3037,简单计算,国庆七天乐收官

又回到了简单计算的题目,继续巩固练习。 题解详见:https://www.coderli.com/gesp-1-bcqm3037/ 【GESP】C一级练习BCQM3037,简单计算,国庆七天乐收官 | OneCoder又回到了简单计算的题目,继续巩固练习。https://www.cod…

性能测试工具locust —— Python脚本参数化!

1.1.登录用户参数化 在测试过程中,经常会涉及到需要用不同的用户登录操作,可以采用队列的方式,对登录的用户进行参数化。如果数据要保证不重复,则取完不再放回;如可以重复,则取出后再返回队列。 def lo…

std::future::then的概念和使用方法

std::future::then是 C 中用于异步操作的一种机制,它允许在一个异步任务完成后,接着执行另一个操作(即延续操作)。以下是关于 std::future::then 的概念和使用方法: 1. 概念: std::future::then 的主要目…

Chrome清除nslookup解析记录 - 强制http访问 - 如何禁止chrome 强制跳转https

步骤: 地址栏输入 chrome://net-internals/#hsts在Delete domain 栏的输入框中输入要http访问的域名,然后点击“delete”按钮最后在Query domain 栏中搜索刚才输入的域名,点击“query”按钮后如果提示“Not found”即可! 办法来自…

Java | Leetcode Java题解之第459题重复的子字符串

题目: 题解: class Solution {public boolean repeatedSubstringPattern(String s) {return kmp(s s, s);}public boolean kmp(String query, String pattern) {int n query.length();int m pattern.length();int[] fail new int[m];Arrays.fill(fa…

Hunuan-DiT代码阅读

一 整体架构 该模型是以SD为基础的文生图模型,具体扩散模型原理参考https://zhouyifan.net/2023/07/07/20230330-diffusion-model/,代码地址https://github.com/Tencent/HunyuanDiT,这里介绍 Full-parameter Training 二 输入数据处理 这里…

E系列I/O模块在锂电装备制造系统的应用

为了满足电池生产线对稳定性和生产效率的严苛要求,ZLG致远电子推出高速I/O应用方案,它不仅稳定可靠,而且速度快,能够迅速响应生产需求。 锂电池的生产工艺较为复杂,大致分为三个主要阶段:极片制作、电芯制作…

单点登录Apereo CAS 7.1客户端集成教程

从上一篇部署并成功运行CAS服务端后,我们已经能通过默认的账号密码进行登录。 上篇地址:单点登录Apereo CAS 7.1安装配置教程-CSDN博客 本篇我们将开始对客户端进行集成。 CAS中的客户端,就是指我们实际开发的各个需要登录认证的应用。现在,跟着笔者的步伐,一起探索如何…

springmvc直接访问 上下文路径 302 后路径更改并跳转源码解析

【问题现状】 application.yml 配置如下属性: server:servlet:context-path: /learning直接访问:http://localhost:8888/learning 路径时,会返回302的响应状态;并跳转路径:http://localhost:8888/learning/ (原路径后…

Docker Overlay2 空间优化

目录 分析优化数据路径规划日志大小限制overlay2 大小限制清理冗余数据 总结 分析 overlay2 目录占用磁盘空间较大的原因通常与 Docker 容器和镜像的存储机制以及它们的长期累积相关,其实我之前在 Docker 原理那里已经提到过了。 通常时以下几种原因导致&#xff…

☕️从小工到专家的 Java 进阶之旅:全新的HttpClient,现代高效的网络通信利器

你好,我是看山。 本文收录在 《从小工到专家的 Java 进阶之旅》 系列专栏。日拱一卒,功不唐捐。 在 Java 开发领域,网络通信一直是至关重要的部分。从早期的网络编程方式到如今,Java 在 HTTP 客户端方面经历了不断的演进。 其中&…

【C语言】函数栈帧的创建和销毁

文章目录 前言函数栈帧相关寄存器相关汇编指令内存函数栈帧的创建销毁过程 前言 为了更好的了解函数里面变量是如何创建,为什么创建的变量是随机值和函数怎么传参和顺序是怎样的、以及实参和形参的关系,还要函数之间的调用、返回和销毁的过程。我们今天…

Comfyui 学习笔记5

1.图像处理小工具,沿某个轴反转Image Flip 2. reactor换脸 3. 通过某人的多张照片进行训练 训练的模型会保存在 models/reactor/face/下面,使用时直接load就好 4. 为一个mask 更加模糊 羽化 5. 指定位置替换,个人感觉这种方式进行换脸的融…

Pura 70系列和Pocket 2已支持升级尝鲜鸿蒙NEXT,报名教程在这里

相信不少关注鸿蒙 NEXT 的人都知道,10月8日起,华为开启了鸿蒙 NEXT 系统的公测,但有不少人不知道的是,除了公测的 Mate 60 和 Mate X5 两个系列的机型,还有两个系列的手机其实也可以提前升级体验鸿蒙 NEXT 系统。 Pur…

从数据管理到功能优化:Vue+TS 项目实用技巧分享

引言 在项目开发过程中,优化用户界面和完善数据处理逻辑是提升用户体验的重要环节。本篇文章将带你一步步实现从修改项目图标、添加数据、优化日期显示,到新增自定义字段、调整按钮样式以及自定义按钮跳转等功能。这些操作不仅提升了项目的可视化效果&am…

统一流程引擎如何具体实现对多系统业务流程的整合?

在信息化时代,企业和组织通常会使用多个业务系统来满足不同的业务需求。然而,这些分散的业务系统往往会导致业务流程的碎片化,降低工作效率。统一流程引擎的出现为解决这一问题提供了有效的途径。它能够整合多系统的业务流程,实现…

LeetCode 3310. 移除可疑的方法

LeetCode 3310. 移除可疑的方法 你正在维护一个项目,该项目有 n 个方法,编号从 0 到 n - 1。 给你两个整数 n 和 k,以及一个二维整数数组 invocations,其中 invocations[i] [ai, bi] 表示方法 ai 调用了方法 bi。 已知如果方法 k…