本文介绍了pytest的安装,fixture的使用,参数化,命令行,断言,分组mark运行等
介绍了如何利用pytest生成log或html报告,以及pytest-bdd行为驱动模块的使用
pip install -U pytest
python -m pytest --version
import pytest
import time
def test_equal():
assert (1, 2, 3) == (1, 2, 3)
def test_not_equal():
assert 1 != 2
@pytest.mark.cal
def test_add():
assert 1 + 1 == 2
@pytest.mark.cal
def test_sub():
assert 1 - 1 == 0
# pytest 遵循测试发现规则,即当前目录及子目录下所有 test_*.py 或 *_test.py文件,和以test_开头的方法
pytest ./testdemo2/test_simple.py
也可以直接在IDE中运行,注意,右键运行时,只运行鼠标focus的函数,focus空白时运行该文件中所有函数
-v 显示详细信息 -k "xxx" 运行方法名中包含字符串的格式
-m 依照pytest.mark的分组进行测试 pytest --duration=3 运行最慢的三个
--maxfail=2 2次失败后停止
pytest test_Mod.py::test_func
pytest test_mod.py::TestCase::test_method
pytest --pyargs pkg.testing
pytest --showlocals # 在追溯信息中显示局部变量
pytest -l # 显示局部变量 (简写)
pytest --tb=auto # (默认) 第1和最后1条使用详细追溯信息,其他使用简短追溯信息
pytest --tb=long # 详尽,信息丰富的追溯信息格式
pytest --tb=short # 简短的追溯信息格式
pytest --tb=line # 每个失败信息一行
pytest --tb=native # Python标准库格式
pytest --tb=no # 不使用追溯信息s
pytest -ra
显示摘要
-f fail -E error -s skip -x xfail -X xsuccess -p success -P success and have print -a all
pytest --junitxml=path
pytest --resultlog=path
pip install pytest-html
-> pytest -v -m xx --html=path
可以在代码中直接传入命令行参数
if __name__ == ‘__main__‘:
pytest.main([‘-v‘, ‘-m cal‘, ‘--html=test1.html‘])
def add(a, b):
def throw_type_error(a):
if not isinstance(a, int) and not isinstance(a, float):
raise TypeError(‘please input nums‘)
throw_type_error(a)
throw_type_error(b)
return a + b
def test_add_exception():
with pytest.raises(TypeError):
add(‘a‘, ‘b‘)
def test_add_expection_message():
with pytest.raises(TypeError) as error_info:
add(‘a‘, ‘b‘)
error_message = error_info.value.args[0]
# 确定场景,add时需要抛出异常
# warining 断言
pytest.warns
hook方法中的pytest_assertrepr_compare
暂时不会用
使用装饰器
import pytest
class Calculator:
def __init__(self, num1, num2):
self.num1 = num1
self.num2 = num2
def add(self):
return self.num1 + self.num2
def sub(self):
return self.num1 - self.num2
@pytest.mark.parametrize(‘num1,num2,result‘, [
(1, 1, 2),
(1, 2, 3),
(3, 2, 2)
])
def test_calculator_add(num1, num2, result):
cal = Calculator(num1, num2)
assert result == cal.add()
@pytest.mark.parametrize(‘num1,num2,result‘, [
(1, 1, 2),
(1, 2, 3),
(3, 2, 2)
])
def test_calculator_add(num1, num2, result):
cal = Calculator(num1, num2)
assert result == cal.add()
parameter = [
(Calculator(1, 1), 2),
(Calculator(2, 3), 5),
(Calculator(1, 4), 3)
]
cal_ids = [f"{p[0].num1} + {p[0].num2} ={p[1]}" for p in parameter]
@pytest.mark.parametrize(‘cal_test,result‘,parameter,ids=cal_ids)
def test_cal_sum(cal,result):
assert result == cal.add()
fixture可以在测试之前或之后运行,用来准备测试环境
全局共享的fixture配置可以写入conftest.py文件中
共享的测试数据也可以写入conftest.py文件
@pytest.fixture()
def some_num():
return 4
def test_some_num(some_num):
assert some_num == 4
# 如利用selenium测试时所需准备的driver
@pytest.fixture()
def browser(scope=‘session‘):
b = webdriver.Chrome()
b.implicitly_wait(10)
yield b
b.quit()
# fixture使用yield函数之后的语句作为teardonw函数
使用addfinalizer(func__ name__)实现无论测试套中是否存在异常,都调用teardown函数,且支持多个teardown
# 方法一
@pytest.fixture
def make_customer_record():
def _make_customer_record(name):
return {
"name": name,
"orders": []
}
return _make_customer_record
def test_customer_records(make_customer_record):
customer_1 = make_customer_record("Lisa")
customer_2 = make_customer_record("Mike")
customer_3 = make_customer_record("Meredith")
# 方法二
import pytest
class Customer:
def __init__(self, name):
self.name = name
self.orders = []
def __call__(self):
return {‘name‘: self.name, ‘orders‘: self.orders}
def destroy(self):
self.name = None
self.orders = None
@pytest.fixture
def make_customer_record():
created_records = []
def _make_customer_record(name):
obj = Customer(name=name)
record = obj()
created_records.append(obj)
return record
yield _make_customer_record
for obj in created_records:
obj.destroy()
def test_customer_records(make_customer_record):
customer_1 = make_customer_record("Lisa")
customer_2 = make_customer_record("Mike")
customer_3 = make_customer_record("Meredith")
print(customer_1, customer_2, customer_3)
"""
{‘name‘: ‘Lisa‘, ‘orders‘: []} {‘name‘: ‘Mike‘, ‘orders‘: []} {‘name‘: ‘Meredith‘, ‘orders‘: []}
"""
基本简单参数化还是以parameterize为主
这里举例使用params和ids对数据进行预处理
def idfn(fixture_value):
if fixture_value == 0:
return "eggs"
else:
return None
@pytest.fixture(params=[0,1],ids=idfn)
def b(request):
return request.param
def test_b(b):
pass
其中,存在包含关系,可以多重包含从而实现每个setup,teardown和setupclass,teardownclass的关系
Scope | DESC |
---|---|
session | 一次run中的所有case |
module | 一个.py文件 |
class | 类的范围 |
function(default) | 方法(函数)的范围 |
--setup-show
filename | desc |
---|---|
pytest.ini | 改变pytest的默认行为 |
conftest.py | fixture配置 |
tox.ini | tox tools |
setup.cfg | influence setup.py |
[pytest]
addopts = -rsxX -l --tb=short --strict
; --rsxX 表示pytest报告 所有的用例被跳过,预计失败,预计不符的原因
xfail_strict = true
markers =
smoke: smoke test
get: get test
cal: cal test
注意,pytest.ini文件中含有中文时有可能会gbk编码错误
pytest --markers
查看注册的marker
test.feature文件
Feature: 测试woniuboss登陆
? ? 描述:woniuboss登陆功能测试
Scenario: 输入用户名密码登陆
Given 用户名:wncd000 ,密码:woniu123,验证码:000
When 打开页面:http://172.16.5.31:8080/WoniuBoss4.0/login
And 输入用户名,密码,验证码
Then 我可以在结果页面看到:首页 - 蜗牛BOSS系统
Given->When->Then
类似与准备->执行->验证/清理
的流程import time
import pytest
from selenium import webdriver
from pytest_bdd import scenarios, given, when, then, parsers
@pytest.fixture(scope=‘module‘)
def browser():
driver = webdriver.Chrome()
# b = webdriver.Firefox()
driver.implicitly_wait(3)
yield driver
driver.quit()
scenarios(r‘./test.feature‘)
@given(parsers.parse(‘用户名:{username} ,密码:{password},验证码:{verify_code}‘))
def user(browser, username, password, verify_code):
return dict(username=username, password=password, verify_code=verify_code)
@when(parsers.parse(‘打开页面:{url}‘))
def open_page(browser, url):
browser.get(url)
@when(‘输入用户名,密码,验证码‘)
def do_login(browser, user):
browser.find_element_by_name(‘userName‘).send_keys(user[‘username‘])
browser.find_element_by_name(‘userPass‘).send_keys(user[‘password‘])
browser.find_element_by_name(‘checkcode‘).send_keys(user[‘verify_code‘])
browser.find_element_by_css_selector(‘#form-login > div > div > div.modal-footer > button‘).click()
@then(parsers.parse(‘我可以在结果页面看到:{message}‘))
def see_results(browser, message):
time.sleep(1)
assert str(message) in browser.page_source
flask 运行环境 python -m venv flask_env
windows环境下 -> flask_env -> Script -> activate.bat
注意 flask_env为独立的配置环境,需要在其目录下安装 pip install flask
-> set FLASK_APP=flaskblog.py
-> flask run
* Serving Flask app "flaskblog.py"
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
使用 set FLASK_ENV=development
可以动态观察网页
原文:https://www.cnblogs.com/WheelCode/p/13070627.html