全网最全Pytest资料整理

前言:

本次是将我最近学习的pytest的相关方法整理出来,希望对大家有所帮助,更多学习资料可以查看:
https://docs.qq.com/doc/DWmxXaVdLUlVyTkZL

1 pytest安装

pip install pytest
  1. pytest是一个非常成熟的单元框架
  2. pytest可以和其他框架整合,例如requests,httprunner
  3. pytest可以实现测试用例跳过、失败重跑
  4. pytest可以和allure生成非常美观的测试报告
  5. pytest可以和jenkins持续集成
  6. pytest有非常强大的插件,并且你这些插件能实现很多的实用的操作
pytest-xdist 测试用例分布式执行,多cpu并发
pytest-ordering 用于改变测试用例的执行顺序
pytest-rerunfailures 用于失败重跑
allure-pytest 用于生成美观的测试报告

2 规范

用Pytest写用例时候,一定要按照下面的规则去写,否则不符合规则的测试用例是不会执行的
1.测试方法必须以test开头
2.测试类必须以Test开头,并且不能有init方法

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dzGECqM7-1677554325831)(assets/image-20221027095044327.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-prqhy8Yq-1677554325832)(assets/image-20221027095723592.png)]

class TestClass:
    def test_one(self):
        x = "this"
        assert "h" in x

    def test_two(self):
        x = "hello"
        assert "h" in x

    def two(self):
        x = "hello"
        assert "0" in x

3 断言支持

assert xx :判断 xx 为真
assert not xx :判断 xx 不为真
assert a in b :判断 b 包含 a
assert a == b :判断 a 等于 b
assert a != b :判断 a 不等于 b
  assert dict["code"]=='0'
  assert response.json()['message']=='success'
@pytest.mark.skip 跳过某个单元测试

4 参数化支持(重点)

@pytest.mark.parametrize("username",['admin','张三','admin'])
def test1(username):
    print(username)

参数化中文乱码支持 根目录新建conftest.py

def pytest_collection_modifyitems(items):
    """
    该方法解决
    """
    for item in items:
        item.name = item.name.encode("utf-8").decode("unicode_escape")
        item._nodeid = item.nodeid.split('::')[0] +'::'+ item.nodeid.split('::')[1].encode("utf-8").decode("unicode_escape")
pytest会默认读取conftest.py里面的所有fixture

conftest.py 文件名称是固定的,不能改动

不同目录可以有自己的conftest.py,一个项目中可以有多个conftest.py

测试用例文件中不需要手动import conftest.py,pytest会自动查找
#多参数 集合(元组/集合/set)
@pytest.mark.parametrize("username,pwd",[('admin','123456'),('test1','123')])
def test2(username,pwd):
    print(username,pwd)


@pytest.mark.parametrize("username,pwd",[['admin', '123456'], ['test1', '123456']])
def test3(username,pwd):
    print(username,pwd)
    

集合(字典)

test_data = [
    {
        'case': '登入成功',
        'usr': 'admin',  # 正常登入
        'psw': '123456'
    },
    {
        'case': '账号不存在',
        'usr': 'admin1',  # 账号不存在
        'psw': '123456'
    },
    {
        'case': '密码错误',
        'usr': 'admin',  # 密码错误
        'psw': '12345'
    },
    {
        'case': '账号或密码为空',
        'usr': '',  # 账号或密码为空
        'psw': ''
    },
]

@pytest.mark.parametrize('param', test_data)
def test4(param):
    usr = param.get('usr')
    psw = param.get('psw')
    print(f'usr: {usr} , psw: {psw}')

ids 优化结果提示

@pytest.mark.parametrize('param', test_data, ids=[data.get('case') for data in test_data])
def test4(param):
    usr = param.get('usr')
    psw = param.get('psw')
    print(f'usr: {usr} , psw: {psw}')
[data.get('case') for data in test_data] 是推导式

推导式是Python的一种独有特性。是Python的可以从一个数据序列构建另一个新的数据序列的结构体

不用推导式

list=[]
for item in test_data:
    list.append(item['case'])

多层嵌套结构

# 笛卡尔积,组合数据
data_1 = [1, 2, 3]
data_2 = ['x', 'y']
@pytest.mark.parametrize('a', data_1)
@pytest.mark.parametrize('b', data_2)
def test_parametrize_1(a, b):
 print(f'笛卡尔积 测试数据为 : {a}{b}')

5 参数化csv整合

id.csv

id,message
1,success
3,success
4,success
5,success
6,success
7,success
-1,skuId不合法
path =os.path.join(get_project_path(),"files","id.csv")


#list
def get_csv_data1():
   list=[]
   with open(path, encoding="utf-8") as f:
       csv_reader = csv.reader(f)
       next(csv_reader)
       for line in csv_reader:
          list.append(line)
   return list

@pytest.mark.parametrize('id,message', get_csv_data1())
def test_Get1(id,message):
    url=host+"/pinter/com/getSku?id="+id

@pytest.mark.parametrize('id,message', csv_list,ids=[i[0] for i in csv_list])

#字典类型
def get_csv_data2():
   list=[]
   with open(path, encoding="utf-8") as f:
       csv_reader = csv.DictReader(f)
       for line in csv_reader:
          list.append(line)
   return list

@pytest.mark.parametrize('dic', get_csv_data2())
def test_Get2(dic):
    print(dic)
    ....
    assert dict["code"]=='0'
    assert response.json()['message']=='success'

6 失败重试

​ 平时在做接口测试的时候,经常会遇到网络抖动或者环境问题导致测试用例运行失败,而这个并不是我们想要的结果,我们想要重新运行失败的测试用例

pip install pytest-rerunfailures
pip show pytest-rerunfailures
@pytest.mark.flaky(reruns=3)  #失败最大试3次 
@pytest.mark.flaky(reruns=3,reruns_delay=2) #失败最大3次 ,每次延迟2秒执行

7 执行顺序插件

pytest执行顺序一般是按照从上往下的顺序执行的,如果使用过程中想要指定顺序,可以使用order标签

pip install pytest-ordering
pip show pytest-ordering
@pytest.mark.run(order=2)

8 报表插件pytest-allure

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DOulawkB-1677554325833)(assets/image-20221027114913668.png)]

pip install allure-pytest 
pip show allure-pytest
pytest 脚本名称 --alluredir ./report

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jg0KxlCU-1677554325834)(assets/image-20221027114930351.png)]

解析 report

需要 allure-commandline-2.13.3.zip 工具

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sxg8HyUY-1677554325834)(assets/1589623466077.png)]e

mac

https://blog.csdn.net/u014015919/article/details/90292041

allure --version

allure serve report

单独main方法运行 (需要单独建py文件)

 pytest.main(['-s','test_allure02.py','--clean-alluredir','--alluredir=allure-results'])
 os.system(r"allure generate -c -o allure-report")

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JN1zuXDu-1677554325834)(assets/image-20221029171628979.png)]

-q: 安静模式, 不输出环境信息

-s: 详细打印

-v: 更丰富信息模式, 输出更详细的用例执行信息

8.1 allure扩展注解(了解)

@allure.parent_suite,@allure.suite,@allure.sub_suite对应的是
1,2,3级目录
@allure.parent_suite('我是parent_suite')
@allure.suite('我是suite')
@allure.sub_suite('我是sub_suite')

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cvPZJ2FA-1677554325835)(assets/image-20221029181216352.png)]

@allure.feature('测试参数化')
@allure.id('我是id')
@allure.title('我是title')
@allure.link('https://www.baidu.com/', LinkType.LINK, '我是link')
@allure.label('我是label')
@allure.issue('https://www.baidu.com/', '我是issue')
@allure.description('我是description')
@allure.severity('我是severity')

9 并行执行

多进程

pip  install pytest-xdis

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jmNc4Vfk-1677554325835)(assets/image-20221029190326147.png)]

模拟1000测试用例

data_1 = [x for x in range(10)]
data_2 = [x for x in range(100)]
@pytest.mark.parametrize('a', data_1)
@pytest.mark.parametrize('b', data_2)
def test_parametrize_1(a, b):
 #sleep(0.01)
 print(f'笛卡尔积 测试数据为 : {a}{b}')

10 fixture特性

@pytest.fixture()
def get_token():
  url = host +'/pinter/bank/api/login2'
#表单参数
  data = {
  'userName':'admin',
  'password':'1234'
  }
  resp = requests.post(url=url,data=data)
  resp_json = resp.json()
  print(resp_json)
  token = jsonpath.jsonpath(resp_json, '$.data')[0]  # 使用jsonpath从响应结果中提取
  return token

def test_query2(get_token):
  url = host + '/pinter/bank/api/query2?userName=admin' # 接口地址
  headers = {
    'testfan-token':get_token
  }
  resp = requests.get(url=url,headers=headers)
  status_code = resp.status_code #获取响应状态码
  print('响应状态码:{}'.format(status_code))
  text = resp.text #获取响应内容,结果类型是字符串
  print('响应内容:{}'.format(text))
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值