Pytest+Allure定制报告

1、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>

这个文件需要在执行pytest -s -q --alluredir [xml_path]命令后将文件放在[xml_path]路径下,这样在执行allure generate [xml_parh] -o [report_path]生成的html格式的report才会显示相关的环境信息

image.png

2、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"]
  }
]

查看报告

image.png

3、@allure.step

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

@allure.step("输入用户名")
def input_username(user):
    print("输入用户名")
    return user
 
@allure.step("输入密码")
def input_password(pwd):
    print("输入密码")
    return pwd
 
@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"]

查看报告

image.png

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

查看报告

image.png

4、allure.attach

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

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

查看报告

image.png

5、@allure.description

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

    @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

查看报告

image.png

6、@allure.title

使用allure.title(title)可以重命名测试用例在allure报告中的名称

@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"]

查看报告

image.png

7、@allure.link、@allure.testcase、@allure.issue

这三种特性都可以给测试用例添加一个链接

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

查看报告

image.png
image.png
image.png

8、@allure.feature、@allure.story

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

@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()
@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(r"/Users/luozelin/Desktop/pytest/allurereport/imgs/attpng.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

查看报告

image.png

从上面可以看出
@allure.feature("xxxx")在测试报告中显示为用例属于某一模块
@allure.story("xxxx")在测试报告中显示为用例是什么测试场景
以上两种标记不仅仅能够在测试报告中显示,而且还可以使用命令执行指定的测试模块或者场景

image.png

9、@allure.severity

此标记用来标识测试用例或者测试类的级别,分为blocker,critical,normal,minor,trivial5个级别,下面们把测试用例按级别标记,并查看一下测试报告
严重性级别来标记case,这里等于给每个case定义一个严重级别 ,在Graphs页面查看分布情况

@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(r"/Users/luozelin/Desktop/pytest/allurereport/imgs/attpng.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
image.png

从上面来看,对应的用例级别为:
@allure.severity(allure.severity_level.BLOCKER)对应的是中断缺陷(客服端程序无响应,无法执行下一步骤)
@allure.severity(allure.severity_level.CRITICAL)对应的是临界缺陷(功能点缺失)
@allure.severity(allure.severity_level.NORMAL)对应的是普通缺陷(数据计算错误)
@allure.severity(allure.severity_level.MINOR) 对应的是次要缺陷(界面错误与ui需求不符)
@allure.severity(allure.severity_level.TRIVIAL) 对应的是轻微缺陷(必须项无提示,或者提示不规范)

[转载参考文章]:https://blog.csdn.net/BearStarX/article/details/101216016

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,290评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,107评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,872评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,415评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,453评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,784评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,927评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,691评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,137评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,472评论 2 326
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,622评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,289评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,887评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,316评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,490评论 2 348

推荐阅读更多精彩内容