mark标记
- 举例:某用例可以用@pytest.mark.xxx,则想要运行该条时需要加-m参数指定值为xxx,:如pycharm中写pytest.main(["-s", "test_server.py", "-m=xxx"]),cmd执行时pytest -v -m xxx,若不想执行则用 pytest -v -m "not xxx"
- 指定运行某函数也可在pycharm中用pytest.main(["-v", "test_server.py::TestClass::test_method"]),cmd下用pytest -v test_server.py::TestClass::test_method ,意为执行server.py文件下TestClass类中test_method方法,也可选择多个节点运行,中间用逗号隔开:
pytest.main(["-v", "test_server.py::TestClass", "test_server.py::test_send_http"])
- 用 -k 匹配用例名称执行,如 pytest -v -k http (指定匹配带有http的用例)、pytest -k "not send_http" -v(去掉带有send_http的用例)、pytest -k "http or quick" -v(同时带quick的用例)
基础用例a失败,则依赖a用例结果的b、c用例直接跳过且标记为xfail
举个例子
#encoding=utf-8
import pytest
canshu = [{"user": "amdin", "psw": ""}]
@pytest.fixture(scope="module")
def login(request):
user = request.param["user"]
psw = request.param["psw"]
print("正在操作登录,账户:%s,密码:%s" %(user,psw))
if psw:
return True
else:
return False
@pytest.mark.parametrize("login", canshu, indirect=True)
class Test_xx():
def test_01(self,login):
'''用例1登录'''
result = login
print("用例1:%s" % result)
assert result == True
def test_02(self,login):
result = login
print("用例2,登录结果:%s" %result)
if not result:
pytest.xfail("登录不成功,标记为xfail")
assert 1 == 1
def test_03(self,login):
result = login
print("用例3,登录结果:%s" %result)
if not result:
pytest.xfail("登录不成功,标记为xfail")
assert 1 == 1
if __name__ == "__main__":
pytest.main(["-s", "pratice.py"])
结果如图
可以看到有两个用例判断登录失败后置为xfail且被ignore
pytest.ini配置文件
pytest.ini pytest的主配置文件,可以改变pytest的默认行为,该文件放在python项目的根目录,基本格式如下:
# 保存为pytest.ini文件
[pytest]
addopts = -rsxX
xfail_strict = true
使用pytest --help指令可以查看pytest.ini的设置选项
[pytest] ini-options in the first pytest.ini|tox.ini|setup.cfg file found:
markers (linelist) markers for test functions
empty_parameter_set_mark (string) default marker for empty parametersets
norecursedirs (args) directory patterns to avoid for recursion
testpaths (args) directories to search for tests when no files or dire
console_output_style (string) console output: classic or with additional progr
usefixtures (args) list of default fixtures to be used with this project
python_files (args) glob-style file patterns for Python test module disco
python_classes (args) prefixes or glob names for Python test class discover
python_functions (args) prefixes or glob names for Python test function and m
xfail_strict (bool) default for the strict parameter of
addopts (args) extra command line options
minversion (string) minimally required pytest version
具体参考https://www.cnblogs.com/yoyoketang/p/9550648.html这篇
doctest测试框架
doctest从字面意思上看,那就是文档测试。doctest是python里面自带的一个模块,它实际上是单元测试的一种。官方解释:doctest 模块会搜索那些看起来像交互式会话的 Python 代码片段,然后尝试执行并验证结果。个人感觉就是单元测试。
doctest测试用例可以放在两个地方
- 函数或者方法下的注释里面
例如:
def multiply(a, b):
"""
fuction: 两个数相乘
>>> multiply(4, 3)
12
>>> multiply('a', 3)
'aaa'
"""
return a * b
if __name__ == '__main__':
import doctest
doctest.testmod(verbose=True)
------------------------输出------------------------
Trying:
multiply(4, 3)
Expecting:
12
ok
Trying:
multiply('a', 3)
Expecting:
'aaa'
ok
1 items had no tests:
__main__
1 items passed all tests:
2 tests in __main__.multiply
2 tests in 2 items.
2 passed and 0 failed.
Test passed.
- 模块的开头
'''
fuction: 两个数相乘
>>> multiply(4, 8)
12
>>> multiply('a', 5)
'aaa'
'''
def multiply(a, b):
"""
fuction: 两个数相乘
"""
return a * b
if __name__ == '__main__':
import doctest
doctest.testmod(verbose=True)
-------------------------输出---------------------
Failure
<Click to see difference>
**********************************************************************
File "F:/testpython/pratice.py", line 4, in pratice
Failed example:
multiply(4, 8)
Expected:
12
Got:
32
Failure
<Click to see difference>
**********************************************************************
File "F:/testpython/pratice.py", line 6, in pratice
Failed example:
multiply('a', 5)
Expected:
'aaa'
Got:
'aaaaa'
pytest框架是可以兼容doctest用例,执行的时候加个参数 --doctest-modules ,这样它就能自动搜索到doctest的用例
$ pytest -v --doctest-modules xxx.py
doctest独立文件
doctest内容也可以和代码抽离开,单独用一个.txt文件保存,在当前xxx.py同一目录新建一个xxx.txt文件,写入测试的文档,要先导入该功能,导入代码前面也要加>>>,如
>>> from xxx import multiply
>>> multiply(4, 3)
12
>>> multiply('a', 3)
'aaa'
cmd执行“python -m doctest -v xxx.txt”测试结果
pytest-html
- 安装pytest-html
pip install pytest-html - 执行,到pytest用例目录下
pytest --html=report.html
想要指定生成路径的话:pytest --html=./report/report.html - 报告独立显示
pytest --html=report.html --self-contained-html
-失败截图可以写到conftest,py文件里,这样用例运行时,只要检测到用例实例,就调用截图的方法,并且把截图存到html报告上
# conftest.py文件
# coding:utf-8
from selenium import webdriver
import pytest
driver = None
@pytest.mark.hookwrapper
def pytest_runtest_makereport(item):
"""
当测试失败的时候,自动截图,展示到html报告中
** 作者:上海-悠悠 QQ交流群:588402570**
:param item:
"""
pytest_html = item.config.pluginmanager.getplugin('html')
outcome = yield
report = outcome.get_result()
extra = getattr(report, 'extra', [])
if report.when == 'call' or report.when == "setup":
xfail = hasattr(report, 'wasxfail')
if (report.skipped and xfail) or (report.failed and not xfail):
file_name = report.nodeid.replace("::", "_")+".png"
screen_img = _capture_screenshot()
if file_name:
html = '<div><img src="data:image/png;base64,%s" alt="screenshot" style="width:600px;height:300px;" ' \
'onclick="window.open(this.src)" align="right"/></div>' % screen_img
extra.append(pytest_html.extras.html(html))
report.extra = extra
def _capture_screenshot():
'''
** 作者:上海-悠悠 QQ交流群:588402570**
截图保存为base64,展示到html中
:return:
'''
return driver.get_screenshot_as_base64()
@pytest.fixture(scope='session', autouse=True)
def browser(request):
global driver
if driver is None:
driver = webdriver.Firefox()
def end():
driver.quit()
request.addfinalizer(end)
return driver
用例文件,分为两个
# test_01.py文件
from selenium import webdriver
import time
#** 作者:上海-悠悠 QQ交流群:588402570**
def test_yoyo_01(browser):
browser.get("https://www.cnblogs.com/yoyoketang/")
time.sleep(2)
t = browser.title
assert t == "上海-悠悠"
# test_02.py文件
from selenium import webdriver
import time
# ** 作者:上海-悠悠 QQ交流群:588402570**
def test_yoyo_01(browser):
browser.get("https://www.cnblogs.com/yoyoketang/")
time.sleep(2)
t = browser.title
assert "上海-悠悠" in t
在cmd中运行 pytest --html=report.html --self-contained-html,生成报告
失败重试
需要 pip install pytest-rerunfailures 安装插件(这个插件目前这样安装会报错,可以在豆瓣等网站上下载好包在本地安装,也可以通过pycharm安装)
重跑命令:py.test --reruns 1 --html=report.html --self-contained-html,--reruns 1代表重跑一次
修改报告
添加描述(Description)列,添加可排序时间(Time)列,并删除链接(Link)列:(说实话conftest.py中的钩子函数和除fixture功能外的其他用法都还一头雾水)
from datetime import datetime
from py.xml import html
import pytest
@pytest.mark.optionalhook
def pytest_html_results_table_header(cells):
cells.insert(2, html.th('Description'))
cells.insert(1, html.th('Time', class_='sortable time', col='time'))
cells.pop()
@pytest.mark.optionalhook
def pytest_html_results_table_row(report, cells):
cells.insert(2, html.td(report.description))
cells.insert(1, html.td(datetime.utcnow(), class_='col-time'))
cells.pop()
@pytest.mark.hookwrapper
def pytest_runtest_makereport(item, call):
outcome = yield
report = outcome.get_result()
report.description = str(item.function.__doc__)