pytest
运行自定义命令行参数
1.首先需要在conftest.py添加命令行选项,命令行传入参数”—cmd“, 用例如果需要用到从命令行传入的参数,就调用cmd函数:
# conftest.py
import pytest
def pytest_addoption(parser):
parser.addoption('--cmd', action='store', default='type2',
help='type1 or type2')
@pytest.fixture()
def cmdopt(request):
return request.config.getoption('--cmd')
# test_para.py
import pytest
def test_05(cmdopt):
if cmdopt == 'type1':
print('第一')
elif cmdopt == 'type2':
print('第二')
cmd打开,输入指令启动,也可以在pycharm里面右键执行上面代码
pytest test_para.py --cmd=type1 或 > pytest test_para.py --cmd type1
上边的两种写法都可以,实例中的 ‘–cmd’ 是自定义的,自定义后可以通过 pytest -h 来查看, help = 后边跟的是参数的解释
配置文件pytest.ini
pytest 配置文件可以改变 pytest 的运行方式,它是一个固定的文件 pytest.ini 文件,读取配置信息,按指定的方式去运行
用 pytest -h 指令可以查看 pytest.ini 的设置选项
mark 标记
我们之前通过mark标记了一些函数,但是有的时候我们标记的过多,就会忘记了一些标记下都是什么case,为了之后我们能精准的运行mark标记,我们可以写入到pytest.ini文件中:
# pytest.ini
[pytest]
markers =
webtest: seek python
w: Open the space
我们写好后就可以通过命令来查看了
> pytest --markers
@pytest.mark.webtest: seek python
@pytest.mark.w: Open the space
@pytest.mark.skip(reason=None): skip the given test function with an optional reason. Example: skip(reason="no way of currently testing this") skips the test.
@pytest.mark.skipif(condition): skip the given test function if eval(condition) results in a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform. see http://pytest.org/latest/skipping.html
@pytest.mark.xfail(condition, reason=None, run=True, raises=None, strict=False): mark the test function as an expected failure if eval(condition) has a True value. Optionally specify a reason for better reporting and run=False if you don't even want to execute the test function. If only specific exception(s) are expected, you can list them in raises, and if the test fails in other ways, it will be reported as a true failure. See http://pytest.org/latest/skipping.html
@pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in different arguments in turn. argvalues generally needs to be a list of values if argnames specifies only one name or a list of tuples of values if argnames specifies multiple names. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.see http://pytest.org/latest/parametrize.html for more info and examples.
@pytest.mark.usefixtures(fixturename1, fixturename2, ...): mark tests as needing all of the specified fixtures. see http://pytest.org/latest/fixture.html#usefixtures
@pytest.mark.tryfirst: mark a hook implementation function such that the plugin machinery will try to call it first/as early as possible.
@pytest.mark.trylast: mark a hook implementation function such that the plugin machinery will try to call it last/as late as possible.
通过命令 pytest --markers 返回来的结果,我们可以发现前两行就是我们刚刚写入到pytest.ini的配置了
addopts
addopts 参数可以更改默认命令行选顷,这个当我们在 cmd 输入指令去执行用例的时候,会用到
例如我们要运行标记为 w 的函数,正常我们直接命令运行 > pytest -m w
我们可以直接在pytest.ini中配置
[pytest]
markers =
webtest: seek python
w: Open the space
addopts= -m w
这样,我们下次命令运行时,直接 > pytest 运行就可以运行标记为 w 的函数了
doctest框架
doctest是python自带的一个模块,doctest测试用例可以放在两个地方
函数或者方法下的注释里面
模块的开头
'''
>>> number('a', 3)
'aaa'
'''
import doctest
def number(a, b):
'''
fuction:两个数相乘
>>> number(3, 4)
12
'''
return a * b
if __name__ == '__main__':
doctest.testmod(verbose=True)
Trying:
number('a', 3)
Expecting:
'aaa'
ok
Trying:
number(3, 4)
Expecting:
12
ok
2 items passed all tests:
1 tests in __main__
1 tests in __main__.number
2 tests in 2 items.
2 passed and 0 failed.
Test passed.
上述代码中 verbose=True
这样在执行测试的时候会输出详细信息,否则不会输出任何东西
我们也可以通过命令行来执行 > python -m doctest -v ceshi.py
pytest是可以完美兼容doctest的,执行的时候需要加个参数 --doctest-module,这样就可以搜索到doctest用例并运行了
pytest -v --doctest-module ceshi.py
doctest内容可以和代码分离开,单独的存放到一个 .txt 文件当中
我们在 ceshi.py 同级目录下创建个 ceshi.txt 文件,写入测试内容,首先我们要导入该功能,导入的时候前边也得加 >>>
>>> from ceshi import number
>>> number(3,4)
12
命令执行 > python -m doctest -v ceshi.txt
Trying:
from ceshi import number
Expecting nothing
ok
Trying:
number(3,4)
Expecting:
12
ok
1 items passed all tests:
2 tests in ceshi.txt
2 tests in 1 items.
2 passed and 0 failed.
Test passed.
装饰器usefixtures
当用例需要调用fixture时,前面讲到可以直接在用例里加fixture参数,如果一个测试class都需要用到fixture,每个用例都去传参,会比较麻烦,这个时候,可以在class外面加usefixtures装饰器,让整个class都调用fixture,实例如下:
# conftest.py
import pytest
import time
from selenium import webdriver
@pytest.fixture(scope='session')
def driver(request):
driver = webdriver.Chrome()
def end():
driver.quit()
request.addfinalizer(end)
return driver
@pytest.fixture()
def start(driver):
print('打开百度')
driver.get('https://www.baidu.com')
print(driver.title)
time.sleep(5)
# test_class.py
import pytest
@pytest.mark.hello
@pytest.mark.usefixtures('start')
class Testclass:
def test_1(self,driver):
driver.find_element_by_id('kw').send_keys('python')
driver.find_element_by_id('su').click()
print('搜索python')
def test_2(self,driver):
driver.get('https://i.qq.com/')
print('打开空间')
命令运行 > pytest -m hello 结果如下:
因为usefixtures无法回去返回值,所以当fixture中带返回值,并且要用到返回值时,我们只能通过传fixture的参数来调用了
html报告+错误截图
html报告+错误截图
首先我们通过pip安装html插件
pip install pytest-html
运行的命令就是在正常的命令后边加上 --html=test.html 也就是
pytest --html=test.html
这样生成的报告 test.html 就会自动生成在同级目录下,如果想指定目录的话也可以:
pytest --html=./report/test.html
这样就会在同级目录中建立个 report 文件夹,test.html会生成在文件夹当中!上面方法生成的报告,css是独立的,分享报告的时候样式会丢失,为了更好的分享发邮件展示报告,可以把css样式合并到html里
pytest --html=report.html --self-contained-html
失败截图可以直接写到conftes.py中,如下:
import pytest
import time
from selenium import webdriver
@pytest.mark.hookwrapper
def pytest_runtest_makereport(item):
"""
当测试失败的时候,自动截图,展示到html报告中
"""
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="https://img-blog.csdnimg.cn/2022010621262354869.png" alt="screenshot" style="width:600px;height:300px;" ' \
'οnclick="window.open(this.src)" align="right"/></div>' % screen_img
extra.append(pytest_html.extras.html(html))
report.extra = extra
def _capture_screenshot():
'''
截图保存为base64,展示到html中
:return:
'''
return driver.get_screenshot_as_base64()
@pytest.fixture(scope='session')
def dri(request):
global driver
driver = webdriver.Chrome()
def end():
driver.quit()
request.addfinalizer(end)
return driver
import pytest
import time
@pytest.mark.webtest
def test_1(dri,start):
'''
搜索python
'''
print('搜索python')
dri.find_element_by_id('kw').send_keys('python')
dri.find_element_by_id('su').click()
time.sleep(5)
#直接断言失败
assert 1 == 2
命令运行 > pytest -m webtest --html=./teport/test1.html --self-contained-html
生成的报告如下:
失败重试
首先我们要pip安装插件
pip install pytest-rerunfailures
失败重试只需要在命令运行的时候加上 --reruns n (n代表的是数字,也就是失败重试几次)
pytest --reruns 2
上述命令代表的意思就是失败后重试2次
通过上述报告我们发现,第一条信息是第三次运行的结果,第二条是第一次运行的结果,第三条是第二次运行的结果
Allure2生成测试报告
首先我们先用pip安装插件
pip install allure-pytest
然后我们去下载最新版本的allure2,连接:https://bintray.com/qameta/maven/allure2
下载完之后我们解压到python安装目录下,如下图:
然后我们找到allure.bat,并配置环境变量到path,allure.bat目录如下:
配置完环境变量后,我们来验证一下,进入命令窗口,输入:allure --version
环境安装好了,那么我们来验证一下,用例就用咱们之前写好的就可以,直接命令运行
pytest -m webtest --alluredir report
运行完之后,会在同级目录下创建个report文件夹,并在文件夹中生成xml报告,我们想要查看这个报告的话有两种方法,
一、直接命令运行
allure serve report
这个时候它会自动打开测试报告
二、命令运行
allure generate report/ -o report/html
运行完之后,会在report文件夹下生成一个html,我们可以在文件夹下找到 index.html ,如果我们从文件夹直接打开这个网页会出现问题,我们直接在pycharm中打开就可以了
allure.attach.file 添加图片