测试接口及pytest
<!doctype html>
测试接口
import requests except = {'title':'V2EX'} response = requests.get(url='https://www.v2ex.com/api')
if response.json()['title'] == except['title']:
print('断言成功')
assert 1
else:
print('断言失败')
assert 0
pytest
pytest使用手册:https://learning-pytest.readthedocs.io/zh/latest/
定义:
是python的单元测试框架
特点:
- 入门简单易上手,文档支持好
- 支持单元测试和功能测试
- 支持参数化
- 可以跳过指定用例,或对某些预期失败的case标记成失败
- 支持重复执行失败的case
- 支持运行由unittest编写的测试用例
- 有很多第三方插件,并且可自定义扩展。
- 方便和支持继承工具进行集成
下载install pytest
测试之前的准备
M:\py_tests\ # 我的是M盘的 py_tests 目录,所有操作都在 py_tests 目录内完成
├─scripts
│ ├─test_case_dir1
│ │ ├─test_case_02.py # 用例脚本文件
│ │ └─__init__.py
│ ├─test_allure_case.py # 脚本文件
│ ├─test_case_01.py # 脚本文件
│ └─__init__.py
├─report
│ ├─report.html # pytest-html生成的用例报告
│ ├─assets # allure的依赖目录
│ ├─result # allure生成的用例数据
│ └─allure_html # allure生成的用例报告目录
| └─index.html # allure生成的最终的html类型的测试报告
├─case_set.py
├─demo0.py # 用例脚本文件
├─demo1.py # 用例脚本文件
├─pytest.ini # 配置文件
└─__init__.py
简单示例
启动pytest框架方式
方式一:
直接执行py文件
import requests import pytestexpect ={'title':'V2EX'}
def test_case_01():
response = requests.get(url='https://www.v2ex.com/api/site/info.json')
print(response.json())if response.json()['title'] == expect['title']:
print('断言成功')
assert 1
else:
print('断言失败')if name == 'main':
pytest.main(['-s','run.py'])
pytest只执行test开头的用例,所以用例必须是test开头的函数
如何或去当前脚本中所有的变量或函数:
ptint(dir()) #获取当前脚本中所有的变量
demo1.py
import pytestdef test_case01():
print('执行用例01.........')
assert 0 #断言失败断言就是做出判断的语言,断言成功就是,将用例设置为成功,即断言成功
def test_case02():
print("执行用例02........")
assert 1 #断言成功
def custom_case03():
print("执行用例03.........")
assert 1 #断言成功
if name == "main":
pytest.main(["-s","demo1.py"])
上述代码执行之后结果:
E:\pycharm\解释器\python.exe F:/测试/day75/demo1.py ============================= test session starts ============================= platform win32 -- Python 3.6.8, pytest-5.3.2, py-1.8.0, pluggy-0.13.1 rootdir: F:\测试\day75 collected 2 items #表示执行2个用例demo1.py 执行用例01.........
F执行用例02........ #F表示用例执行失败
. #.表示该用例执行成功================================== FAILURES ===================================
_________________________________ test_case01 _________________________________报错信息,和错误位置
def test_case01():
print('执行用例01.........')
> assert 0 # 断言失败
E assert 0demo1.py:6: AssertionError
========================= 1 failed, 1 passed in 0.11s =========================
Process finished with exit code 0
脚本中的第一个用例执行失败;第二个用例执行成功;但是第三个也就是custom_case03并没有执行,由此知道pytest只识别以test_开头的用例
pytest.main(["-s","demo1.py"])参数说明
-s:表示输出用例的详细结果
demo1.py表示要执行的脚本名称
用例类的写法:
import pytest class TestCase(object): def test_case01(self): """用例01""" print('执行用例01') assert 0 #断言失败def test_case02(self):
"""用例02"""
print('执行用例02')
assert 1 #断言成功
if name=='main':
pytest.main(["-s","demo1.py"])
用法和unittest差不多,类名要以Test开头,并且其中的用例方法也要以test开头,然后执行也一样
setup和teardown
模块级别,也就是在整个测试脚本中的用例集执行前后,对应的是:
setup_module
teardown_moule
import pytest def teardown_module(): print('模块断开数据连接')def setup_module():
print('建立数据库连接连接成功')def test_cese_01():
print('用例函数郭建凯的成功啦')
assert 1
class TestCase(object):def test_cese_01(self):
print('用例类模块1郭建凯的成功啦')
assert 1if name == 'main':
pytest.main(['-s','run.py'])执行顺序为:
1 setup_module()
2 test_case_01()
3 class TestCase(object)
4 teardown_module()
函数级别的,也就是在测试用例函数执行前后,对应的是:
函数级别的,不参与类的用例,只对函数用例有效
setup_function
teardown_function
实例:
import pytest def teardown_function(): print('断开数据连接')def setup_function():
print('建立数据库连接连接成功')def test_cese_01():
print('郭建凯的成功啦')
assert 1if name == 'main':
pytest.main(['-s','run.py'])上述执行顺序为:先执行
1 setup_function()
2 test_case_01()
3 teardown_function()
类级别的,也就是测试用例类前后,对应的是
setup_class()
teardown_class()
import pytest def teardown_module(): print('模块断开数据连接')def setup_module():
print('建立数据库连接连接成功')def test_cese_01():
print('用例函数郭建凯的成功啦')
assert 1
class TestCase(object):def setup_class(self):
print('类级别的setup')def teardown_class(self):
print('类级别的teardown')def test_cese_01(self):
print('用例类模块1郭建凯的成功啦')
assert 1if name == 'main':
pytest.main(['-s','run.py'])执行顺序为:
1 def setup_module()
2 def test_case_01()
3 def setup_class(self)
4 def test_case_01(self)
5 def teardown_class(self)
6 def teardown_module()
类方法级别的,在每个类方法前后执行
setup_mothod
teardown_mothod
知识点补充:
import sys
def foo():
print('fooo.......')
if 'foo' in dir():
getattr(sys.modules[__name__].'foo')()
#反射getattr寻找脚本中有没有foo这个函数,有就执行
配置文件
pytest.ini
[pytest]
addopts = -s -v --html=report/report.html --alluredir ./report/result
testpaths = ./scripts
python_files = test_*.py #如果将test_*改为test_login.py,只执行脚本test_login.py
python_classes = Test*
python_functions = test_*
xfail_strict=true #我们将预期失败,结果却执行成功了的用例标记为执行失败
注意:在创建自动化脚本时py文件不能是有中文
skip(跳过用例)
class TestCase(object):def setup_class(self):
print('类级别的setup')
def teardown_class(self):
print('类级别的teardown')
@pytest.mark.skip(condition=True,reason='用例1')
#这是用例无条件跳过
def test_cese_01(self):
print('用例类模块1郭建凯的成功啦')
assert 1
def test_cese_02(self):
print('用例类模块2跳过测试成功啦')
assert 1
class TestCase(object):
def setup_class(self):
print('类级别的setup')
def teardown_class(self):
print('类级别的teardown')
@pytest.mark.skipif(condition=True,reason='用例1')
#这是只有当condition属性为真时用例跳过
def test_cese_01(self):
print('用例类模块1郭建凯的成功啦')
assert 1
def test_cese_02(self):
print('用例类模块2跳过测试成功啦')
assert 1
如果想要跳过整个类,在类前加入
@pytest.mark.skip(condition=True,reason='用例类') class TestCase(object):def setup_class(self):
print('类级别的setup')
def teardown_class(self):
print('类级别的teardown')
@pytest.mark.skipif(condition=True,reason='用例1')
#这是只有当condition属性为真时用例跳过
def test_cese_01(self):
print('用例类模块1郭建凯的成功啦')
assert 1
def test_cese_02(self):
print('用例类模块2跳过测试成功啦')
assert 1
标记预期
如果我们事先知道测试函数会执行失败,但又不想直接跳过,而是希望显示的提示
预期失败,但实际结果却执行成功
预期失败,实际结果也执行失败
pytest使用pytest.mark.xfail
用例
import pytestclass TestCase(object):
def setup_class(self):
print('类级别的setup')
def teardown_class(self):
print('类级别的teardown')
@pytest.mark.xfail(condition=True,reason='xxx')
def test_cese_01(self):
"""预期失败,实际成功"""
assert 1
@pytest.mark.xfail(condition=True,reason='oo')
def test_cese_02(self):
"""预期失败,实际失败"""
assert 0
结果:
scripts/test_case.py::TestCase::test_cese_01 FAILED
#FAILED 是表标记为失败,实际执行成功,因为配置文件设置后,也会执行失败
scripts/test_case.py::TestCase::test_cese_02 XFAIL
#XFAIL 是表示标记失败,实际执行也失败
scripts/test_case.py::TestCase::test_cese_01 XPASS
#XPASS是没有设置位置文件,标记失败,执行却成功了
参数化
@pytest.mark.parametrize("mobile",l) 作用是遍历列表中的每一个元素作为参数传给用例,在用例中断言
import requests import pytestl = [
{"url": "https://www.v2ex.com/api/site/info.json", "expect": {"title": "V3EX"}},
{"url": "https://cnodejs.org/api/v1/topics", "expect": {"success": True}}
]li = [100086,10010,110,120]
@pytest.mark.parametrize("mobile",l)
作用是遍历列表中的每一个元素作为参数传给用例,在用例中断言
def test_case(mobile):
response = requests.get(url=mobile['url'])
for title in mobile['expect']:
if mobile['expect'][title] != response.get(title,None):
assert mobile['expect'][title] != response.get(title,None)
else:
assert mobile['expect'][title] == response.get(title,None)
固件
固件(Fixture)是一些函数,pytest会在执行测试函数之前(或者之后)家在运行他们,也称夹具
我们可以利用固件做任何事情,其中最常见的可能就是数据库的初始链接和最后关闭操作
使用pytest.fixture()定义固件,下面是最简单的固件,访问主页前,必须先登录:
@pytest.fixture(scope="function") def login(): print('登录')def test_index1(login):
print('主页1')
def test_index2(login):
print('主页2')
作用域
在之前实例中,你可能会觉得,这跟setup和teardown的功能类似,但是fixture相对于setup
和teardown来说更灵活pytest通过scope参数来控制固件的适用范围,也就是作用域
在定义固件时,通过scope参数来控制固件的适用范围,也就是作用域。
在定义固件时,通过scope参数声明作用域,可选项有:
function:函数级,每个测试函数都会执行一次固件
class:类级别,每个测试类执行一次所有方法都可以使用
module:模块级,每个模块执行一次,模块内函数和方法都可以使用;
session:会话级,一次测试只执行一次,所有被找到的函数和方法都可以用
默认作用域是function
预处理和后处理
很多时候需要在测试前进行预处理(如新建数据库连接),并在测试完成进行清理(关闭数据库连接)。
当有大量重复的这类操作,最佳实践是使用固件来自动化所有预处理和后处理。
Pytest 使用 yield 关键词将固件分为两部分,yield 之前的代码属于预处理,会在测试前执行;yield 之后的代码属于后处理,将在测试完成后执行。
以下测试模拟数据库查询,使用固件来模拟数据库的连接关闭:
import pytest@pytest.fixture()
def db():
print('Connection successful')yield
print('Connection closed')
def search_user(user_id):
d = {
'001': 'xiaoming',
'002': 'xiaohua'
}
return d[user_id]def test_case_01(db):
assert search_user('001') == 'xiaoming'
def test_case_02(db):
assert search_user('002') == 'xiaohua'
结果:
M:\py_tests>pytestscripts/test_case_01.py::test_case_01 Connection successful
PASSEDConnection closedscripts/test_case_01.py::test_case_02 Connection successful
PASSEDConnection closed
====================================================== 2 passed in 0.15s =======================================================
可以看到在两个测试用例执行前后都有预处理和后处理。
常用插件
pytest中还有非常多的插件供我们使用,我们来介绍几个常用的。
先来看一个重要的,那就是生成测试用例报告。
pytest测试报告插件
想要生成测试报告,首先要有下载,才能使用。
下载
pip install pytest-html
如果下载失败,可以使用PyCharm下载,怎么用PyCharm下载这里无需多言了吧。
使用
在配置文件中,添加参数:
[pytest]
addopts = -s --html=report/report.html
完事之后,让我们继续终端中使用pytest重新跑测试用例,用例结果就不展示了,跟上面的结果一样,我们关注项目目录下的report/report.html文件,我们用浏览器打开它,你会发现:
allure框架
终端执行allure的语句
allure generate report/result -o report/allure_html --clean
浙公网安备 33010602011771号