pytest_04


pytest文档18-配置文件pytest.ini

pytest配置文件可以改变pytest的运行方式,它是一个固定的文件pytest.ini文件,读取配置信息,按指定的方式去运行。

ini配置文件

pytest里面有些文件是非test文件

  • pytest.ini pytest的主配置文件,可以改变pytest的默认行为    ##放在顶层目录就可以了 ,就可以了,放到顶层文件夹下
  • conftest.py 测试用例的一些fixture配置
  • _init_.py 识别该文件夹为python的package包
  • tox.ini 与pytest.ini类似,用tox工具时候才有用
  • setup.cfg 也是ini格式文件,影响setup.py的行为

ini文件基本格式

# 保存为pytest.ini文件

[pytest]

addopts = -rsxX
xfail_strict = true


有时候标签多了,不容易记住,为了方便后续执行指令的时候能准确使用mark的标签,可以写入到pytest.ini文件

# pytest.ini
[pytest]

markers =
  webtest:  Run the webtest case
  hello: Run the hello case

标记好之后,可以使用pytest --markers查看到

$ pytest --markers


配置文件如何放;我的没生效怎么回事??呃

一般一个工程下方一个pytest.ini  放在顶层目录就可以了 ,就可以了,放到顶层文件夹下

addopts

addopts参数可以更改默认命令行选项,这个当我们在cmd输入指令去执行用例的时候,会用到,比如我想测试完生成报告,指令比较长

$ pytest -v --rerun 1 --html=report.html --self-contained-html

每次输入这么多,不太好记住,于是可以加到pytest.ini里

# pytest.ini
[pytest]

markers =
  webtest:  Run the webtest case
  hello: Run the hello case

 xfail_strict = true

 addopts = -v --rerun 4   --html=report.html --self-contained-html

这样我下次打开cmd,直接输入pytest,它就能默认带上这些参数了

更改测试用例收集规则

pytest默认的测试用例收集规则

  • 文件名以 test_*.py 文件和 *_test.py
  • 以  test_ 开头的函数
  • 以  Test 开头的类,不能包含 __init__ 方法
  • 以  test_ 开头的类里面的方法

我们是可以修改或者添加这个用例收集规则的;当然啦,是建议在原有的规则上添加的,如下配置;使用pychrm执行的时候依然读取pytest.ini  配置

[pytest]

python_files =     test_*  *_test  test*
python_classes =   Test*   test*
python_functions = test_*  test*

20-pytest-html报告优化(添加Description)

pytest-html测试报告默认是不展示用例描述Description内容,之前用unittest生成的报告是可以展示用例的描述,也就是test开头的用例下三个引号里面的注释(docstring)内容。
pytest-html框架是可以修改生成的报告内容的,可以自己添加和删除html报告的table内容。

 conftest.py

@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__)

pytest文档22-fixture详细介绍-作为参数传入,error和failed区别

fixture是pytest的核心功能,也是亮点功能,熟练掌握fixture的使用方法,pytest用起来才会得心应手!

fixture简介

fixture的目的是提供一个固定基线,在该基线上测试可以可靠地和重复地执行。fixture提供了区别于传统单元测试(setup/teardown)有显著改进:

  • 有独立的命名,并通过声明它们从测试函数、模块、类或整个项目中的使用来激活。
  • 按模块化的方式实现,每个fixture都可以互相调用。
  • fixture的范围从简单的单元扩展到复杂的功能测试,允许根据配置和组件选项对fixture和测试用例进行参数化,或者跨函数 function、类class、模块module或整个测试会话sessio范围。

fixture作为参数传入

定义fixture跟定义普通函数差不多,唯一区别就是在函数上加个装饰器@pytest.fixture(),fixture命名不要用test_开头,跟用例区分开。用例才是test_开头的命名。

fixture是可以有返回值的,如果没return默认返回None。用例调用fixture的返回值,直接就是把fixture的函数名称当成变量名称,如下案例

# test_fixture1.py
import pytest

@pytest.fixture()
def user():
    print("获取用户名")
    a = "yoyo"
    return a

def test_1(user):
    assert user == "yoyo"


pytest文档23-使用多个fixture和fixture直接互相调用

使用多个fixture

如果用例需要用到多个fixture的返回数据,fixture也可以return一个元组、list或字典,然后从里面取出对应数据。

# test_fixture4.py
import pytest

@pytest.fixture()
def user():
    print("获取用户名")
    a = "yoyo"
    b = "123456"
    return (a, b)


def test_1(user):
    u = user[0]
    p = user[1]
    print("测试账号:%s, 密码:%s" % (u, p))
    assert u == "yoyo"

if __name__ == "__main__":
    pytest.main(["-s", "test_fixture4.py"])

当然也可以分开定义成多个fixture,然后test_用例传多个fixture参数

# test_fixture5.py
import pytest

@pytest.fixture()
def user():
    print("获取用户名")
    a = "yoyo"
    return a

@pytest.fixture()
def psw():
    print("获取密码")
    b = "123456"
    return b

def test_1(user, psw):
    '''传多个fixture'''
    print("测试账号:%s, 密码:%s" % (user, psw))
    assert user == "yoyo"

ixture与fixture互相调用

fixture与fixture直接也能互相调用的

import pytest

@pytest.fixture()
def first():
    print("获取用户名")
    a = "yoyo"
    return a

@pytest.fixture()
def sencond(first):
    '''psw调用user fixture'''
    a = first
    b = "123456"
    return (a, b)

def test_1(sencond):
    '''用例传fixture'''
    print("测试账号:%s, 密码:%s" % (sencond[0], sencond[1]))

    assert sencond[0] == "yoyo"

pytest文档24-fixture的作用范围(scope)  (没怎么用过,因为都是接口,接口可以通过逻辑实现)

https://www.cnblogs.com/yoyoketang/p/9762197.html

一个测试工程下是可以有多个conftest.py的文件,一般在工程根目录放一个conftest.py起到全局作用。
在不同的测试子目录也可以放conftest.py,作用范围只在该层级以及以下目录生效。

conftest层级关系

一个测试工程下是可以有多个conftest.py的文件,一般在工程根目录放一个conftest.py起到全局作用。
在不同的测试子目录也可以放conftest.py,作用范围只在该层级以及以下目录生效。

在web_conf_py项目工程下建两个子项目baidu、blog,并且每个目录下都放一个conftest.py和__init__.py(python的每个package必须要有__init__.py)

pytest文档25-conftest.py作用范围

在web_conf_py项目工程下建两个子项目baidu、blog,并且每个目录下都放一个conftest.py和__init__.py(python的每个package必须要有__init__.py)

web_conf_py是工程名称

├─baidu
│  │  conftest.py
│  │  test_1_baidu.py
│  │  __init__.py
│  
│          
├─blog
│  │  conftest.py
│  │  test_2_blog.py
│  │  __init__.py
│   
│  conftest.py
│  __init__.py

26-运行上次失败用例(--lf 和 --ff)(挺有用)

 “80%的bug集中在20%的模块,越是容易出现bug的模块,bug是越改越多“平常我们做手工测试的时候,比如用100个用例需要执行,其中10个用例失败了,
当开发修复完bug后,我们一般是重点测上次失败的用例。
那么自动化测试也一样,当用例特别多时,为了节省时间,第一次部分用例失败了,修复完之后,可以只测上次失败的用例

pytest -h

命令行输入pytest -h,找到里面两个命令行参数: --lf 和 --ff

  • --lf, --last-failed 只重新运行上次运行失败的用例(或如果没有失败的话会全部跑)  是小写的 LF
  • --ff, --failed-first 运行所有测试,但首先运行上次运行失败的测试(这可能会重新测试,从而导致重复的fixture setup/teardown) 小写的 FF

pytest文档29-allure-pytest(最新最全,保证能搞成功!)

allure-pytest 环境准备

windows环境相关:

python 3.6版本
pytest 4.5.0版本
allure-pytest 2.8.6 最新版

使用pip安装pytest和allure-pytest,加上--index-url地址,下载会快一些

pip install pytest4.5.0 --index-url https://pypi.douban.com/simple             最好不要加版本号
pip install allure-pytest2.8.6 --index-url https://pypi.douban.com/simple

安装完成之后,打开一个你之前写的pytest脚本,看能不正常使用,如果报错:AttributeError: module 'allure' has no attribute 'severity_level'
这个是之前 pytest-allure-adaptor 这个插件与 allure-pytest 不能共存,卸载掉 pytest-allure-adaptor

pip uninstall pytest-allure-adaptor

allure命令行工具

allure是一个命令行工具,需要去github上下载最新版   https://github.com/allure-framework/allure2/releases

 命令行执行

pytest --alluredir ./report/allure_raw

执行完成后,在当前目录下,report目录会生成一个allure_raw的原始文件,这个只是测试报告的原始文件,不能打开成html的报告

打开html的报告需要启动allure服务,启动命令如下,会在默认浏览器打开

allure serve report/allure_raw