app自动化测试框架(三、allure美化测试报告)

一、安装allure
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

转载: https://blog.csdn.net/z_erduo/article/details/116332523?spm=1001.2014.3001.5502

二、生产报告
main.py

import pytest,os
cur_path = os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__)))))
result_path = cur_path + '/web/autotest/ui/result'
result_port = cur_path + '/web/autotest/ui/result_port'
if not os.path.exists(result_path):os.makedirs(result_path)
if not os.path.exists(result_port):os.makedirs(result_port)

pytest.main([
    '--alluredir',
    result_path,
    'test_suites/test_login.py',
])
os.system("allure generate --clean "+result_path+"  --report-dir "+result_port) #转换为html

执行成功后result_path路径下会生成报告文件


image.png

result_report会生成html报告文件


image.png

打开报告方式:

方式一: 执行命令:
allure serve result_path路径
浏览器会自动打开报告

方式二:进入result_report路径
使用pycharm打开result_report文件,打开index.html浏览器

ps:如果直接在文件夹右键打开index.html无法生成报告

image.png

三、增强报告的可观性:
allure特性
在报告中看到测试功能,子功能,或场景,测试步骤包括测试附加信息

使用方法 参数值 参数说明
@allure.epic() epic描述
@allure.feature() 模块名称
@allure.story() 子模块名称
@allure.title() 用例的标题
@allure.testcase() 测试用例的链接地址
@allure.issue() 缺陷 对应缺陷管理系统里面的链接
@allure.description() 用例描述 测试用例的描述
@allure.step() 操作步骤 测试用例的步骤
@allure.severity() 用例等级 blocker,critical,normal,minor,trivial
@allure.link() 链接 定义一个链接,在测试报告展现
@allure.attachment() 附件 报告添加附件

1、给登录模块增加登录木块区分和子用例标题

import pytest
import logging
from page_obj.login_page import LoginPage
import allure

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

    @allure.title("成功登录")
    def test_login_success(self, app_page):
        LoginPage(app_page).login('xxxxxxx', 'xxxxxx')
        logging.info("开始断言")


    @allure.title("失败登录")
    def test_login_error(self, app_page):
        LoginPage(app_page).login('xxxxxxx', 'xxxxxx')
        logging.info("开始断言")
image.png

2、@allure.story

import pytest
import logging
from page_obj.login_page import LoginPage
import allure

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

    @allure.story("手机登录")
    @allure.title("成功登录")
    def test_login_success(self, app_page):
        LoginPage(app_page).login('xxxxxxx', 'xxxxxx')
        logging.info("开始断言")

    @allure.story("手机登录")
    @allure.title("失败登录")
    def test_login_error(self, app_page):
        LoginPage(app_page).login('xxxxxxx', 'xxxxxx')
        logging.info("开始断言")


    @allure.story("账号密码登录1")
    @allure.title("成功登录")
    def test_login_error2(self, app_page):
        LoginPage(app_page).login('xxxxxxx', 'xxxxxx')
        logging.info("开始断言")
image.png

3、添加测试步骤

import pytest
import logging
from page_obj.login_page import LoginPage
import allure

@allure.feature("添加地址")
class Testaddress:

    @allure.title("成功添加地址")
    def test_address_success(self, app_page):
        with allure.step("step1:登录用户"):
            print("登录用户")

        with allure.step("step2:删除地址"):
            print("删除地址")

        with allure.step("step3:添加地址"):
            print("添加地址")

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

4、增加失败截图

conftest.py

import pytest, os
from selenium import webdriver
from appium import webdriver
import logging
from py._xmlgen import html
cur_path = os.path.dirname(os.path.realpath(__file__))
import allure
driver = None

@pytest.fixture()
def app_page():
    logging.info('----------------测试开始-----------------')
    desired_caps = {}
    desired_caps['platformName'] = 'Android'
    desired_caps['platformVersion'] = '8.1.0'
    desired_caps['deviceName'] = 'c6e989d7'
    desired_caps['appPackage'] = 'xxxx'
    desired_caps['appActivity'] = 'xxxxx'
    desired_caps['autoGrantPermissions'] = True
    desired_caps['automationName'] = 'uiautomator2'

    global driver
    driver = webdriver.Remote('http://127.0.0.1:4723/wd/hub', desired_caps)
    yield driver
    logging.info('----------------测试结束-----------------')
    driver.quit()


#通过conftest来实现报告的描述
@pytest.mark.optionalhook
def pytest_html_results_table_header(cells):
    cells.insert(1, html.th('Description'))  #html报告中插入一列,列头名为Description

@pytest.mark.optionalhook
def pytest_html_results_table_row(report, cells):
    try:
        cells.insert(1, html.td(report.description))
    except:
        pass

# @pytest.mark.hookwrapper
# def pytest_runtest_makereport(item, call):
    # outcome = yield
    # report = outcome.get_result()
    # report.description = str(item.function.__doc__)

# @pytest.mark.hookwrapper
# def pytest_runtest_makereport(item):
#     pytest_html = item.config.pluginmanager.getplugin('html')
#     outcome = yield
#     report = outcome.get_result()
#     extra = getattr(report, 'extra', [])
#
#     if report.when == 'call' or report.when == "setup":
#         xfail = hasattr(report, 'wasxfail')
#         if (report.skipped and xfail) or (report.failed and not xfail):
#             file_name = report.nodeid.replace("::", "_")+".png"
#             screen_img = _capture_screenshot()
#             if file_name:
#                 html = '<div><img src="data:image/png;base64,%s" alt="screenshot" style="width:375px;" ' \
#                        'onclick="window.open(this.src)" align="right"/></div>' % screen_img
#                 extra.append(pytest_html.extras.html(html))
#         report.extra = extra

# def _capture_screenshot():
#     '''截图保存为base64'''
#     return driver.get_screenshot_as_base64()


@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    '''
    获取每个用例状态的钩子函数
    :param item:
    :param call:
    :return:
    '''
    # 获取钩子方法的调用结果
    outcome = yield
    rep = outcome.get_result()
    # 仅获取用例call且执行结果是失败的情况, 不包含 setup/teardown
    if rep.when == "call" and rep.failed:
        # 添加allure报告截图
        if hasattr(driver, "get_screenshot_as_png"):
            with allure.step('添加失败截图..'):
                allure.attach(driver.get_screenshot_as_png(), "失败截图", allure.attachment_type.PNG)
image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,772评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,458评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,610评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,640评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,657评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,590评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,962评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,631评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,870评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,611评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,704评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,386评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,969评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,944评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,179评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,742评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,440评论 2 342

推荐阅读更多精彩内容