python测试开发日常工具-pytest、allure

pytest、allure框架使用demo(一)

pytest、allure-commandline下载、安装、配置

  • pip install pytest
  • pip install allure-pytest
  • allure-commandline下载地址,选择合适的包,下载zip包
  • 解压包,把bin目录加入到PATH环境变量
  • allure --version 检查是否成功

pytest.ini

[pytest]
;在你当前的这个相对同级的目录中找符合 test开头py文件(或者再往下层找),Test开头的类,test开头的函数
python_files = test*.py
python_classes = Test*
python_functions = test*
;要执行的测试用例的文件夹
testpaths = ../fixture
; --disable-warnings将警告不显示
; -v 让pytest的输出结果更加详细
; -s 开启终端(控制台/输入台)的交互, 如果程序执行的过程中需要控制台输入,但是没有加-s参数,那么会报错
; -k 筛选出名称包含某字符串的用例运行 
; 例:-k 0401 函数名称中包含0401的测试函数
; -m 是对pytest.mark标记的用例名进行筛选,多个参数中间可以使用运算符or and not
;  例:addopts = -v -s -m regression and yuyz  #执行标签是regression和yuyz的用例
;-v s k 等参数如果放在main方法中嫌太多了,可以放在pytest.ini文件中的addopts中
;addopts = -v -s -k test01 --disable-warnings
addopts = -v -s --disable-warnings
;pytest.mark标记的用例,将警告解决处理
markers =
    smoke: Run smoke test
    regression: 大回归的测试
    yuyz: 个人进行测试的
; --html=report/report.html 同级目录下,创建文件夹
; --self-contained-html 使用pytest-html的时候,可以将html的css文件放在一起,而不再另外生成css文件

conftest.py

import allure
import pytest
from pytest_html import extras

# 定义一个全局变量,用于存储内容
global_data = {}

'''
fixture ,将函数中返回的数据传给用例,当多个用例都需要这个函数/数据的时候,可以将数据放在fixture标记的函数中
fixture函数可以放在conftest文件中也可以放在测试文件中
fixture的数据如果是一个列表。会被视为多个用例,测试函数会多次执行
autouse=True 则每个模块/类/测试函数前置都会执行
scope='module',session,class,常常需要搭配使用autouse,在每个模块中前置或者后置会被执行,scope='function',在每个函数的前置或后置会被执行。
    后置执行,需要加yield,每条用例执行完之后会执行yield之后的
    module范围,这个模块执行一次
    class范围的时候也包括了模块中的函数(在类中执行一次,模块中每个函数都执行), 
    function则包含了模块中的所有的函数
name='c_fixture',可以自定义名称,名称可以与函数的不一样,被调用的时候使用name
'''

@pytest.fixture(autouse=True, scope='module')
def fixture_data():
    print('fixture_data')
    yield
    print('fixture_data...')

@pytest.fixture()
def fixture_data2():
    return [1, 2, 3]

@pytest.fixture(params=['a', 'b', 'c'])
def fixture_data3(request):
    return request.param

@pytest.fixture(params=['d', 'e', 'f'], name='p4')
def fixture_data4(request):
    return request.param

@pytest.fixture(params=[('输入正确的', {'name': 'zhangsan', 'password': '123456'}, '成功'),
                        ('输入错误用户', {'name': 'zhangsan1', 'password': '123456'}, '失败'),
                        ('输入正确密码', {'name': 'zhangsan', 'password': '1234561'}, '失败')
                        ], name='p5')
def fixture_data5(request):
    return request.param

@pytest.fixture()
def set_global_data():
    """设置全局变量,用于关联参数"""
    def set_data(key, value):
        global_data[key] = value
    return set_data

@pytest.fixture()
def get_global_data():
    """从全局变量global_data中取值"""    
    def get_data(key):
        return global_data[key]
    return get_data

# 当测试出错的时候,截图
@pytest.hookimpl(hookwrapper=True)  
def pytest_runtest_makereport(item, call):  # 利用钩子函数的回调进行判断并且处理
    outcome = yield
    report = outcome.get_result()
    if report.when == 'call':
        xfail = hasattr(report, 'wasxfail')
        if (report.skipped and xfail) or (report.failed and not xfail):
        # if report.outcome != 'passed':
            """失败截图数据"""
            image_path = 'D:\workfile\PycharmProjects\\fixture\img\23.png'
            with open(image_path, 'rb') as image_file:
                allure.attach(image_file.read(), '错误截图', attachment_type=allure.attachment_type.PNG)

test1.py

import allure
import pytest
from pytest_html import extras

test_data5 = [('输入正确的', {'name': 'zhangsan', 'password': '123456'}, '成功'),
              ('输入错误的', {'name': 'lisi', 'password': '123456'}, '失败'),
              ('输入没有的', {'name': 'wwwww', 'password': '123456'}, '没有')]

def test_d1():
    print('test_d1')

def test_d2():
    print('test_d2')

# allure 行为标记,让allure的报告层级鲜明
@allure.epic('用户端')
@allure.feature('用户登录')
class Test01:

    @allure.testcase('127.09.34.64:8080')
    @allure.issue('127.09.34.64:8081')
    @allure.story('用例登录用例1')
    @allure.title('执行登录')
    @allure.severity('critical')  # blocker阻塞 critical严重 normal一般 minor次要 trivial轻微
    def test01_1(self):
        print('test01_1')

    @allure.severity('blocker')
    def test01_2(self):
        print('test01_2')

    @allure.severity('normal')  
    def test01_3(self, fixture_data2):
        with allure.step('步骤test01_3'):
            print('步骤1')
        print('test01_3')
        print(fixture_data2)

    @allure.severity('minor')
    def test01_4(self, fixture_data3):
        print('test01_4')
        print(fixture_data3)
        assert fixture_data3 == 'a'

    '''名称使用自定义的param'''
    @allure.severity('critical')
    @allure.title('{title}')
    @allure.description('原始描述5')
    @pytest.mark.parametrize('title,test_input,expected', test_data5)
    def test01_5(self, title, test_input, expected):
        print('test01_5')
        print(test_data5)

    @allure.severity('critical')
    @allure.description('原始描述')
    def test01_6(self):
        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')
        assert 42 == int(6 * 7)
        # 这里断言成功,则会用新的描述方式,断言失败则会用原始描述
        allure.dynamic.description(desc)

    @allure.severity('critical')
    @allure.title('原始标题')
    def test_01_7(self):
        assert 4 == 2*2
        allure.dynamic.title('断言成功,更新标题')
        print('其他的比如story epic testcase都是可以用dynamic进行更新的!')

    def test01_add_img(self, extra):  # pytest默认的外部数据列表
        def image_to_base64(image_path):
            import base64
            """这个函数是将图片转化为base64数据"""
            with open(image_path, "rb") as image_file:
                encoded_string = base64.b64encode(image_file.read())
                return encoded_string.decode('utf-8')
        # 添加图片文件
        image_path = 'D:\workfile\PycharmProjects\23.png'
        extra.append(extras.jpg(image_path))

        # 添加base64格式的图片
        base64_data = image_to_base64(image_path)
        extra.append(extras.image(base64_data))  # pytest-html添加图片

    def test01_allure_add_img(self):
        image_path = 'D:\workfile\PycharmProjects\23.png'
        with open(image_path, 'rb') as image_file:
            allure.attach(image_file.read(), name='图片的名称', attachment_type=allure.attachment_type.PNG)

@allure.epic('管理端')
@allure.feature('用户管理')
class Test02:

    @allure.testcase('127.09.123.64:8080')
    @allure.issue('127.09.123.64:8081')
    @allure.story('用户管理用例1')
    @allure.title('管理登录')
    @allure.severity('critical')
    def test02_1(self):
        print('test01_1')

    def test02_2(self):
        print('test01_2')

@allure.step('步骤1')
def step1():
    print('step1')

@allure.step('步骤2')
def step2():
    print('step2')

def test_03():
    step1()
    step2()

run_suite.py

import pytest
# from pytest_html.html_report
testcases_path = DIR_PATH + os.sep + "testcases"
'''
pip install pytest-html
'''
if __name__ == '__main__':
    # pytest.main(['-vs', '-k', 'test01_5'])  # 运行标签是regression和yuyz的用例,可以将-v -s命令参数放在pytest.ini文件中
    # 在main的同级目录下面生成测试报告html, --self-contained-html 可以将html的css文件放在一起(使用pytest-html的时候才使用)
    # pytest.main(["--html=report/report.html", "--self-contained-html"]) 
    
    # --allure-epics=用户端 指定epic进行执行用例
    # --allure-features=f1,f2
    # --allure-stories=s1
    # 如果只想进行冒烟测试,只想要验证关键用例,只执行blocker critical级别的用例
    pytest.main(['--allure-severities=blocker,critical', '--alluredir', 'allure_result', '--clean-alluredir'])
    # --clean-alluredir 每次执行之前清空报告
    # pytest.main(['--allure-epics=用户端', '--alluredir', 'allure_result', '--clean-alluredir'])  # 获取测试结果,保存allure测试数据
    
    # pytest.main(['-vs', 'testPytest1.py::TestCal::test_div_norm'])  # 执行某一个函数
    # pytest.main(['-vs', testcases_path, '--alluredir', allure_report_path])  # 执行testcases_path的所有用例
    # pytest.main(['-vs', '-m', 'regression'])  # 执行标签是regression的用例
    # pytest.main(['-vs', '-m', 'not regression'])  # 执行标签不是regression的用例
    # pytest.main(['-vs', '-m', 'regression or yuyz'])  # 执行标签是regression或yuyz的用例
    # pytest.main(['-vs', '-m', 'regression and yuyz'])  # 执行标签是regression和yuyz的用例
    import os
    # --clean 让报告可以覆盖
    os.system('allure generate --clean ./allure_result -o ./allure_report')  # 根据测试数据,生成测试报告html
    # os.system('allure serve result')  # 生成测试报告,在一个web端上展示

努力追求财富自由,不是为了让自己可以放纵,而是为了让自己在面对自己不想要的选择的时候可以坦然说不,去选择自己喜欢的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值