Allure-pytest功能特性介绍

前言

Allure框架是一个灵活的轻量级多语言测试报告工具,它不仅以web的方式展示了简介的测试结果,而且允许参与开发过程的每个人从日常执行的测试中最大限度的提取有用信息
从dev/qa的角度来看,Allure报告简化了常见缺陷的统计:失败的测试可以分为bug和被中断的测试,还可以配置日志、步骤、fixture、附件、计时、执行历史以及与TMS和BUG管理系统集成,所以,通过以上配置,所有负责的开发人员和测试人员可以尽可能的掌握测试信息。
从管理者的角度来看,Allure提供了一个清晰的“大图”,其中包括已覆盖的特性、缺陷聚集的位置、执行时间轴的外观以及许多其他方便的事情。allure的模块化和可扩展性保证了您总是能够对某些东西进行微调,使Allure更适合您,那么今天我们就来说说如何使报告更加详细的显示我们需要的信息,以及allure与jenkins的集成

生成报告

pytest框架编写的项目如何生成测试报告,这里将不再讲解,具体过程可以参考:pytest进阶之html测试报告

注意:python使用的allure插件为allure-pytest

测试代码

为了大家能够快速的认识allure的所有功能特性,附上完整的测试代码

"""
------------------------------------
@Time : 2019/8/28 19:50
@Auth : linux超
@File : conftest.py
@IDE  : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : [email protected]
@GROUP: 878565760
------------------------------------
"""
import pytest
import allure

@pytest.mark.hookwrapper
def pytest_runtest_makereport(item):
    outcome = yield
    report = outcome.get_result()
    report.nodeid = report.nodeid.encode("utf-8").decode("unicode_escape")  # 解决乱码

@allure.step("打开浏览器")
def fixture_step():
    pass

@pytest.fixture
def init_url():
    fixture_step()
    yield True

conftest.py

"""
------------------------------------
@Time : 2019/9/4 21:05
@Auth : linux超
@File : test_allure_feature.py
@IDE  : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : [email protected]
@GROUP: 878565760
------------------------------------
"""
import pytest
import allure
import os

def login(username=None, password=None):
    """模拟登录"""
    user = "linux超"
    pwd = "123456"
    if user == username and pwd == password:
        return {"code": 1001, "msg": "登录成功", "data": None}
    elif "" == password or password is None and username:
        return {"code": 1002, "msg": "密码不能为空", "data": None}
    elif "" == username or username is None and password:
        return {"code": 1003, "msg": "用户名不能为空", "data": None}
    else:
        return {"code": 1004, "msg": "用户名或密码错误", "data": None}

@allure.step("输入用户名")
def input_username(user):
    print("输入用户名")
    return user

@allure.step("输入密码")
def input_password(pwd):
    print("输入密码")
    return pwd

login_success_data = [
    # 测试数据
    {
        "case": "用户名正确, 密码正确",
        "user": "linux超",
        "pwd": "123456",
        "expected": {"code": 1001, "msg": "登录成功", "data": None}
    }
]

login_fail_data = [
    {
        "case": "用户名正确, 密码为空",
        "user": "linux超",
        "pwd": "",
        "expected": {"code": 1002, "msg": "密码不能为空", "data": None}
    },
    {
        "case": "用户名为空, 密码正确",
        "user": "",
        "pwd": "linux超哥",
        "expected": {"code": 1003, "msg": "用户名不能为空", "data": None}
    },
    {
        "case": "用户名错误, 密码错误",
        "user": "linux",
        "pwd": "linux",
        "expected": {"code": 1004, "msg": "用户名或密码错误", "data": None}
    }
]

username_none = [
    {
        "case": "缺省用户名参数",
        "pwd": "123456",
        "expected": {"code": 1003, "msg": "用户名不能为空", "data": None}
    }
]
password_none = [
    {
        "case": "缺省密码参数",
        "user": "linux超",
        "expected": {"code": 1002, "msg": "密码不能为空", "data": None}
    }
]
# 改变输出结果
ids_login_success_data = [
    "测试{}用户名:{}密码{}期望值{}".
        format(data["case"], data["user"], data["pwd"], data["expected"]) for data in login_success_data
]
ids_login_fail_data = [
    "测试{}用户名:{}密码{}期望值{}".
        format(data["case"], data["user"], data["pwd"], data["expected"]) for data in login_fail_data
]
ids_username_none = [
    "测试{}密码{}期望值{}".
        format(data["case"], data["pwd"], data["expected"]) for data in username_none
]
ids_password_none = [
    "测试{}用户名:{}期望值{}".
        format(data["case"], data["user"], data["expected"]) for data in password_none
]

@allure.feature("登录模块")
class TestLogin(object):

    @allure.severity(allure.severity_level.BLOCKER)
    @allure.story("测试登录成功")
    @allure.title("登录成功场景-{data}")
    @pytest.mark.parametrize("data", login_success_data, ids=ids_login_success_data)
    def test_login_success(self, data):
        """测试登录成功"""
        user = input_username(data["user"])
        pwd = input_password(data["pwd"])
        result = login(user, pwd)
        assert result == data["expected"]

    @allure.severity(allure.severity_level.CRITICAL)
    @allure.story("测试登录失败")
    @pytest.mark.parametrize("data", login_fail_data, ids=ids_login_fail_data)
    def test_login_fail(self, data):
        """测试用户名或密码错误"""
        user = input_username(data["user"])
        pwd = input_password(data["pwd"])
        result = login(user, pwd)
        assert result == data["expected"]

    @allure.severity(allure.severity_level.MINOR)
    @allure.story("测试用户名参数缺失")
    @pytest.mark.parametrize("data", username_none, ids=ids_username_none)
    def test_username_none(self, data):
        """测试缺省用户名"""
        pwd = input_password(data["pwd"])
        result = login(password=pwd)
        assert result == data["expected"]

    @allure.severity(allure.severity_level.MINOR)
    @allure.story("测试密码参数缺失")
    @pytest.mark.parametrize("data", password_none, ids=ids_password_none)
    def test_password_none(self, data):
        """测试缺省密码"""
        user = input_username(data["user"])
        result = login(username=user)
        assert result == data["expected"]

    @allure.severity(allure.severity_level.MINOR)
    @allure.story("测试初始化地址")
    @allure.testcase("https://www.cnblogs.com/linuxchao/", "测试用例地址")
    def test_init_url(self, init_url):
        flag = init_url
        assert flag is True

    @allure.severity(allure.severity_level.NORMAL)
    @allure.story("测试失败用例与用例中添加附件")
    @allure.link("https://www.cnblogs.com/linuxchao/", name="bug链接")
    @allure.description("这是一个一直执行失败的测试用例")
    def test_failed(self):
        """你也可以在这里添加用例的描述信息,但是会被allure.description覆盖"""
        try:
            assert False
        except AssertionError as e:
            with open("attach.png", "rb") as f:
                context = f.read()
                allure.attach(context, "错误图片", attachment_type=allure.attachment_type.PNG)
            raise e

    @allure.severity(allure.severity_level.TRIVIAL)
    @allure.story("测试broken用例")
    @allure.issue("https://www.cnblogs.com/linuxchao/", "错误链接")
    def test_broken(self):
        """broken"""
        with open("broken.json", "r", encoding=‘utf8‘) as f:
            f.read()

    @allure.severity(allure.severity_level.TRIVIAL)
    @allure.story("测试无条件跳过测试用例")
    @pytest.mark.skip(reason="无条件跳过")
    def test_skip(self):
        """skip"""
        pass

if __name__ == ‘__main__‘:
    pytest.main(["-vsq",
                 "--alluredir", "./allure-results", ])
    os.system(r"allure generate --clean ./allure-results -o ./allure-report")

test_allure_feature.py

"""
------------------------------------
@Time : 2019/8/28 19:45
@Auth : linux超
@File : test_allure_fixture.py
@IDE  : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : [email protected]
@GROUP: 878565760
------------------------------------
"""
import pytest
import os
import allure

def function_scope_step():
    print("function_scope_step")

def class_scope_step():
    print("class_scope_step")

def module_scope_step():
    print("module_scope_step")

def session_scope_step():
    print("session_scope_step")

def step_inside_test_body():
    print("step_inside_test_body")

@pytest.fixture(params=[True, False], ids=[‘param_true‘, ‘param_false‘])
def function_scope_fixture_with_finalizer(request):
    if request.param:
        print(‘True‘)
    else:
        print(‘False‘)

    def function_scope_finalizer():
        function_scope_step()

    request.addfinalizer(function_scope_finalizer)

@pytest.fixture(scope=‘class‘)
def class_scope_fixture_with_finalizer(request):
    def class_finalizer_fixture():
        class_scope_step()

    request.addfinalizer(class_finalizer_fixture)

@pytest.fixture(scope=‘module‘)
def module_scope_fixture_with_finalizer(request):
    def module_finalizer_fixture():
        module_scope_step()

    request.addfinalizer(module_finalizer_fixture)

@pytest.fixture(scope=‘session‘)
def session_scope_fixture_with_finalizer(request):
    def session_finalizer_fixture():
        session_scope_step()

    request.addfinalizer(session_finalizer_fixture)

@allure.severity(allure.severity_level.BLOCKER)
@allure.feature("fixture场景")
class TestClass(object):

    def test_with_scoped_finalizers(self,
                                    function_scope_fixture_with_finalizer,
                                    class_scope_fixture_with_finalizer,
                                    module_scope_fixture_with_finalizer,
                                    session_scope_fixture_with_finalizer):
        step_inside_test_body()

if __name__ == ‘__main__‘:
    pytest.main(["-vsq",
                 "--alluredir", "./allure-results", ])
    os.system(r"allure generate --clean ./allure-results -o ./allure-report")

test_allure_fixture.py

[
  {
    "name": "Ignored tests",
    "matchedStatuses": ["skipped"]
  },
  {
    "name": "Infrastructure problems",
    "matchedStatuses": ["broken", "failed"],
    "messageRegex": ".*bye-bye.*"
  },
  {
    "name": "Outdated tests",
    "matchedStatuses": ["broken"],
    "traceRegex": ".*FileNotFoundException.*"
  },
  {
    "name": "Product defects",
    "matchedStatuses": ["failed"]
  },
  {
    "name": "Test defects",
    "matchedStatuses": ["broken"]
  }
]

categories.json

Browser=Chrome
Browser.Version=63.0
Stand=Production
ApiUrl=127.0.0.1/login
python.Version=3.6

environment.properties

"""
------------------------------------
@Time : 2019/9/3 14:21
@Auth : linux超
@File : run.py
@IDE  : PyCharm
@Motto: Real warriors,dare to face the bleak warning,dare to face the incisive error!
@QQ   : [email protected]
@GROUP: 878565760
------------------------------------
"""
import pytest
import os

if __name__ == ‘__main__‘:
    pytest.main(["-sq",
                 "--alluredir", "./allure-results"])
    os.system(r"allure generate --clean allure-results -o allure-report")

run.py

目录结构

Allure特性

Environment

在Allure报告中添加环境信息,通过创建environment.properties或者environment.xml文件,并把文件存放到allure-results(这个目录是生成最后的html报告之前,生成依赖文件的目录)目录下

environment.properties

Browser=Chrome
Browser.Version=63.0
Stand=Production
ApiUrl=127.0.0.1/login
python.Version=3.6

或者

environment.xml

<environment>
    <parameter>
        <key>Browser</key>
        <value>Chrome</value>
    </parameter>
    <parameter>
        <key>Browser.Version</key>
        <value>63.0</value>
    </parameter>
    <parameter>
        <key>Stand</key>
        <value>Production</value>
    </parameter>
        <parameter>
        <key>ApiUrl</key>
        <value>127.0.0.1/login</value>
    </parameter>
        <parameter>
        <key>python.Version</key>
        <value>3.6</value>
    </parameter>
</environment>

执行run.py查看报告

Categories

测试报告默认统计两种类型的测试用例结果,失败的用例和故障测试用例,我们可以自定义添加用例的统计类型,同样需要在allure-results目录下新建categories.json文件

[
  {
    "name": "Ignored tests",
    "matchedStatuses": ["skipped"]
  },
  {
    "name": "Infrastructure problems",
    "matchedStatuses": ["broken", "failed"],
    "messageRegex": ".*bye-bye.*"
  },
  {
    "name": "Outdated tests",
    "matchedStatuses": ["broken"],
    "traceRegex": ".*FileNotFoundException.*"
  },
  {
    "name": "Product defects",
    "matchedStatuses": ["failed"]
  },
  {
    "name": "Test defects",
    "matchedStatuses": ["broken"]
  }
]

执行run.py查看报告

Fixtures and Finalizers

Fixtures和Finalizers是pytest在测试开始和测试结束调用的方法,allure会自动跟踪每一个fixture的调用,并且详细显示会调用哪些fixture和参数,而且会保留正确的调用顺数

测试代码

test_allure_html.py

def function_scope_step():
    print("function_scope_step")

def class_scope_step():
    print("class_scope_step")

def module_scope_step():
    print("module_scope_step")

def session_scope_step():
    print("session_scope_step")

def step_inside_test_body():
    print("step_inside_test_body")

@pytest.fixture(params=[True, False], ids=[‘param_true‘, ‘param_false‘])
def function_scope_fixture_with_finalizer(request):
    if request.param:
        print(‘True‘)
    else:
        print(‘False‘)

    def function_scope_finalizer():
        function_scope_step()

    request.addfinalizer(function_scope_finalizer)

@pytest.fixture(scope=‘class‘)
def class_scope_fixture_with_finalizer(request):
    def class_finalizer_fixture():
        class_scope_step()

    request.addfinalizer(class_finalizer_fixture)

@pytest.fixture(scope=‘module‘)
def module_scope_fixture_with_finalizer(request):
    def module_finalizer_fixture():
        module_scope_step()

    request.addfinalizer(module_finalizer_fixture)

@pytest.fixture(scope=‘session‘)
def session_scope_fixture_with_finalizer(request):
    def session_finalizer_fixture():
        session_scope_step()

    request.addfinalizer(session_finalizer_fixture)

class TestClass(object):

    def test_with_scoped_finalizers(self,
                                    function_scope_fixture_with_finalizer,
                                    class_scope_fixture_with_finalizer,
                                    module_scope_fixture_with_finalizer,
                                    session_scope_fixture_with_finalizer):
        step_inside_test_body()

执行run.py查看报告

@allure.step

pytest支持使用@allure.step修饰某些测试用例中需要的函数,使测试用例在allure报告中能够更加详细的显示测试过程

测试代码

test_allure_feature.py文件中修改如下代码

@allure.step("输入用户名")
def input_username():
    print("输入用户名")

@allure.step("输入密码")
def input_password():
    print("输入密码")

执行run.py查看报告

conftest.py

@allure.step修饰的测试步骤还支持在conftest.py文件中定义,作为fixture的步骤,现在我们在项目目录下新建conftest.py文件,写入如下代码

conftest.py

@allure.step("打开浏览器")
def fixture_step():
    pass

@pytest.fixture
def init_url():
    fixture_step()
    yield True

test_allure_feature.py文件中添加如下用例

    def test_init_url(self, init_url):
        flag = init_url
        assert flag == True

执行run.py查看报告

allure.attach

使用allure.attach可以给报告中添加文件,图片,log,html代码等等。 我们修改test_allure_feature.py中如下用例, 并在用例所在目录添加attach.png图片

    def test_failed(self):
        """failed"""
        try:
            assert False
        except AssertionError as e:
            with open("attach.png", "rb") as f:
                context = f.read()
                allure.attach(context, "错误图片", attachment_type=allure.attachment_type.PNG)
            raise e

执行run.py查看报告

@allure.description

如果你想在报告中展示测试用例的描述信息,那么你可以使用@allure.description(string)或者@allure.description_html(html代码)修饰你的测试用例,test_allure_feature.py文件修改如下代码

    @allure.description("这是一个一直执行失败的测试用例")
    def test_failed(self):
        """你也可以在这里添加用例的描述信息,但是会被allure.description覆盖"""
        try:
            assert False
        except AssertionError as e:
            with open("attach.png", "rb") as f:
                context = f.read()
                allure.attach(context, "错误图片", attachment_type=allure.attachment_type.PNG)
            raise e

执行run.py查看报告

@allure.title

使用allure.title(title)可以重命名测试用例在allure报告中的名称,test_allure_feature.py文件修改如下代码

    @allure.title("登录成功场景-{data}")
    @pytest.mark.parametrize("data", login_success_data, ids=ids_login_success_data)
    def test_login_success(self, data):
        """测试登录成功"""
        user = input_username(data["user"])
        pwd = input_password(data["pwd"])
        result = login(user, pwd)
        assert result == data["expected"]

@allure.link

@allure.testcase

@allure.issue

这三种特性都可以给测试用例添加一个链接,test_allure_feature.py文件修改如下代码

    @allure.testcase("https://www.cnblogs.com/linuxchao/", "测试用例地址")
    def test_init_url(self, init_url):
        flag = init_url
        assert flag == True

    @allure.link("https://www.cnblogs.com/linuxchao/", name="bug链接")
    @allure.description("这是一个一直执行失败的测试用例")
    def test_failed(self):
        """你也可以在这里添加用例的描述信息,但是会被allure.description覆盖"""
        try:
            assert False
        except AssertionError as e:
            with open("attach.png", "rb") as f:
                context = f.read()
                allure.attach(context, "错误图片", attachment_type=allure.attachment_type.PNG)
            raise e

    @allure.issue("https://www.cnblogs.com/linuxchao/", "错误链接")
    def test_broken(self):
        """broken"""
        with open("broken.json", "r", encoding=‘utf8‘) as f:
            f.read()

执行run.py查看报告

@allure.feature

@allure.story

feature和story被称为行为驱动标记,因为使用这个两个标记,通过报告可以更加清楚的掌握每个测试用例的功能和每个测试用例的测试场景

在test_allure_feature.py文件中的测试类使用@allure.feature修饰, 测试方法使用@allure.story修饰

执行run.py查看报告

以上两种标记不仅仅能够在测试报告中显示,而且还可以使用命令执行指定的测试模块或者场景

@allure.severity

此标记用来标识测试用例或者测试类的级别,分为blocker,critical,normal,minor,trivial5个级别,下面们把测试用例按级别标记,并查看一下测试报告

总结

以上就是所有的allure-pytest插件在pytest中支持的大部分功能特性,也许整理的不是很详细,所以如果你想详细的了解具体的特性在报告中的效果,还需自己动手尝试一下,附上本文参考链接

https://docs.qameta.io/allure/

原文地址:https://www.cnblogs.com/linuxchao/p/linuxchao-pytest-allure.html

时间: 2024-10-31 22:23:05

Allure-pytest功能特性介绍的相关文章

Pytest框架介绍

Pytest框架介绍.安装 pytest是python测试框架,与python自带的unittest测试框架类似,但是比unittest框架使用起来更简洁,功能更强大 pytest特征 1:断言提示信息更清楚 2:自动化加载函数与模块 3:支持运行由nose, unittest编写的测试case 4:支持py2.3,2.7,3.x 5:丰富的插件以及社区支持 6:支持参数化 7:支持失败重跑 8:支持多线程跑用例 9:支持分布式 pytest安装 pip安装,在cmd下面执行命令 pip ins

Allure+pytest 生成测试报告

简介: python 主流自动化测试报告插件有三个:HTMLTestRunner.BeautifulReport 和 Allure.HTMLTestRunner是一个比较古老的报告模板,界面也不是很好看.BeautifulReport  界面很简洁,看起来也很直观,是一款比较不错的报告插件.如果你想提升一下你的level,让你的自动化测试报告变得高大上,那么请选择 Allure . Allure 是一款轻量级的开源自动化测试报告生成框架.它支持绝大部分测试框架,比如 TestNG.Junit .

pytest框架-介绍、Mark、命令运行用例、。。。。

1.pytest介绍:基于unittest 之上的单元测试框架 1.1.自动发现测试模块和测试用例: unitest 需要添加用例,(泰斯特楼贷)加载器加载测试用例 pytest 只需要一条代码就可以 1.2.断言使用 assert + 表达: unitest 定义了所有的 断言方式 pytest  只需要使用一个关键字 assert + 表达式 就可以了,表达式为真则通过,表达式为假则不通过断言失败 1.3.pytest 可以设置测试会话级.模块级.类级.函数级的 fixtures: 1.4.

MariaDB数据库主从复制、双主复制、半同步复制、基于SSL的安全复制实现及其功能特性介绍

一.复制概述 MariaDB/MySQL内建的复制功能是构建大型,高性能应用程序的基础.将MySQL的数据分布到多个系统上去,这种分布的机制,是通过将MySQL的某一台主机的数据复制到其它主机(slaves)上,并重新执行一遍来实现的.复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器.主服务器将更新写入二进制日志文件,并维护文件的一个索引以跟踪日志循环.这些日志可以记录发送到从服务器的更新.当一个从服务器连接主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更新的位

用Pytest+Allure生成漂亮的HTML图形化测试报告

本篇文章将介绍如何使用开源的测试报告生成框架Allure生成规范.格式统一.美观的测试报告. 通过这篇文章的介绍,你将能够: - 将Allure与Pytest测试框架相结合: - 执行测试之后,生成Allure格式的测试报告. 1.Allure测试报告介绍 Allure是一款非常轻量级并且非常灵活的开源测试报告生成框架. 它支持绝大多数测试框架, 例如TestNG.Pytest.JUint等.它简单易用,易于集成.下面就Pytest如何与Allure集成做详细介绍. 2.Pytest框架集成Al

httpd协议及其功能介绍

一.http协议 1.http协议的版本: http/0.9: 诞生于1991,仅用于传输html文档,不能包含图片 http/1.0: 引入了MIME,支持多媒体数据的处理,keep-alive(保持连接),有缓存功能 http/1.1: 支持更多的请求方法,更精细的缓存控制,持久连接 http/1.0和http/1.1之所以能够传输多媒体数据,是因为引入了MIME MIME: Multipurpose Internet Mail Extension MIME引入了base64的编码机制,能够

如何简单实现接口自动化测试(基于 python) 原博主地址https://blog.csdn.net/gitchat/article/details/77849725

如何简单实现接口自动化测试(基于 python) 2017年09月05日 11:52:25 阅读数:9904 GitChat 作者:饿了么技术社区 原文:如何简单实现接口自动化测试(基于 python) 关注微信公众号:GitChat 技术杂谈 ,这里一本正经的讲技术 一.简介 本文从一个简单的登录接口测试入手,一步步调整优化接口调用姿势,然后简单讨论了一下接口测试框架的要点,最后介绍了一下我们目前正在使用的接口测试框架pithy.期望读者可以通过本文对接口自动化测试有一个大致的了解. 二.引言

PostgreSQL即学即用(第2版)pdf

下载地址: 网盘下载 内容简介 · · · · · · 本书将帮助你理解和使用PostgreSQL 这一开源数据库系统.你不仅会学到版本9.2.9.3 和9.4中的企业级特性,还会发现PostgreSQL 不只是个数据库系统,也是一个出色的应用平台.本书通过示例展示了如何实现在其他数据库中难以或无法完成的任务.这一版内容覆盖了LATERAL 查询.增强的JSON 支持.物化视图和其他关键话题. 作者简介  · · · · · · Regina Obe 是数据库咨询公司Paragon的负责人之一,

VMware V12.0.1 专业版 + 永久密钥 此博文包含图片 (2015-10-30 16:53:14)

转自:http://blog.sina.com.cn/s/blog_4549d6770102vxue.html 热门虚拟机软件VMware Workstation 现已更新至v12.0.1 专业版!12.0属于大型更新,专门为Win10的安装和使用做了优化,支持DX10.4K高分辨率显示屏.OpenGL 3.3.7.1声道,以及各种新硬件和新技术.下面附上永久许可证密钥及最新注册机!v11已抛弃了对32位系统支持,安装包体积从而大幅减小. VMware是功能最强大的虚拟机软件,用户可在虚拟机同时