pytest 基础
#模块以test_开头或者以_test结尾
#类名以Test开头
#方法以test开头
#运行方式
# 主函数运行
pytest.main([‘-s’,“指定运行的模块名(执行 )”])
运行所有: pytest.main()
指定模块: pytest.main([‘-s’,“指定运行的模块名.py”])
指定目录: pytest.main([‘-s’,“./用例模块目录”])
通过nodeid指定用例运行:
pytest.main([‘-vs’,‘./文件目录/文件模块.py::函数’,‘-n=2’])
pytest.main([‘-vs’,‘./文件目录/文件模块.py::类名::方法’])
# 命令行运行
-s : 表示输出调试信息,包括打印的信息
-v : 表示输出模块名,类名,用例名
-n : 支持多线程或者分布式运行
例: pytest -vs -n 2 --reruns=2
–reruns num : 表示失败重跑
-x : 表示有一个用例报错,就停止执行
–maxfail num :表示有num失败,就停止执行
-k : 表示根据测试用例函数名的部分字符串,执行用例
例: pytest -vs -k “ao”
-m : 表示分组
例: pytest -vs -m “smock or usermange” (or 或,and与)
用例分组需要通过装饰器进行分组
@pytest.mark.smock
@pytest.mark.usermange
–html : 表示生成HTML报告
pytest -vs
# 通过pytest.ini 方式进行运行
位置:放置在项目的根目录
编码格式 :ANSI
作用:改变pytest的默认格式
运行规则:不管是那种运行模式,都会
[pytest]
#命令行参数,用空格进行分开
addopts = -vs
#测试用例文件夹,可以自己配置
testpath =
#配置测试搜索的模块文件名称
python_files = test_.py
#配置测试搜索的测试类名
python_classes = Test

#配置测试搜索的测试函数名
python_functions = test
#分组执行
markers =
#执行测试用例的顺序
unittest Ascall码执行
pytest 默认顺序执行
@pytest.mark.run(order=1)
#如何分组执行(smock,分模块运行)
smoke 用例需要挑选部分用例执行
@pytest.mark.smock
@pytest.mark.usermange

#pytes跳过用例执行
#无条件跳过
@pytest.mark.skip(reason=‘msg’)
#有条件跳过
@pytest.mark.skip(name = ‘’,reason=‘msg’)
#生成测试报告
pytest --html ./report.html
#部分用例的前后置 fixtrue
scope 表示作用域,默认是 function 函数 class 类 module 模块 package/session 会话
params 数据驱动
autous 自动执行,为true 表示在执行用例前执行一次在所有用例执行完后再执行,只执行一次
ids
name 给fixtrue作用的函数重命名
#作用于方法上的前后置
@pytest.fixtrue(scope=“function”)
def exec_data():
print(“数据库查询,类似于前置”)
yield
print(“数据库校验,类似于后置”)
class TestMs:
def test_01(self,exec_data):
print(“执行exec_data后再执行该用例”)
#作用于类上,类下所有的方法都会使用该前后置方法
@pytest.fixtrue(scope=“class”)
def exec_data():
print(“数据库查询,类似于前置”)
yield
print(“数据库校验,类似于后置”)
@pytest.mark.usefixtures(‘exec_data’)
class TestMs:
def test_01(self):
print(“”)
#作用于会话上的前后置,一般会结合conftest.py 文件一起使用
conftest.py 单独用于存放fixture 固件,使用时不需要导包
可以使用多个conftest.py
pytest 参数化
pytest fixture(fixture调用fixture,类似于顺序调用)
叠加使用usefixtures(内存先调用,外层再调用)
使用fixtures 进行参数化
parameterize 叠加使用是内层对外层进行组合使用
上传实体文件和获取文件信息
import json
import requests
import hashlib
import time
import jsonpath

应用信息

app_id = “AK20220706VREUUA”
app_key = “43833160911b20adfb6bc22c2a10a64f”
openapi_host = “http://10.13.87.81:9003”

class SendRequestKing:
def init(self,app_id,app_key,openapi_host):
self.app_id = app_id
self.app_key = app_key
self.openapi_host = openapi_host

def _sig(self,content_md5, url, date):sha1 = hashlib.sha1(self.app_key.lower().encode('utf-8'))sha1.update(content_md5.encode('utf-8'))sha1.update(url.encode('utf-8'))sha1.update("application/json".encode('utf-8'))sha1.update(date.encode('utf-8'))return "WPS-3:{0}:{1}".format(self.app_id,sha1.hexdigest())#return "WPS-3:%s:%s" % (app_id, sha1.hexdigest())def get_token(self,scop):url = "/auth/v1/app/inscope/token?app_id={0}&scope={1}".format(self.app_id,scop)rsp = self.request("get", self.openapi_host, url)rsp = rsp.json()app_token = jsonpath.jsonpath(rsp, '$..app_token')[0]print(app_token)return app_tokendef request(self,method:str, host, uri, body=None, cookie=None, headers=None):requests.packages.urllib3.disable_warnings()method = method.upper()if method == "PUT" or method == "POST" or method == "DELETE":body = json.dumps(body)if method == "PUT" or method == "POST" or method == "DELETE":content_md5 = hashlib.md5(body.encode('utf-8')).hexdigest()print("content_md5", content_md5)else:content_md5 = hashlib.md5("".encode('utf-8')).hexdigest()print("content_md5", content_md5)date = time.strftime("%a, %d %b %Y %H:%M:%S GMT", time.gmtime())print(date)header = {"Content-type": "application/json"}header['X-Auth'] = self._sig(content_md5, uri, date)header['Date'] = dateheader['Content-Md5'] = content_md5header['W-SCENE-ID'] = content_md5if headers != None:header = {}for key, value in headers.items():header[key] = valueurl = host + '/open' + uriprint("请求URL", url)rsp = requests.request(method, url, data=body,headers=header, cookies=cookie, verify=False)# print("[response]: status={0},URL={1},data={2}".format(r.status_code, url, r.text))# print("+++")return rsp

if name == ‘main’:
#测试获取token
gettoken = SendRequestKing(“AK20220706VREUUA”,“43833160911b20adfb6bc22c2a10a64f”,“http://10.13.87.81:9003”)
scop = “file_preview,file_edit,file_format_control,app_files_synerg_mgr”
#测试调用应用文档接口
app_token = gettoken.get_token(scop)
print(app_token)
url = “/appfile/v1/files/new?app_token={0}”.format(app_token)
body = {“file_name”: “0111-file.doc”, “file_type”: “file”}
rsp = gettoken.request(“post”,openapi_host,url,body)
print(rsp)import jsonpath
import pytest
import os
from common.handlerequestks import SendRequestKing
from common.config import conf
from common.handlefile import encrypt, upload_entity_file
from common.handleyaml import OperYaml
from common.dirpath import DATAPATH

class TestAppfile():
app_id = conf.get(“env”, “app_id”)
app_sk = conf.get(“env”, “app_sk”)
open_host = conf.get(“env”, “open_host”)
scop = conf.get(“env”, “scop”)
appfile = SendRequestKing(app_id, app_sk, open_host)
app_token = appfile.get_token(scop)

# casedates = OperYaml().readyaml(os.path.join(DATAPATH,conf.get("createnew","yamlfile")))# 创建文件获取文件ID
@pytest.fixture()
def get_file_info(self):# 新建文件url = conf.get('createnew', 'url')url = url.format(self.app_token)case = {"file_name": "test.doc", "file_type": "file", "parent_id": 0}rsp = (self.appfile.request("post", self.open_host, url, case)).json()file_id = jsonpath.jsonpath(rsp, '$..file_id')[0]print("新建文件ID", file_id)# 上传实体文件请求url = conf.get('newversionres', 'url')url = url.format(self.app_token, file_id)sha1, size = encrypt(r'E:\Pyproject\py_interface\filestore\文字类型\test.doc', 'sha1')case = {"hash_value": sha1, "file_size": size}rsp = (self.appfile.request("post", self.open_host, url, case)).json()# print("上传实体文件请求的返回+++{0}".format(rsp))upload_url = jsonpath.jsonpath(rsp, '$..url')[0]feedback = jsonpath.jsonpath(rsp, '$..feedback')[0]# print(upload_url,feedback)# 上传实体文件rsp = upload_entity_file(upload_url, r'E:\Pyproject\py_interface\filestore\文字类型\test.doc')# print("上传实体文件返回{0}".format(rsp))sha1 = jsonpath.jsonpath(rsp.json(), '$..sha1')[0]etag = rsp.headers['etag']etag = etag.split('"')[1]# print(f"上传实体文件返回的etag+++{etag}")return file_id, sha1, etag, feedback, sizedef test_newversionsub(self, get_file_info):file_id, shal, etag, feedback, size = get_file_infoprint(file_id, shal, etag, size)url = conf.get('newversionsub', 'url')url = url.format(self.app_token, file_id)body = {"hash_value": shal,"file_size": size,"feedback": feedback,"etag": etag}rsp = self.appfile.request("post", self.open_host, url, body)print(rsp.json())

if name == ‘main’:
pytest.main([‘test_newversionsub.py’, ‘-sv’])

import pytest
class TestLogin:

@pytest.fixture()
def get_file_id(self):print("this is get_file_id")return "a"@pytest.fixture()
def get_upload(self):print("this is get_upload")return "b"
#采用随机生成文件,然后进行上传文件
@pytest.fixture()
def get_etag(self,get_upload,get_shal):print("this is get_etag")etag = get_upload+"e"return etag@pytest.fixture()
def get_shal(self):print("this is get_shal")return "d"def test_login(self,get_file_id,get_etag,get_shal):print(get_file_id,get_etag,get_shal)print("test login")

if name == ‘main’:
pytest.main([‘-s’])

pytest setup teardown
pytest parametrize给夹具传参
class TestAppfile():
app_id = conf.get(“env”, “app_id”)
app_sk = conf.get(“env”, “app_sk”)
open_host = conf.get(“env”, “open_host”)
scop = conf.get(“env”, “scop”)

# 创建文件获取文件ID
@pytest.fixture()
def get_file_info(self,request):# 新建文件print("this get file_info ",request.param)return 'a'@pytest.mark.parametrize('get_file_info',[1,2,3,4,5,6],indirect=True)
def test_newversionsub(self, get_file_info):print("this is submit")

if name == ‘main’:
pytest.main([‘test_pytest.py’, ‘-sv’])
#运行结果如下图

#indirect = True 是将get_file_info作为一个函数去执行,而不是一个参数,[1,2,3,4,5,6]则是这个函数的入参。data本质是一个列表,如果入参是fixture是单个入参,则data可以定义为
#来源于博客 https://blog.csdn.net/bo_mask/article/details/125421041pytest parametrize叠加,实现组合场景(里层是场景,外层是对应场景的用例)
class TestAppfile():
# 创建文件获取文件ID
@pytest.fixture()
def get_file_info(self,request):
# 新建文件
print("this get file_info ",request.param)
return ‘a’

@pytest.mark.parametrize('data', ["a", "b", "c"])
@pytest.mark.parametrize('get_file_info',[1,2],indirect=True)
def test_newversionsub(self, get_file_info,data):print("this is submit",get_file_info)print("this is ok ",data)

if name == ‘main’:
pytest.main([‘test_pytest.py’, ‘-sv’])
#@pytest.mark.parametrize(‘get_file_info’,[1,2],indirect=True) 可理解为场景,场景1下执行用例data,场景2下执行data

[pytest]夹具使用注意事项相关推荐

  1. pytest官方文档 6.2 中文翻译版(第五章):pytest夹具:明确的,模块化的,可扩展的

    软件测试夹具是用于初始化的测试功能的.它们提供了一个固定的基线,以便测试能够可靠地执行并产生一致的,可重复的结果.初始化可能会设置服务.状态或其他运行环境.测试函数可以通过参数访问测试夹具,通常在测试 ...

  2. 接口自动化系列一: Pytest 夹具统一鉴权, 统一日志输出

    统一鉴权的意义 接口自动化一般需要登录获得鉴权信息, 供各个suite和case使用, 因此登录鉴权适合定义在Session级别的夹具中, 供所有用例共享. 示例: @pytest.fixture(s ...

  3. pytest合集(8)— 测试用例和夹具的参数化

    一.测试用例参数化 pytest.mark.parametrize() 语法糖: parametrize(argnames, argvalues, indirect=False, ids=None,  ...

  4. 单元测试界的高富帅,Pytest框架,手把手教学,高阶用法实战

    一.xunit 风格的前后置方法 1.函数用例的前后置方法 在模块中以函数形式定义用例,可以通过 setup_function 和 teardown_function 来定义函数用例的前后置方法,使用 ...

  5. 自动化测试框架-pytest框架入门篇

    前段时间,九九姐更新了自动化测试中unittest框架,然后有很多小伙伴私聊九九姐,说想学习一下pytest框架的内容.既然大家已经说话了,九九姐怎么能不安排呢,所以今天就给大家说一说pytest框架 ...

  6. Python3《零基础小白从入门到实战》之“pytest测试框架之测试夹具(Fixture) ”

    测试夹具(Fixture)是什么? 在测试过程当中,有时你需要提前给你的测试用例去准备一个运行环境.这个测试环境通常来说被称为测试夹具(Fixture),又被称为固定装置.测试固件等. 当你要测试一个 ...

  7. 接口自动化测试实战之pytest框架+allure讲解

    一.前言 本文章主要会讲解Python中pytest框架的讲解,介绍什么是pytest.为何要测试.为何使用以及参考和扩展等等,话不多说,咱们直接进入主题哟. 二.pytest讲解 2.1 什么是py ...

  8. pytest官方文档 6.2 中文翻译版(第一章):安装和入门指南

    安装和入门指南 Python版本: Python 3.6, 3.7, 3.8, 3.9, PyPy3 平台: Linux and Windows PyPI 包名: pytest Documentati ...

  9. 关键字驱动实现web自动化

    接口自动化测试步骤几乎是一样的,可以用excel写测试用例,通过ddt实现数据驱动,而web自动化不符合测试步骤一致的要求,用ddt实现数据驱动并不理想,这时候可以使用关键字驱动实现web自动化. 一 ...

最新文章

  1. 工作5年后才明白的道理:不起眼的技能中,藏着你的未来
  2. tomcat服务器两个端口配置两个项目,Tomcat 7通过设置不同的端口部署两个项目
  3. 彻底搞懂 Git-Rebase
  4. 南华大学计算机学院足球队,球场健儿,不言放弃——记南华大学“新生杯”足球赛...
  5. 一维数组工具 OneArryasTools v1.1(doc生成正常)
  6. [SQLITE_READONLY] Attempt to write a readonly databse (attempt to write a readonly database)
  7. WPF 和 windows Form Application的区别
  8. 下一个计划 : .NET/.NET Core应用性能管理
  9. Apache + Tomcat 配置多个应用
  10. java 异常捕获抛出_JAVA异常处理捕获与抛出原理解析
  11. Java——Map 集合
  12. [leetcode] 406. Queue Reconstruction by Height (medium)
  13. 单页面应用的路由问题
  14. java 485通讯_JAVA开发工程师 | 广州市三地信息技术有限公司
  15. VS编译器 :LNK链接错误汇总:LNK2001 / LNK2005 / LNK2019 / LNK1120
  16. LaTeX插入参考文献教程 | 非BibTeX格式
  17. JS 判断用户设备是IOS 还是 Android
  18. 如何在电脑上查看手机网页源代码?
  19. 零基础怎样自学编程?新手如何学习编程?编程学习入门指南
  20. 学士后java课程内容_java学士后详细课程

热门文章

  1. poco mysql 安装,CentOS 上安装 POCO - 文章教程
  2. vi编辑器 每日练习题
  3. 大泉州人才网qzrencai.com整站采集程序 v1.1
  4. sql语句查询 近7天,三十天数据
  5. 如何用数据库寻找相似的历史k线
  6. Torch 训练的一些注意点:优化器params参数 与 lr 调度器篇 [1]
  7. 专题2:弹性力学中平面问题的基本理论(2-1 平面应力问题与平面应变问题 2-2 平衡微分方程 2-3 斜面上的应力及主应力)
  8. 电工基础知识问答精华
  9. 影院服务器可以给投影机信号吗,工程投影机能否在家里使用?能实现家用影院吗?...
  10. 第三方(微信小程序)连接OneNET平台