pytest框架fixtureconftesthookpytest.iniallure

Posted IT界的测试混子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了pytest框架fixtureconftesthookpytest.iniallure相关的知识,希望对你有一定的参考价值。

Fixture

pytest fixture 官网:
https://docs.pytest.org/en/stable/fixture.html#fixture

Fixture是在测试函数运行前后,由pytest执行的外壳函数,代码可以定制,满足多变的测试需求,
功能包括:

  • 定义传入测试中的数据集
  • 配置测试前系统的初始状态
  • 为批量测试提供数据源等

pytest fixture 使用
方法1:直接通过函数名,作为参数传递到方法中,有返回值

import pytest

@pytest.fixture
def login():
    print("login....")
    return "login success"
    
def test_add_cart2(login):
    print(login)
    print("添加购物车")

方法2:使用 @pytest.mark.usefixtures(‘login’),测试用例前加上装饰器,没有返回值

import pytest
@pytest.fixture
def login():
    print("login....")
    return "login success"
    
@pytest.mark.usefixtures("login")
def test_add_cart():
    print("添加购物车")

pytest fixture参数

  • autouse 自动应用。默认为False,设置为True自动应用。
  • scope指定作用域(session>module>class>function)
  • setup-show 回溯 fixture 的执行过程
import pytest

@pytest.fixture(autouse=True)
def login():
    print("login....")
    return "login success"

@pytest.fixture(scope="class")
def goto_main():
    print("goto mian page...")

@pytest.fixture(scope="function")
def login_out():
    print("login out....")

@pytest.mark.usefixtures("goto_main")
class TestFixture:
    def test_01(self):
        print("test_01")

    def test_02(self):
        print("test_02")

    def test_03(self,login_out):
        print("test_03")

运行结果
在这里插入图片描述

test_fixture.py --setup-show

在这里插入图片描述

conftest.py

  • conftest.py文件名固定
  • conftest.py 文件就近生效

存放fixture

conftest.py

#conftest.py
import pytest
@pytest.fixture(scope="function")
def setup_and_teardown():
    print("计算开始".center(30,"*"))
    yield "计算中..."
    print("计算结束".center(30,"*"))

test_add.py

#test_add.py
import pytest
def add(a,b):
    return a + b

class TestAdd:
    @pytest.mark.parametrize('a,b,expect',[[0.1,0.2,0.3],], ids=["浮点数相加"])
    def test_add_float(self, a,b,expect,setup_and_teardown):
        print(setup_and_teardown)
        print("{}+{}={}".format(str(a),str(b),str(expect)))
        assert expect == round(add(a, b),2)

执行结果
在这里插入图片描述

pytest 插件

pip install pytest-ordering  控制用例的执行顺序
pip install pytest-dependency   控制用例的依赖关系
pip install pytest-xdist    分布式并发执行测试用例
pip install pytest-rerunfailures   失败重跑
pip install pytest-assume              多重较验
pip install pytest-random-order  用例随机执行
pip install  pytest-html                    测试报告 

hook 函数(pytest定制插件必备)

官方文档:

https://docs.pytest.org/en/latest/reference/reference.html?highlight=hooks#hooks

hook执行顺序

root
└── pytest_cmdline_main
├── pytest_plugin_registered
├── pytest_configure
│ └── pytest_plugin_registered
├── pytest_sessionstart
│ ├── pytest_plugin_registered
│ └── pytest_report_header
├── pytest_collection
│ ├── pytest_collectstart
│ ├── pytest_make_collect_report
│ │ ├── pytest_collect_file
│ │ │ └── pytest_pycollect_makemodule
│ │ └── pytest_pycollect_makeitem
│ │ └── pytest_generate_tests
│ │ └── pytest_make_parametrize_id
│ ├── pytest_collectreport
│ ├── pytest_itemcollected
│ ├── pytest_collection_modifyitems
│ └── pytest_collection_finish
│ └── pytest_report_collectionfinish
├── pytest_runtestloop
│ └── pytest_runtest_protocol
│ ├── pytest_runtest_logstart
│ ├── pytest_runtest_setup
│ │ └── pytest_fixture_setup
│ ├── pytest_runtest_makereport
│ ├── pytest_runtest_logreport
│ │ └── pytest_report_teststatus
│ ├── pytest_runtest_call
│ │ └── pytest_pyfunc_call
│ ├── pytest_runtest_teardown
│ │ └── pytest_fixture_post_finalizer
│ └── pytest_runtest_logfinish
├── pytest_sessionfinish
│ └── pytest_terminal_summary
└── pytest_unconfigure

说明原始链接
https://github.com/pytest-dev/pytest/issues/3261

hook函数解决ids中文乱码问题:

conftest.py

#conftest.py
from typing import List
def pytest_collection_modifyitems(
    session: "Session", config: "Config", items: List["Item"]
) -> None:
    for item in items:
        item.name = item.name.encode('utf-8').decode('unicode-escape')
        item._nodeid = item.nodeid.encode('utf-8').decode('unicode-escape')

test_add.py

#test_add.py
import pytest
def add(a,b):
    return a + b

class TestAdd:
    @pytest.mark.parametrize('a,b,expect',[[0.1,0.2,0.3],], ids=["浮点数相加"])
    def test_add_float(self, a,b,expect,):
        print("{}+{}={}".format(str(a),str(b),str(expect)))
        assert expect == round(add(a, b),2)

执行结果,用例名称显示为中文了
在这里插入图片描述

pytest.ini

使用mark标记用例时,会有以下提示

PytestUnknownMarkWarning: Unknown pytest.mark.debug - is this a typo? You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/mark.html
@pytest.mark.debug
在这里插入图片描述

解决:
pytest.ini

[pytest]
markers  = debug

再执行
在这里插入图片描述其他参数

[pytest]
markers  = debug
python_files = test_*
python_classes = Test*
python_functions  = test_*
addopts  = --clean-alluredir -v --alluredir=./result
testpaths = test_path
log_cli = 1

makers 注册mark标记
修改测试用例收集的命名规则

  • python_files = test_*
  • python_classes = Test*
  • python_functions = test_*

addopts 增加pytest运行时默认参数,省去重复工作
testpaths 指定测试目录
log_cli 控制台实时输出日志

更多参数详解使用pytest --help查看
在这里插入图片描述

allure

文档:
https://docs.qameta.io/allure/#

allure 下载地址:
https://repo1.maven.org/maven2/io/qameta/allure/allure-commandline/2.13.8/

allure安装

(1)需要先安装java 环境
(2) windows下载zip包,解压后把bin目录加入环境变量
Mac可以用brew安装

brew install allure

(3)安装 allure-pytest库

pip install allure-pytest

allure特性

在报告中看到测试功能,子功能,或场景,测试步骤包括测试附加信息

  • 功能加上@allure.feature(‘功能名称’)
  • 子功能加上@allure.story(‘子功能名称’)
  • 步骤加上@allure.step(‘功能名称’)
  • @allure.attach(‘具体文本信息’),需要附加信息,可以是数据、文本、图片、视频、网页
  • 运行时限制过滤 pytest 文件名 --allure-features’购物车功能’ --allure-stories’加入购物车’

注解@allure.feature与@allure.story相当于父子关系

特性-step

测试过程中每个步骤,一般放在具体的逻辑方法中。可以放在关键步骤中,在报告中显示,在app、web自动化测试当中,建议切换到每一个新的页面做一个step

  • @allure.step() 只能以装饰器的形式放在类或方法上面
  • with allure.step() 可以在测试用例方法里面
特性 -testcase

关联测试用例,可以直接给测试用例的地址链接

TEST_CASE_LINK = "https://www.baidu.com"
@allure.testcase(TEST_CASE_LINK ,"test case title")
def test_with_testcase_link()
	pass
按重要级别进行一定范围的测试
  • 通过附件mark标记
  • 通过allure.feature,allure.story来标记
  • 通过allure.severity来附加标记
    (级别Trivial:不重要 ,Minor不太重要,Normal 正常问题 Critical 严重 Blocker 阻塞)
    步骤:
    • 在测试方,函数和类上加 @allure.severity(allure.severity_level.TRIVIAL)
    • 执行时 pytest -s -v 文件名 --allure-severities normal,critical
allure运行不同测试用例
  • 按mark标记运行
pytest -m smoke --clean-alluredir -v --alluredir=./result
  • 按feature运行
pytest --allure-features="pay" --clean-alluredir -v --alluredir=./result
  • 按story运行
pytest --allure-stories="pay" --clean-alluredir -v --alluredir=./result
  • 按severity运行
pytest --allure-severities blocker,critical --clean-alluredir -v --alluredir=./result
allure.attach文件、截图、html

allure.attcah显示许多不同类型提供的附件
(1)在测试报告里附加网页
allure.attach(body内容,name,attachment_type,extension)

    allure.attach(body=r'<head></head><body>增加html内容</body>', name="attach增加html内容",
                 attachment_type=allure.attachment_type.HTML)

(2)在测试报告里附加图片
allure.attach.file(source,name,attachment_type,extension)

allure.attach.file(source=png_path, name="attach增加PNG内容", attachment_type=allure.attachment_type.PNG)

allure --help查看更多参数

在这里插入图片描述#### allure生成报告
在测试执行期间收集结果

#--alluredir,指定生成结果路径
pytest [测试文件] -s -q --alluredir=./result/ 

查看测试报告,三种方式
(1)在线查看报告,会直接打开默认浏览器展示当前报告,执行以下

allure serve ./result/ 

(2)先从结果生成报告,再打开index.html

#从结果生成报告
allure generate ./result/ -o ./report/ --clean
#打开报告
allure open -h 127.0.0.1 -p 8888 ./report/

(3)先生成html报告,再从pycharm中右键点击index.html>【Open in Browser】>选择浏览器,打开报告。注意:直接双击html无效

#从结果生成报告
allure generate ./result/ -o ./report/ --clean

在这里插入图片描述

test allure demo

pytest.ini

;pytest.ini
[pytest]
markers  = debug smoke
python_files = test_* 
python_classes = Test*
python_functions  = test_*
;addopts  = -m smoke --clean-alluredir -v --alluredir=./result
;addopts  = --allure-severities blocker,critical --clean-alluredir -v --alluredir=./result
;addopts  = --allure-stories="pay" --clean-alluredir -v --alluredir=./result
addopts  =  --clean-alluredir -v --alluredir=./result
testpaths = ./

test_allure.py

#test_allure.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# pip install allure-pytest
import allure
# pip install pytest
import pytest

def choose_goods():
    print("选择商品")

def add_cart():
    print("添加购物车")

def pay():
    print("支付")

def clearn_cart():
    print("清除购物车")

def collect_goods():
    print("收藏商品")

@allure.feature("功能模块-购物车功能")
class TestGoodsCart:
    @pytest.mark.smoke
    @allure.severity(allure.severity_level.BLOCKER)
    @allure.story("pay")
    # @allure.story("子功能-加购商品并支付")
    @allure.title("测试用例名称-加购商品并支付成功")
    def test_add_cart_and_pay(login,attach_html):
        with allure.step("step1:选择商品"):
            choose_goods()

        with allure.step("step2:加入购物车"):
            add_cart()

        with allure.step("step3:支付"):
            pay()

        with allure.step("断言"):
            assert 1 == 2

    @allure.severity(allure.severity_level.CRITICAL)
    @allure.story("子功能-清除购物车")
    @allure.title("测试用例名称-清除购物车")
    def test_clearn_cart(login,attach_png):
        with allure.step("step1:选择商品"):
            choose_goods()

        with allure.step("step2:清除购物车"):
            clearn_cart()

        with allure.step("断言"):
            assert 1 == 1

    @allure.testcase("https://www.taobao.com/","关联用例title")
    @allure.story("子功能-购物车商品转收藏")
    @allure.title("测试用例名称-购物车商品转收藏")
    def test_collect_goods(login):
        with allure.step("step1:选择商品"):
            choose_goods()

        with allure.step("step2:收藏购物车商品"):
            collect_goods()

        with allure.step("断言"):
            assert 1 == 1

conftest.py

#conftest.py
import os
import allure
import pytest
from typing import List
def pytest_collection_modifyitems(
    session: "Session", config: "Config", items: List["Item"]
) -> None:
    for item in items:
        item.name = item.name.encode('utf-8').decode('unicode-escape')
        item._nodeid = item.nodeid.encode('utf-8').decode('unicode-escape')


@pytest.fixture()
def login():
    print("login".center(30,"*"))
    return "login success..."

@pytest.fixture()
def attach_html():
    allure.attach(body=r'<head></head><body>增加html内容</body>', name="attach增加html内容",
                 attachment_type=allure.attachment_type.HTML)

png_path = os.path.join(os.path.split(os.path.abspath(__file__))[0],"taobao.png")
@pytest.fixture()
def attach_png():
    allure.attach.file(source=png_path, name="attach增加PNG内容", attachment_type=allure.attachment_type.PNG)

执行

pytest test_allure.py
allure generate --clean ./result  --report-dir ./report

插入html文件
在这里插入图片描述

插入图片
在这里插入图片描述

关联link,可点击跳转
在这里插入图片描述

以上是关于pytest框架fixtureconftesthookpytest.iniallure的主要内容,如果未能解决你的问题,请参考以下文章

pytest测试框架

Python - pytest

pytest框架

pytest文档71-pytest+yaml实现接口自动化框架

pytest接口自动化测试框架 | pytest获取执行数据pytest禁用插件

pytest框架--@pytest.fixture(scpoe=‘xxx')装饰器