1.前言

1.1.Allure框架是一个灵活的轻量级多语言测试报告工具,它不仅以web的方式展示了简介的测试结果,而且允许参与开发过程的每个人从日常执行的测试中最大限度的提取有用信息。

1.2.从dev/qa的角度来看,Allure报告简化了常见缺陷的统计:失败的测试可以分为bug和被中断的测试,还可以配置日志、步骤、fixture、附件、计时、执行历史以及与TMS和BUG管理系统集成,所以,通过以上配置,所有负责的开发人员和测试人员可以尽可能的掌握测试信息。

1.3.从管理者的角度来看,Allure提供了一个清晰的“大图”,其中包括已覆盖的特性、缺陷聚集的位置、执行时间轴的外观以及许多其他方便的事情。allure的模块化和可扩展性保证了您总是能够对某些东西进行微调,使Allure更适合您,那么今天我们就来说说如何使报告更加详细的显示我们需要的信息,以及allure与jenkins的集成。

2.生成报告

2.1.pytest框架编写的项目如何生成测试报告,具体参考:pytest进阶之html测试报告。

https://blog.csdn.net/hyq413950612/article/details/123743418?spm=1001.2014.3001.5501

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

3.测试代码

3.1.conftest.py

import pytest
import allure@pytest.mark.hookwrapper
def pytest_runtest_makereport(item):outcome = yieldreport = 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

3.2.test_allure_feature.py

import pytest
import allure
import osdef 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 pwdlogin_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_urlassert 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 Falseexcept 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"""passif __name__ == '__main__':pytest.main(["-vsq","--alluredir", "./allure-results", ])os.system(r"allure generate --clean ./allure-results -o ./allure-report")

3.3.test_allure_fixture.py

import pytest
import os
import alluredef 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")

3.4.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"]}
]

3.5.environment.properties

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

3.6.run.py

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

4.目录结构

5.Allure特性:

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

5.2.environment.properties

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

或者
5.3.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>

5.4.执行run.py查看报告。

***6.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"]}
]

6.1.执行run.py查看报告。

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

7.1.test_allure_fixture.py

import pytest
import os
import alluredef 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")

7.2.执行run.py查看报告。

一.Allure常用注解
feature::标注主要功能模块
story:标注feature功能模块下的分支功能
severity:标注测试用例的重要级别
step:标注测试用例的重要步骤
Issue和TestCase:标注Issue、Case,可加入URL

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

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

import pytest
import allure
import osdef 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 pwdlogin_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_urlassert 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 Falseexcept 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"""passif __name__ == '__main__':pytest.main(["-vsq","--alluredir", "./allure-results", ])os.system(r"allure generate --clean ./allure-results -o ./allure-report")

2.2.执行run.py查看报告。

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

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

import pytest
import allure
import osdef 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 pwdlogin_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_urlassert 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 Falseexcept 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"""passif __name__ == '__main__':pytest.main(["-vsq","--alluredir", "./allure-results", ])os.system(r"allure generate --clean ./allure-results -o ./allure-report")

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

4.1.test_allure_feature.py

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

4.2.执行run.py查看报告。

4.3.conftest.py文件:@allure.step修饰的测试步骤还支持在conftest.py文件中定义,作为fixture的步骤,现在在项目目录下新建conftest.py文件。

4.4.conftest.py

@allure.step("打开浏览器")
def fixture_step():pass@pytest.fixture
def init_url():fixture_step()yield True

4.5.test_allure_feature.py

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

4.6.执行run.py查看报告。

5.用例标题和用例描述定制详解

test_allure_title_describe.py

import allure
import pytest@allure.feature('test_module_01')
@allure.story('test_story_01')
#test_case_01为用例title
def test_case_01():"""用例描述:这是用例描述,Test case 01,描述本人"""#注释为用例描述assert 0if __name__ == '__main__':pytest.main(['-s', '-q', '--alluredir', './report'])

5.1.添加用例标题和用例描述,Report展示见下图。

6.@allure.description:如果想在报告中展示测试用例的描述信息,那么可以使用@allure.description(string)或者@allure.description_html(html代码)修饰你的测试用例(和第五点一样,但是第五点使用后会被allure.description覆盖)。

6.1.test_allure_feature.py

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

6.2.执行run.py查看报告。

7.@allure.title:使用allure.title(title)可以重命名测试用例在allure报告中的名称(和第五点一样,但是第五点使用后会被allure.title重新命名覆盖)。

7.1.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"]

8.@allure.link和9.@allure.testcase和10.@allure.issue
这三种特性都可以给测试用例添加一个链接。

10.1.test_allure_feature.py

@allure.testcase("https://www.cnblogs.com/linuxchao/", "测试用例地址")def test_init_url(self, init_url):flag = init_urlassert flag == True@allure.link("https://www.cnblogs.com/linuxchao/", name="bug链接")@allure.description("这是一个一直执行失败的测试用例")def test_failed(self):"""你也可以在这里添加用例的描述信息,但是会被allure.description覆盖"""try:assert Falseexcept 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()

10.2.执行run.py查看报告。


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

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

11.1.执行run.py查看报告。

第十六:Allure-pytest功能特性介绍相关推荐

  1. 第十六期:简单的介绍一下大数据中最重要的MapReduce

    MapReduce是分布式运行的,由两个阶段组成:Map和Reduce,Map阶段是一个独立的程序,有很多个节点同时运行,每个节点处理一部分数据. MapReduce执行流程图 概述 MapReduc ...

  2. 2021年大数据Hadoop(二十六):YARN三大组件介绍

    全网最详细的Hadoop文章系列,强烈建议收藏加关注! 后面更新文章都会列出历史文章目录,帮助大家回顾知识重点. 目录 本系列历史文章 前言 Yarn三大组件介绍 ResourceManager No ...

  3. (92)低速接口UART、IIC、SPI介绍,面试必问(十六)(第19天)

    (92)低速接口UART.IIC.SPI介绍,面试必问(十六)(第19天) 1 文章目录 1)文章目录 2)FPGA初级课程介绍 3)FPGA初级课程架构 4)低速接口UART.IIC.SPI介绍,面 ...

  4. symfony入门学习资料之十六:Symfony框架启动过程介绍

    symfony入门学习资料之十六:Symfony框架启动过程介绍 Symfony框架的核心本质是把Request转换成Response的一个过程.从入口文件(web_dev.php)的源码可以看个大概 ...

  5. STM32驱动SDIO WIFI 介绍(十六) ---- 上位机UDP操作/代码

    代码工程的GITHUB连接:点进进入GITHUB仓库 https://github.com/sj15712795029/stm32f1_marvell88w8801_marvell8801_wifi ...

  6. mysql 魔术设置_PHP之十六个魔术方法详细介绍

    PHP中把以两个下划线__开头的方法称为魔术方法(Magic methods),这些方法在PHP中充当了举足轻重的作用. 魔术方法包括: __construct(),类的构造函数 __destruct ...

  7. Python自动化测试框架【Allure-pytest功能特性介绍】

    Python自动化测试框架[Allure-pytest功能特性介绍] 目录:导读 前言 生成报告 测试代码 目录结构 Allure特性 Environment Categories Fixtures ...

  8. 2021年大数据HBase(十六):HBase的协处理器(Coprocessor)

    全网最详细的大数据HBase文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 系列历史文章 HBase的协处理器(Coprocessor) 一.起源 二 ...

  9. 第十六届全国大学生智能车竞赛技术报告 | 单车拉力组- 上海海事大学-骑摩托的蒙娜丽莎

    简 介: 本文设计的智能车系统以 STC16F40K128微控制器为核心控制单元,通过车体前方的电感检测赛道电磁信息,通过编码器检测智能车的实时速度,利用陀螺仪检测小车姿态,使用PID 控制算法调节电 ...

最新文章

  1. UE5虚幻引擎5中的实时特效学习 Introduction to real time FX in Unreal Engine 5
  2. Web API 接口-JavaScript全部api接口文档
  3. 使用Global.asax在ASP.NET中记录错误日志
  4. python申请内存函数_Python Ctypes c函数的内存分配
  5. intellij-IDE运行Java程序报错:java: -source 1.5 中不支持 lambda 表达式 有用
  6. jsf集成spring_Spring和JSF集成:导航
  7. 【点云分割】区域生长(用鼠标选中一个点长出一个)
  8. Centos7.6环境Docker安装Oracle19c企业版
  9. struts 通配符的使用
  10. 什么是pdi检测_汽车pdi检测是什么?如何知道新车做没做pdi
  11. python函数参数生成器_python函数补充、生成器、迭代器
  12. 2019最新补单安全小技巧
  13. 计算机u盘病毒清除方式,彻底清除u盘病毒有什么方法呢
  14. 触动精灵 - 获取颜色相似度
  15. ae镜头光晕插件Optical Flares
  16. Python使用Reportlab处理PDF数据 - 自定义页眉和页脚
  17. Java 面试题看这些就够了
  18. 流体力学基础——简介
  19. JavaScript资源大全中文版(Awesome最新版--转载自张果老师博客)
  20. 利用python渲染IPsec配置

热门文章

  1. [JS]关于表单的自动运算(已解决)
  2. (转)如何使用CodeSmith批量生成代码
  3. BZOJ 3611: [Heoi2014]大工程 [虚树 DP]
  4. Xcode6 创建静态库
  5. C#根据身份证获出生日期和性别---含C#代码
  6. flash player 10 音频新API使用:调节音高(pitch)
  7. OCP学习和培训ppt汇总
  8. centos下MySQL Workbench连接时崩溃的解决方法
  9. 运行adb devices命令后 显示 List of devices attached 无法获取设备解决方法
  10. 【白皮书分享】2022数据中台交付标准化白皮书-阿里云+埃森哲.pdf(附下载链接)...