Allure

自动化用例

#coding=utf-8
"""
【自动化用例】
feature 特性名称
story 用户故事/场景
title 对应用例的标题
testcase 对应禅道系统的bug用例url地址,关联起来
issue 如果这个用例有bug,应该关联对应的bug地址
step 用例步骤描述
功能用例整体描述:写在用例方法的注释里
"""
import os

import allure
import pytest


@allure.feature("编辑分类文章")
class TestArticaleClassify():
    @allure.story("典型场景")
    @allure.title("编辑文章分类,重复保存,保存失败")
    @allure.issue("http://127.0.0.1:8080/zentao/bug-view-1.html") #禅道bug地址
    @allure.testcase("http://127.0.0.1:8080/zentao/testcase-view-5-1.html") #禅道用例链接地址
    def test_edit_classify(self):
        """
            编辑文章分类,重复保存,保存失败
            前置条件:1.登录
            步骤:
                1.编辑文章分类,输入文章类别,如计算机
                2.点击保存按钮
                3.重新打开编辑页面,输入:计算机
                4.再次点击保存按钮
            预期结果:
                1.输入成功
                2.保存成功
                3.输入成功
                4.保存失败,提示:已存在
        """
        with allure.step("step:登陆"):
            print("登陆")
            assert 1 == 1
        with allure.step("step1:编辑文章分类,输入文章类别,如计算机"):
            print("step1")
            assert 1 == 1
        with allure.step("step2:点击保存按钮"):
            print("step2")
            assert 1 == 1
        with allure.step("step3:重新打开编辑页面,输入:计算机"):
            print("step3")
            assert 3 == 4
        with allure.step("step4:再次点击保存按钮"):
            print("step4")
            assert 4 == 5

if __name__ == '__main__':
    pytest.main(['--alluredir','./muzi'])
    os.system('allure generate ./muzi/ -o ./report/ --clean')
allure.feature

【用例等级设置】

#coding=utf-8

"""
    用例等级
    allure对用例的等级划分成五个等级:
    blocker  阻塞缺陷(功能未实现,无法下一步)
    critical  严重缺陷(功能点缺失)
    normal   一般缺陷(边界情况,格式错误)
    minor  次要缺陷(界面错误与ui需求不符)
    trivial   轻微缺陷(必须项无提示,或者提示不规范)
"""
import os

import allure
import pytest


@allure.severity("normal")
def test_case_1():
    """
        修改个人姓名-置空
    """
    print("用例1111")

@allure.severity("critical")
def test_case_2():
    """
        修改个人信息-设置为系统已有人员的信息
    """
    print("用例2222")

@allure.severity("critical")
def test_case_3():
    """
        修改个人姓名-生日必选项置空保存
    """
    print("用例3333")

@allure.severity("blocker")
def test_case_4():
    """
        修改个人姓名-点击保存成功
    """
    print("用例4444")

def test_case_5():
    """
        不设置等级,默认等级为
    """
    print("用例5555")

if __name__ == '__main__':
    pytest.main(['--alluredir','./muzi'])
    # 如果有很多测试用例,现在想做快速回顾,只执行用例级别为blocker和critical的测试用例
    # pytest.main(['--alluredir', './muzi', '--allure-severities', 'blocker,critical'])
    # pytest.main(['--alluredir','./muzi','--allure-severities','blocker,critical','--clean-alluredir'])
    os.system('allure generate ./muzi/ -o ./report/ --clean')
    # os.system('allure serve muzi')
severities

 

desc

#coding=utf-8
import os

import allure
import pytest


"""
    假设这是一个登陆操作,简单实现为一个print
"""


@pytest.fixture
def login_fix():
    print("前置条件:登陆")

"""
    封装常用的方法
"""
@allure.step("某某常用操作一")
def step_1():
    print("常用操作一-----------------")

@allure.step("某某常用操作二")
def step_2():
    print("常用操作二-----------------")

@allure.step("某某常用操作三")
def step_3():
    print("常用操作三-----------------")

@allure.epic("大模块名称:NGBSS")
@allure.feature("文章编辑")
class TestDemoAllure():
    @allure.testcase("http://127.0.0.1:8666/zentao/testcase-view-6-1.html")
    @allure.issue("http://127.0.0.1:8666/zentao/bug-view-1.html")
    @allure.title("用例标题一")
    @allure.story("测试场景一")
    @allure.severity("critical")
    def test_case_1(self,login_fix):
        """
            用例标题
            步骤
            预期结果
        """
        step_1()
        step_2()

    @allure.story("测试场景二")
    def test_case_2(self,login_fix):
        step_1()
        step_3()

@allure.epic("大模块名称:CBS")
@allure.feature("欠费催缴")
class TestDemoAllure2():

    @allure.story("测试场景三")
    @allure.severity("critical")
    def test_case_3(self,login_fix):
        """
            用例标题
            步骤
            预期结果
        """
        step_1()


    @allure.story("测试场景四")
    def test_case_4(self,login_fix):
        step_3()

if __name__ == '__main__':
    # pytest.main(['--alluredir','./muzi'])
    # 根据epic执行
    # pytest.main(['--alluredir','./muzi',
    #              '--allure-epics=大模块名称:NGBSS',
    #              '--clean-alluredir'])
    # 根据feature来执行
    # pytest.main(['--alluredir','./muzi',
    #              '--allure-features=欠费催缴',
    #              '--clean-alluredir'])
    # 根据story来执行
    # pytest.main(['--alluredir', './muzi',
    #              '--allure-stories=测试场景四',
    #              '--clean-alluredir'])
    # 多条件筛选
    pytest.main(['--alluredir', './muzi',
                 '--allure-stories=测试场景四,测试场景三',
                 '--clean-alluredir'])
    os.system('allure serve muzi')
desc

 

 step

将用例步骤做关键字封装

1)将用例步骤做关键字封装

1 #common_function.py

2)开始用例设计,登陆单独拿出来,做成前置操作,后面的步骤合起来就是一个用例

1 #test_allure_step.py

3)测试步骤也可以在函数上加上装饰器来实现:

@allure.step()

1 #common_function2.py

2 #test_allure_stepx.py

两种方式对比:

使用 with allure.step("step:步骤") 这种方式代码可读性更好一点, 但不会带上函数里面的传参和对应的值。

使用 @allure.step("step:步骤") 这种方式会带上函数的传参和对应的值。

这两种方式结合起来使用,才能更好的展示测试报告!

# coding=utf-8
# @time: 2022/3/3-16:50
# @author: ljf
# @file:common_function.py

import allure
import pytest

def login(username,password):
    """登陆"""
    print("前置操作:先登陆")

def open_goods():
    """浏览商品"""
    print("浏览商品")

def add_shopping_cart(goods_id="10086"):
    """添加购物车"""
    print("添加购物车")

def buy_goods():
    """生成订单"""
    print("buy")

def pay_goods():
    """支付"""
    print("pay")
common_function.py
# coding=utf-8
# @time: 2022/3/3-16:50
# @author: ljf
# @file:common_function2.py

import allure
import pytest

@allure.step("setup:登陆")
def login(username,password):
    """登陆"""
    print("前置操作:先登陆")

@allure.step("step:浏览商品")
def open_goods():
    """浏览商品"""
    print("浏览商品")

#注意这里的参数会在报告里展示
@allure.step("step添加购物车")
def add_shopping_cart(goods_id="10086"):
    """添加购物车"""
    print("添加购物车")

@allure.step("step:生成订单")
def buy_goods():
    """生成订单"""
    print("buy")

@allure.step("step:支付")
def pay_goods():
    """支付"""
    print("pay")
common_function2.py
# coding=utf-8
# @time: 2022/3/3-16:51
# @author: ljf
# @file:test_allure_step.py

import os

from p05_testcase_step.common_function import *


@pytest.fixture(scope="session")
def login_fix():
    with allure.step("setup:登陆"):
        login("zz","123456")

@allure.feature("购物模块")
@allure.story("子模块")
@allure.title("流程性用例,添加测试步骤")
def test_add_goods_and_buyg(login_fix):
    """
        用例步骤:
        1.登陆,
        2.浏览商品
        3.添加购物车
        4.生成订单
        5.支付成功
    """
    with allure.step("step1:浏览商品"):
        open_goods()

    with allure.step("step2:添加购物车"):
        add_shopping_cart()
        assert 1 == 2

    with allure.step("step3:生成订单"):
        buy_goods()

    with allure.step("step4:支付"):
        pay_goods()

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

if __name__ == '__main__':
    pytest.main(['-s','test_allure_step.py','--alluredir','./result','--clean-alluredir'])
    os.system('allure serve result')
test_allure_step.py
# coding=utf-8
# @time: 2022/3/3-16:53
# @author: ljf
# @file:test_allure_stepx.py

import os

from p05_testcase_step.common_function2 import *

@pytest.fixture(scope="session")
def login_fix():
    with allure.step("setup:登陆"):
        login("zz","123456")

@allure.feature("购物模块")
@allure.story("子模块")
@allure.title("流程性用例,添加测试步骤")
def test_add_goods_and_buyg(login_fix):
    """
        用例步骤:
        1.登陆,
        2.浏览商品
        3.添加购物车
        4.生成订单
        5.支付成功
    """
    open_goods()
    add_shopping_cart()
    buy_goods()
    pay_goods()
    assert 1 == 1

if __name__ == '__main__':
    pytest.main(['-s','test_allure_stepx.py','--alluredir','./result','--clean-alluredir'])
    os.system('allure serve result')
test_allure_stepx.py

title

【参数化结合allure.title()生成不同标题报告】

1.参数化parametrize

1 #test_a.py

2.param+ids参数

1 #test_a_ids.py

3.allure.title描述用例

1 #test_a_title.py

4.优化用例title

1 #test_a_title_new.py

# coding=utf-8
# @time: 2022/3/3-17:05
# @author: ljf
# @file:conftest.py

def pytest_collection_modifyitems(items):
    """
    测试用例收集完成时,将收集到的item的name和nodeid的中文显示在控制台上
    """
    for item in items:
        item.name = item.name.encode("utf-8").decode("unicode_escape")
        item._nodeid = item.nodeid.encode("utf-8").decode("unicode_escape")
conftest.py
# coding=utf-8
# @time: 2022/3/3-17:11
# @author: ljf
# @file:test_a_ids.py

import os

import pytest
import allure

def login(username,password):
    """登陆"""
    print("输入账户: %s" % username)
    print("输入密码: %s" % password)
    # 返回
    return {"code":0,"msg":"success!"}

# 测试数据
test_datas = [
    ({"username":"zz1","password":"123456"},"success!"),
    ({"username":"zz2","password":"123456"},"failed!"),
    ({"username":"zz3","password":"123456"},"success!")
]

@allure.story("登陆接口")
@pytest.mark.parametrize("test_input,expected",
                         test_datas,
                         ids=[
                             "输入正确账号A,密码,登陆",
                             "输入错误账号B,密码,登陆",
                             "输入正确账号C,密码,登陆",
                         ])
def test_login(test_input,expected):
    """测试登陆用例"""
    # 获取函数返回结果
    result = login(test_input["username"],test_input["password"])
    # 断言
    assert  result["msg"] == expected

if __name__ == '__main__':
    pytest.main(["test_a_ids.py",'--alluredir','./result2','--clean-alluredir'])
    os.system('allure generate ./result2/ -o ./report_allure2/ --clean')
    os.system('allure serve result2')
test_a_ids.py
# coding=utf-8
# @time: 2022/3/3-18:00
# @author: ljf
# @file:test_a_title.py

import os

import pytest
import allure

def login(username,password):
    """登陆"""
    print("输入账户: %s" % username)
    print("输入密码: %s" % password)
    # 返回
    return {"code":0,"msg":"success!"}

# 测试数据
test_datas = [
    ({"username":"zz1","password":"123456"},"success!"),
    ({"username":"zz2","password":"123456"},"failed!"),
    ({"username":"zz3","password":"123456"},"success!")
]

"""
    使用@allure.title()时,可以加上传入的参数,
    比如test_input,可以拼接test_input的值
"""
@allure.story("登陆接口")
@allure.title("用例描述,测试输入:{test_input}")
@pytest.mark.parametrize("test_input,expected",
                         test_datas)
def test_login(test_input,expected):
    """测试登陆用例"""
    # 获取函数返回结果
    result = login(test_input["username"],test_input["password"])
    # 断言
    assert  result["msg"] == expected

if __name__ == '__main__':
    pytest.main(["test_a_title.py",'--alluredir','./result3','--clean-alluredir'])
    os.system('allure generate ./result3/ -o ./report_allure3/ --clean')
test_a_title.py
# coding=utf-8
# @time: 2022/3/3-18:15
# @author: ljf
# @file:test_a_title_new.py

import os

import pytest
import allure

def login(username,password):
    """登陆"""
    print("输入账户: %s" % username)
    print("输入密码: %s" % password)
    # 返回
    return {"code":0,"msg":"success!"}

# 测试数据
test_datas = [
    ({"username":"zz1","password":"123456"},"success!","输入正确账号,密码,登陆"),
    ({"username":"zz2","password":"123456"},"failed!","输入错误账号,密码,登陆"),
    ({"username":"zz3","password":"123456"},"success!","输入正确账号,密码,登陆")
]

"""
    使用@allure.title()时,可以加上传入的参数,
    比如test_input,可以拼接test_input的值
"""
@allure.story("登陆接口")
@allure.title("{test_input}")
@pytest.mark.parametrize("test_input,expected,title",
                         test_datas)
def test_login(test_input,expected,title):
    """测试登陆用例"""
    # 获取函数返回结果
    result = login(test_input["username"],test_input["password"])
    # 断言
    assert  result["msg"] == expected

if __name__ == '__main__':
    pytest.main(["test_a_title_new.py",'--alluredir','./result4','--clean-alluredir'])
    os.system('allure generate ./result4/ -o ./report_allure4/ --clean')
test_a_title_new.py
Prame参数
# coding=utf-8
# @time: 2022/3/3-18:36
# @author: ljf
# @file:test_case_01.py

import os
import allure
import pytest

# 接口用例描述例子
desc = "<font color='red'>请求URL:</font>{}<Br/>" \
           "<font color='red'>请求类型:</font>{}<Br/>" \
           "<font color='red'>期望结果:</font>{}<Br/>" \
           "<font color='red'>实际结果描述:</font>{}<Br/>"\
    .format("http://www.baidu.com","post","200","404")



@allure.description("原始描述")
def test_dynamic_description():
    # 断言成功后,可以在测试主体内部动态更新描述
    assert 42 == int(6 * 7)
    # 断言失败,不会动态更新描述
    # assert 43 == int(6 * 7)
    allure.dynamic.description(desc)

@allure.title("原始标题")
def test_with_dynamic_title():
    assert 2 + 2 == 4
    allure.dynamic.title('当断言成功时,用例标题会动态更新')

@allure.title("参数化用例标题: 添加 {param1} 和 {param2}")
@pytest.mark.parametrize('param1,param2,expected', [
    (2, 2, 4),
    (1, 2, 5)
])
def test_with_parameterized_title(param1, param2, expected):
    assert param1 + param2 == expected

if __name__ == '__main__':
    # pytest.main(['-s',"test_case_01.py",'--alluredir','./result'])
    pytest.main(['-s', "test_case_01.py", '--alluredir', './result','--clean-alluredir'])
    # os.system('allure generate ./result/ -o ./report_allure/ --clean')
    os.system('allure serve result')
test_case_01.py
# coding=utf-8
# @time: 2022/3/3-18:37
# @author: ljf
# @file:test_case_02.py
import os

import pytest
import allure

def login(username,password):
    """登陆"""
    print("输入账户: %s" % username)
    print("输入密码: %s" % password)
    # 返回
    return {"code":0,"msg":"success!"}

# 测试数据
test_datas = [
    ({"username":"zz1","password":"123456"},"success!","输入正确账号,密码,登陆"),
    ({"username":"zz2","password":"123456"},"failed!","输入错误账号,密码,登陆"),
    ({"username":"zz3","password":"123456"},"success!","输入正确账号,密码,登陆")
]

"""
    使用@allure.title()时,可以加上传入的参数,
    比如test_input,可以拼接test_input的值
"""
@allure.story("登陆接口")
@pytest.mark.parametrize("test_input,expected,title",
                         test_datas)
def test_login(test_input,expected,title):
    """测试登陆用例"""
    # 获取函数返回结果
    result = login(test_input["username"],test_input["password"])
    # 断言
    assert  result["msg"] == expected
    # 断言成功的用例,动态更新标题
    allure.dynamic.title(title)

if __name__ == '__main__':
    pytest.main(["test_case_02.py",'--alluredir','./result4','--clean-alluredir'])
    os.system('allure serve result4')
test_case_02.py

【allure动态生成用例标题】

1.allure.dynamic 常用动态属性

feature 模块

allure.dynamic.feature(feature_name)

功能点 story

allure.dynamic.story(case_story)

用例标题 title

allure.dynamic.title(case_title)

2.description 用例描述动态更新

1 # test_case_01.py
2 # 接口用例描述例子
3 desc = "<font color='red'>请求URL:</font>{}<Br/>" \
4 "<font color='red'>请求类型:</font>{}<Br/>" \
5 "<font color='red'>期望结果:</font>{}<Br/>" \
6 "<font color='red'>实际结果描述:</font>{}<Br/>" \
7 .format("http://www.baidu.com", "post", "200", "404")
8
9 @allure.description("原始描述")
10 def test_dynamic_description():
11 # 断言成功后,可以在测试主体内部动态更新描述
12 # assert 42 == int(6*7)
13 # 断言失败,不会动态更新描述
14 assert 43 == int(6*7)
15 allure.dynamic.description(desc)

3.title 用例标题动态更新

1 @allure.title("原始标题")
2 def test_dynamic_title():
3 assert 2 + 2 ==4
4 allure.dynamic.title("当断言成功时,用例标题会动态更新")

4.参数化时,使用@allure.title给用例不同标题

1 @allure.title("参数化用例标题:添加{param1}和{param2}")
2 @pytest.mark.parametrize('param1,param2,expected',[
3 (2,2,4),
4 (1,2,5)
5 ])
6 def test_param_title(param1,param2,expected):
7 assert param1 + param2 == expected

5.参数化时,在用例里使用allure.dynamic.title更新用例的标题

1 @allure.story("登陆接口")
2 @pytest.mark.parametrize("test_input,expected,title",
3 test_datas)
4 def test_login(test_input,expected,title):
5 """测试登陆用例"""
6 # 获取函数返回结果
7 result = login(test_input["username"],test_input["password"])
8 # 断言
9 assert result["msg"] == expected
10 # 断言成功的用例,动态更新标题
11 allure.dynamic.title(title)

allure_env

#coding=utf-8
import os

import pytest
import allure

def login(username,password):
    """登陆"""
    print("输入账户: %s" % username)
    print("输入密码: %s" % password)
    # 返回
    return {"code":0,"msg":"success!"}

# 测试数据
test_datas = [
    ({"username":"zz1","password":"123456"},"success!","输入正确账号,密码,登陆"),
    ({"username":"zz2","password":"123456"},"failed!","输入错误账号,密码,登陆"),
    ({"username":"zz3","password":"123456"},"success!","输入正确账号,密码,登陆")
]

"""
    使用@allure.title()时,可以加上传入的参数,
    比如test_input,可以拼接test_input的值
"""
@allure.story("登陆接口")
@pytest.mark.parametrize("test_input,expected,title",
                         test_datas)
def test_login(test_input,expected,title):
    """测试登陆用例"""
    # 获取函数返回结果
    result = login(test_input["username"],test_input["password"])
    # 断言
    assert  result["msg"] == expected
    # 断言成功的用例,动态更新标题
    allure.dynamic.title(title)

if __name__ == '__main__':
    pytest.main(["test_case_02.py",'--alluredir','./result4','--clean-alluredir'])
    os.system('allure serve result4')
test_case_02.py
【allure报告清空上一次记录】 
1.allure报告可以记录用例每次执行的情况,方便跟踪用例的成功率,数据保留到json文件 中
2.会带来一个问题,当你代码里面的用例删除或者更换名称后,依然会记录之前的用例报告
3.--clean-alluredir 每次用例执行之前先清空allure的报告记录
4.使用 pytest -h 可以查看报告相关的三个参数
reporting:
  --alluredir=DIR Generate Allure report in the specified directory (may not exist)
  --clean-alluredir Clean alluredir folder if it exists
  --allure-no-capture Do not attach pytest captured logging/stdout/stderr to report reporting
报告相关参数
  --alluredir=DIR 指定报告的目录路径
  --clean-alluredir 如果已经存在报告,就先清空它
  --allure-no-capture 不加载
  logging/stdout/stderr 文件到报告

【allure生成环境配置】
1.allure报告默认没有环境信息
2.添加环境信息方式一:environment.properties
在allure的result目录(json数据里的)下添加一个 environment.properties 文件
文件格式:
  systemVersion=win10
  pythonVersion=3.6.0
  allureVersion=2.13.0
  baseUrl=http://192.168.1.x:8080
  projectName=test
  author=zz
  email=123123123@qq.com
配置文件不支持中文,有中文会有乱码
3.添加环境信息方式二:environment.xml
在allure的result目录(json数据里的)下添加一个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>
</environment>

3.通过copy命令解决配置文件被删除问题

在运行 pytest 生成 allure 报告的时候,有时候需要加 --clean 参数,清除之前的报告记 录,这样会之前清空 result 目录,environment.properties文件也会被删除。

为了不让 environment.properties 文件删除掉,可以把 environment.properties 文件放 项目根目录,在运行报告的时候,先 copy 到 report 目录

1 if __name__ == '__main__':
2 pytest.main(["test_case_02.py",'‐‐alluredir','./result4','‐‐clean‐allure
dir'])
3 # 把 environment.properties 文件放项目根目录,在运行报告的时候,先 copy 到 r
esult 目录
4 os.system('copy environment.properties result4\\environment.properties')
5 os.system('allure serve result4')
posted on 2022-03-14 15:55  xxxxaaa  阅读(183)  评论(0编辑  收藏  举报