【Pytest+Yaml+Allure】实现接口自动化测试框架

一、框架思想

requests+yaml+pytest+allure实现接口自动化框架。结合数据驱动和分层思想,将代码与数据分离,易维护,易上手。使用yaml编写编写测试用例,利用requests库发送请求,使用pytest管理用例,allure生成测试报告,后续可能加上CI 持续集成(Jenkins)。

数据驱动是整个框架的核心
什么是数据驱动?
在接口测试中,测试用例可能有上百条,如果将用例全部写在代码中,一旦需要修改,将会消耗大量的时间,不容易维护。所以,我们就要测试数据,或者测试用例存储到文件中,用代码读取文件获取数据,实现数据驱动。
数据驱动分为两种:
1、参数的数据驱动
2、用例的数据驱动

json

格式完备,格式死板,不能写注释
yaml格式完备,格式简单,可注释
csv可以使用excel编辑,文本格式方便管理
xml

格式完备,冗长复杂

二、yaml基本语法


大小写敏感
使用缩进表示层级关系
缩进时不允许使用Tab键,只允许使用空格。
缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
yaml支持三种数据结构:
对象:键值对的集合,又称为映射(mapping)/ 哈希(hashes) / 字典(dictionary)
数组:一组按次序排列的值,又称为序列(sequence) / 列表(list)
纯量(scalars):单个的、不可再分的值

数组:
- Cat
- Dog
- Goldfish

也可写成:列表嵌套列表
-
 - Cat
 - Dog
 - Goldfish

字典与列表嵌套:
 -
  id:login_02

三、读取yaml


yaml.load和safe_load()
两者区别:
safe_load()可以解析简单的数据结构,而且比较安全,load可以解析比较复杂的数据结构,通常一般使用的最多的还是load()

四、测试用例数据驱动

case.yaml

  

-
  id: login_01
  title: 登录成功
  url: member/login
  method: POST
  request_data: {"mobile_phone": "17866554324","pwd":"188888"}
  expect: {"code":0,"msg":"OK"}

读取yaml文件的函数: 



#读取yaml

def read_yaml(self):
        with open(self.filename, encoding='utf-8') as fs:
            # 避免报警告:yaml.FullLoader
            data = yaml.load(fs, Loader=yaml.FullLoader)
            return data


五、参数化数据驱动


将测试用例部分数据进行参数化,比如用户名密码之类的数据。 然后将数据放入配置文件中

[case_data]
mobile_phone = 13800138000
pwd = 88888888


六.使用正则表达式替换参数化数据


正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

正则表达式的大致匹配过程是:

1.依次拿出表达式和文本中的字符比较

 2.如果每一个字符都能匹配,则匹配成功;一旦有匹配不成功的字符则匹配失败。

3.如果表达式中有量词或边界,这个过程会稍微有一些不同。

正则表达式贪婪模式:尽可能多的匹配 非贪婪模式:尽可能少的匹配

引入模块

import re
方法:
1.compile(pattern[,flag]):
对正则表达式pattern进行编译,编译后比直接查找速度快

2.match(patter,string[,flag]):
从字符串string的开始就匹配,若匹配成功,则返回匹配对象,否则返回None(None对象没有group()和groups()方法,不判断直接调用这两个方法,则会出现异常)

3.search(pattern,string[,flag]):
从字符串中查找,若匹配成功,则返回匹配对象,否则返回None

4.findall(pattern,string[,flag]):
在字符串 string 中查找正则表达式模式 pattern 的所有(非重复)出现;返回一个匹配对象的列表

5.finditer(pattern,string[, flags])b 和 findall()
相同,但返回的不是列表而是迭代器;对于每个匹配,该迭代器返回一个匹配对象

6.split(pattern,string, max=0) 
根据正则表达式 pattern 中的分隔符把字符 string 分割为一个列表,返回成功匹配的列表,最多分割 max 次(默认是分割所有匹配的地方)

7.sub(pattern, repl, string, max=0) 
把字符串 string 中所有匹配正则表达式 pattern 的地方替换成字符串 repl,如果 max 的值没有给出, 则对所有匹配的地方进行替换
代码如下(示例):

res=re.findall("#(.*?)#",data)



七、发送请求


使用第三方库requests 请求方式:get/post/put/delete

代码如下(示例):

def send_request(method,url,data,header):
    if method=="POST":
        res=requests.post(url,json=data,headers=header)
    elif method=="GET":
        res = requests.post(url, params=data, headers=header)
    elif method=="PUT":
        '''
                封装put方法,uri是访问路由,params是put请求需要传递的参数,如果没有参数这里为空
                :param uri: 访问路由
                :param params: 传递参数,string类型,默认为None
                :return: 此次访问的response
        '''
        if data is not None:
            # 如果有参数,那么通过put方式访问对应的url,并将参数赋值给requests.put默认参数data
            # 返回request的Response结果,类型为requests的Response类型
            res=requests.put(url,json=data,headers=header)
        else:
            # 如果无参数,访问方式如下
            # 返回request的Response结果,类型为requests的Response类型
            res = requests.put(url)
    elif method=="DELETE":
        '''
            封装delete方法,uri是访问路由,params是delete请求需要传递的参数,如果没有参数这里为空
            :param uri: 访问路由
            :param params: 传递参数,string类型,默认为None
            :return: 此次访问的response
        '''
        if data is not None:
            # 如果有参数,那么通过put方式访问对应的url,并将参数赋值给requests.put默认参数data
            # 返回request的Response结果,类型为requests的Response类型
            res=requests.delete(url,data=data,headers=header)
        else:
            # 如果无参数,访问方式如下
            # 返回request的Response结果,类型为requests的Response类型
            res = requests.delete(url,headers=header)
    else:
        logger.info("无效的请求方式,get/post/put/delete,请查找原因!!!")
    return res
    logger.info("响应数据为{}".format(res.json))


八、pytest管理用例


为什么选择pytest,不选择unittest?
pytest特点:

简单灵活,容易上手;支持参数化; 测试用例的skip和xfail 处理;
能够支持简单的单元测试和复杂的功能测试,还可以用来做 selenium/appium等自动化测试、接口自动化测试 (pytest+requests);
pytest具有很多第三方插件,并且可以自定义扩展, 比较好 用的如 pytest-allure(完美html测试报告生成) pytest-xdist (多CPU分发)等;
可以很好的和jenkins集成;**
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。

pytest框架结构:
Import pytest 类似的setup,teardown同样更灵活
模块级 (setup_module/teardown_module)
全局的,整个.py模块开始前和结束后调用一次
函数级 (setup_function/teardown_function)

只对函数用例生效(不在类内),每个函数级用例开始和结束时调用一次
类级 (setup_class/teardown_class)
  只在类前后运行一次(在类中)。
方法级 (setup_method/teardown_methond)
  运行在类中方法始末

类里面的(setup/teardown):运行在调用方法的前后
类中运行顺序:setup_class>setup_method>setup>用例>teardown>teardown_method>teardown_class

pytest执行方式:
Pytest –v (最高级别信息—verbose)
pytest -v -s filename 3.Pytest-q (静默)
(输出打印)
多种执行方式
1.pytest将在当前目录及其子目录中运行test _ * .py或* test.py形 式的所有文件。
2.以test_开头的函数,以Test开头的类,以test_开头的方法。所有包 package都要有__init_.py文件。
3.Pytest可以执行unittest框架写的用例和方法
可以在pytest.ini文件中自定义要运行的测试路径、文件名、类名和方法名等。

pytest断言

mark中skip的使用:

1、不想运行部分用例

2、标记无法运行的测试用例

3、当前外部资源不可用

4、在某些版本中跳过

mark中xfail的使用

1、功能尚未实施或尚未修复,使用@pytest.mark.xfail标记,会是一个xpass,在测试报告中

自定义的标记,可以只执行部分用例

1、当回归测试,只需要执行部分用例时。

pytest中的fixture
在pytest中可以灵活使用fixture,不需要每一个用例都写fixture,写好一个只需要调用就可以
 

@pytest.fixture(scope="class")
def init():
    logger.info("=========================开始执行测试项目=========================")
    yield
    logger.info("=========================测试项目执行完毕=========================")

1.机制:与测试用例同级,或者是测试用例的父级,创建一个conftest.py文件。
2.conftest.py文件里:放所有的前置和后置。 不需要用例.py文件主动引入conftest文件。
3.定义一个函数:包含前置操作+后置操作。
4.把函数声明为fixture :在函数前面加上 @pytest.fixture(作用级别=默认为function)
5.fixture的定义。
  如果有返回值,那么写在yield后面。(yield的作用就相当于return)
  在测试用例当中,调用有返回值的fixture函数时,函数名称就是代表返回值。
  在测试用例当中,函数名称作为用例的参数即可。
 

@pytest.mark.sign
@allure.epic("测试项目")
@allure.feature("登录模块")
@pytest.mark.usefixtures("init")
class Test_Login:
    @pytest.mark.parametrize("case",cases)
    def test_login(self,case):
        res=send_request(case["method"],case["url"],json.loads(case["request_data"]))
        expect=json.loads(case["expect"])
        logger.info("期望结果为{}".format(expect))
        logger.info("响应结果为:{}".format(res.json()))
        if expect:
            try:
                assert res.json()["code"]==expect["code"]
            except Exception as e:
                logger.info("断言失败")
                raise
            return res

进阶方法:conftest中定义多个fixture,一个fixture可以是另一个fixture的前后置,期间还是用yield隔开前后置

参数化与数据驱动框架实现
使用@pytest.mark.parametrize(“case”,cases)实现参数化
当每个测试用例需要不同的测试数据是,可以直接获取

调整测试用例的执行顺序
比如:添加功能模块的用例要先执行,删除功能模块的用例要后执行,可以使用第三方插件
pip install pytest-ordering
在测试方法上加上装饰器:@pytest.mark.last (—最后一个执行) @pytest.mark.run(order=1) (第几个执行)

多线程并行与分布式执行
当用例数量太多时,可以考虑多线程并行,分布式执行
插件:pip3 install pytest-xdist
多个cpu执行,pytest -n 3
 

import pytest
import time

@pytest.mark.parametrize('x',list(range(10)))
def test_somethins(x):
    time.sleep(1)

pytest -v -s -n 5 test_xsdist.py  ----一次执行5个

 九、allure测试报告

 定制化测试报告
Feature: 标注主要功能模块
Story: 标注Features功能模块下的分支功能
Severity: 标注测试用例的重要级别
Step: 标注测试用例的重要步骤
Issue和TestCase: 标注Issue、Case,可加入URL

上述组合框架可以快速简单的实现相应的接口测试,简单上手快,同学们可以亲手实验一下。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[HarmonyOS] 解决HMRouter路由地址无法抽取的问题

解决HMRouter路由地址无法抽取的问题 背景 最近开始学习HarmonyOS开发,搭建项目的时候采用了 HMRouter 路由框架,在项目里使用到路由跳转,官方链接在这: https://gitee.com/hadss/hmrouter/blob/master/HMRouterLibrary/README…

ElasticSearch学习了解笔记

搜索引擎的原理: 1、查询分析(自然语言处理)理解用户需求 2、分词技术 3、关键词搜索匹配 4、搜索排序 lucence Lucene 是一个成熟的权威检索库 Elasticsearch 的搜索原理简单过程是,索引系统通过扫描文章中的每一个词&#xff…

ffmpeg视频滤镜:提取缩略图-framestep

滤镜描述 官网地址 > FFmpeg Filters Documentation 这个滤镜会间隔N帧抽取一帧图片&#xff0c;因此这个可以用于设置视频的缩略图。总体上这个滤镜比较简单。 滤镜使用 滤镜参数 framestep AVOptions:step <int> ..FV....... set frame st…

【C++11】可变参数模板/新的类功能/lambda/包装器--C++

文章目录 一、可变参数模板1、基本语法及原理2、包扩展3、empalce系列接口 二、新的类功能1、默认的移动构造和移动赋值2、成员变量声明时给缺省值3、defult和delete4、final与override 三、STL中一些变化四、lambda1、lambda表达式语法2、捕捉列表3、lambda的应用4、lambda的原…

云网络基础- TCP/IP 协议

文章目录 典型服务模式TCP/IP 协议设置和查看IPIP地址的分类:IP地址组成: 网络位主机位组成克隆:产生一台新的虚拟机win2008 典型服务模式 • C/S,Client/Server架构 – 由服务器提供资源或某种功能 – 客户机使用资源或功能 TCP/IP 协议 • TCP/IP是最广泛支持的通信协议集合…

java基础知识(Math类)

引入&#xff1a;Math 类包含用于执行基本数学运算的方法&#xff0c;如初等指数、对数、平方根 import java.util.Math 1.abs绝对值 int abs Math.abs(-9); 2.pow求幂 double pow Math.pow(2,4); 3.向上取整 double ceil Math.ceil(3.9);//ceil 4 4.向下取整 dou…

什么是 WPF 中的依赖属性?有什么作用?

依赖属性&#xff08;Dependency Property&#xff09;是 WPF 的一个核心概念&#xff0c;它为传统的 .NET 属性提供了增强功能&#xff0c;支持绑定、样式、动画和默认值等功能。通过依赖属性&#xff0c;WPF 提供了一种灵活的数据驱动的方式来处理 UI 属性。 1. 什么是依赖属…

线性代数空间理解

学习线性代数已经很久&#xff0c;但是在使用过程中仍然还是不明所以&#xff0c;比如不知道特征向量和特征值的含义、矩阵的相乘是什么意思、如何理解矩阵的秩……。随着遇到的次数越来越多&#xff0c;因此我决定需要对线性代数的本质做一次深刻的探讨了。 本次主要是参考了3…

Jmeter的组件执行顺序

在 Apache JMeter 中&#xff0c;组件的加载和执行顺序遵循一定的规则&#xff0c;但有些组件在同一层级中可能会根据它们在测试计划中的位置来决定具体的执行顺序。以下是这些组件的大致加载和执行顺序&#xff0c;以及哪些组件属于同一层级&#xff1a; 线程组&#xff08;Th…

计算机网络八股整理(一)

计算机网络八股文整理 一&#xff1a;网络模型 1&#xff1a;网络osi模型和tcp/ip模型分别介绍一下 osi模型是国际标准的网络模型&#xff0c;它由七层组成&#xff0c;从上到下分别是&#xff1a;应用层&#xff0c;表示层&#xff0c;会话层&#xff0c;传输层&#xff0c;…

今天你学C++了吗?——C++中的类与对象(第二集)

♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ ✨✨✨✨✨✨ 个…

【C++习题】14.滑动窗口_找到字符串中所有字母异位词

文章目录 题目链接&#xff1a;题目描述&#xff1a;解法C 算法代码&#xff1a;图解 题目链接&#xff1a; 438. 找到字符串中所有字母异位词 题目描述&#xff1a; 解法 暴力解法&#xff1a; 字母排序后运用滑动窗口解题。 滑动窗口哈希表&#xff1a; 我们可以优化一下&am…

Spring Boot集成MyBatis-Plus:自定义拦截器实现动态表名切换

Spring Boot集成MyBatis-Plus&#xff1a;自定义拦截器实现动态表名切换 一、引言 介绍动态表名的场景需求&#xff0c;比如多租户系统、分表分库&#xff0c;或者不同业务模块共用一套代码但操作不同表。说明 MyBatis-Plus 默认绑定固定表名的问题。 二、项目配置 1. 集成 M…

深入探索API爬虫工作的技术难点与高效解决思路

在大数据与信息化高速发展的今天&#xff0c;API&#xff08;应用程序编程接口&#xff09;爬虫成为了数据收集与分析的重要工具。然而&#xff0c;API爬虫工作并非一帆风顺&#xff0c;它面临着诸多技术挑战。本文将深入探讨几个API爬虫工作的技术难点&#xff0c;并提出相应的…

css效果

css炫彩流光圆环效果 <!DOCTYPE html> <html><head><meta charset"utf-8" /><title></title><style>*{margin: 0;padding: 0;}body{width: 100%;height: 100vh;}.container{position: relative;width: 100%;height: 100vh…

arm Rk1126 编译Qt工程报错: Could not find qmake spec

首先修改qmake.conf文件&#xff0c;配置好正确的交叉编译工具&#xff1a; 然后执行编译&#xff1a; /opt/Rv1126/Rv1126-盒子代码/rv1126-qt5-sdk/bin/qmake untitled.pro 报错。 原因&#xff1a;中文路径。修改路径为英文路径即可

zabbix监控进程

使用zabbix监控指定的进程&#xff0c;现在主要使用监控一些用java python写的一些微服务模块&#xff0c;我这边用于演示就直接使用nginx服务来演示了 创建监控项 name - 进程名称&#xff08;默认为 ALL PROCESSES);user - 用户名&#xff08;默认为 all users);state - 可能…

php 导出excel 一个单元格 多张图片

public function dumpData(){error_reporting(0); // 禁止错误信息输出ini_set(display_errors, 0); // 不显示错误$limit $this->request->post(limit, 20, intval);$offset $this->request->post(offset, 0, intval);$page floor($offset / $limit) 1 ;$wh…

【C++11】锋芒毕露

(续) 一、可变参数模板 C11支持可变参数模板&#xff0c;也就是说支持可变数量参数的函数模板和类模板&#xff0c;可变数目的参数被称 为参数包&#xff0c;存在两种参数包&#xff1a;模板参数包&#xff0c;表示零或多个模板参数&#xff1b;函数参数包&#xff1a;表示零…

用户管理(MySQL)

目录 1用户管理&#xff08;MySQL&#xff09; 1.1 用户 1.1.1 用户信息 1.1.2 创建用户(后%是可以任意远端登录) 1.1.3 刷新一下 1.1.4 删除用户 1.1.5 修改用户密码 1.2 数据库的权限 1.2.1 登录创建用户 1.2.2给权限 1.2.2.1 把jj数据库中uu表的权限给woaini这个…