Pytest自动化测试框架+Allure报告

简介

Allure Framework 是一款轻量级、多语言支持的测试报告工具,能够以清晰直观的报告形式展示测试结果,帮助开发快速定位问题,管理者掌握测试全局,同时支持高度自定义,满足不同团队的协作需求。

部署使用

1、安装

(1)allure-pytest插件:

pip install -U allure-pytest

这将安装allure-pytest和allure-python-commons程序包,以生成与allure2兼容的报告数据。

(2)allure工具:

官方下载地址:https://github.com/allure-framework/allure2/releases

解压软件包(建议直接放到Python文件夹下),然后添加bin目录到环境变量中,最后使用 allure --version 验证是否安装成功。

Pytest

一、Pytest 的基本概念

Pytest 是一个基于 Python 的测试框架,它比 Python 自带的  unittest 框架更加灵活和高效。其主要特点包括:
  • 自动发现测试用例:Pytest 会自动查找当前目录及其子目录下符合命名规则的测试文件(如 test_*.py 或 *_test.py)和测试函数(以 test_ 开头的函数)。
  • 简洁的语法:Pytest 的语法简单直观,不需要编写复杂的 setup 和 teardown 代码。
  • 丰富的插件支持:支持参数化测试、测试夹具(Fixtures)、自定义标记等高级功能。

二、使用规范

1、命名规范
1.1 测试模块
  • 测试模块文件名通常以 test_ 开头或以 _test 结尾。
1.2 测试类
  • 测试类必须以 Test 开头命名。
  • 测试类中不能包含 __init__ 方法。
1.3 测试函数
  • 测试函数必须以 test_ 开头。
2、装饰器
2.1 夹具(Fixtures)@pytest.fixture
  • 定义 Fixtures
    • 在 conftest.py 文件中定义全局夹具,或在测试模块中定义局部夹具。
# conftest.py
@pytest.fixture
def setup_db():
    # 数据库初始化代码
    pass

  • 使用 Fixtures
    • 在测试函数中通过参数传递 Fixtures。
      def test_login(setup_db):
          # 使用 setup_db 夹具
          pass
  • 作用范围
    • Fixtures 可以通过 scope 参数设置作用范围(如 functionclassmodulesession)。
@pytest.fixture(scope="module")
def setup_module():
    pass

  • yield 关键字
    • 作用:yield关键字可以实现 fixture 的 setup(准备)和 teardown(清理)分离
yield 之前:测试前置准备(相当于 setUp)
yield 返回值:传递给测试用例使用
yield 之后:测试后清理(相当于 tearDown)
  • 使用示例
import pytest
from selenium import webdriver

@pytest.fixture(scope="class")
def driver_and_url():
    # Setup:启动浏览器
    driver = webdriver.Chrome()
    url = "http://example.com"
    yield driver, url  # 返回 driver 和 url 给测试用例
    # Teardown:关闭浏览器
    driver.quit()

class TestWebPage:
    def test_login(self, driver_and_url):
        # 这一步的作用是将fixture返回的多个值解包并赋值给相应的变量,以便在测试用例中使用这些值
        driver, url = driver_and_url   
        driver.get(url)

2.2 标记(markers)@pytest.mark
2.2.1 参数化测试 @pytest.mark.parametrize
  • 使用数据库数据进行驱动:(示例)
def get_db_data():
    """
    从数据库获取测试数据
    Returns:
        list: 包含测试用例字典的列表,每个字典代表一条测试数据
    """
    # 创建数据库连接
    conn = pymysql.connect(
        host='localhost',  # 数据库主机地址
        user='user',       # 数据库用户名
        password='pass',   # 数据库密码
        database='testdb'  # 数据库名称
    )
    # 创建字典格式的游标(返回数据为字典形式)
    cursor = conn.cursor(pymysql.cursors.DictCursor)
    
    # 执行SQL查询,获取用户创建场景的测试数据
    cursor.execute("SELECT * FROM api_test_data WHERE scenario = 'user_creation'")
    
    # 获取所有查询结果
    test_cases = cursor.fetchall()
    
    # 关闭数据库连接
    conn.close()
    return test_cases

# 第一种方式:从test_data中取值
@pytest.mark.parametrize("test_data", get_db_data())
def test_user_creation(test_data):
    """
    用户创建API测试
    Args:
        test_data (dict): 从数据库获取的测试数据,包含:
            - username: 测试用户名
            - password: 测试密码  
            - user_role: 用户角色
            - expected_status_code: 预期HTTP状态码
    """
    # 构造请求payload
    payload = {
        "username": test_data['username'],  # 使用测试数据中的用户名
        "password": test_data['password'],  # 使用测试数据中的密码
        "role": test_data['user_role']      # 使用测试数据中的用户角色
    }
    
    # 发送POST请求到用户创建接口
    response = requests.post("/api/users", json=payload)
    
    # 验证响应状态码是否符合预期
    assert response.status_code == test_data['expected_status_code'], \
        f"预期状态码{test_data['expected_status_code']},实际得到{response.status_code}"

# 第二种方式:从test_data中将多参数展开
@pytest.mark.parametrize("username,password,expected",
                         [(row['user'], row['pass'], row['expected'])
                          for row in get_db_data()])
def test_login(username, password, expected):
    """
    登录功能测试(多参数展开版)
    Args:
        username (str): 测试用户名
        password (str): 测试密码
        expected (bool): 预期结果(True/False)
    """
    # 调用登录函数
    result = login(username, password)
    
    # 验证登录结果是否符合预期
    assert result == expected, \
        f"用户名:{username} 密码:{password} 的登录结果应为{expected}"

 2.2.2 跳过 @pytest.mark.skip

@pytest.mark.skip(reason="功能尚未实现")  #括号内是跳过的原因,也可以不写
def test_new_feature():
    pass

3.常用插件
3.1 pytest-rerunfailures 插件 (失败重连)
3.1.1 安装

pip install pytest-rerunfailures

3.1.2 配置

在 pytest 的配置文件 pytest.ini、tox.ini 或 yproject.toml 中配置重试次数和延迟时间:

项目根目录下创建配置文件pytest.ini,

 右键新建file,修改名称为pytest.ini

编辑文件

# pytest.ini文件
[pytest]
reruns = 5
reruns_delay = 2

Allure报告

1.@allure.epic(),用于描述被测软件系统
2. @allure.feature(“功能名称”)
  • 作用:定义测试用例所属的功能模块,通常用于描述一个大的功能分类。

用法

import allure

@allure.feature("登录功能")
class LoginCase(unittest.TestCase):
  • 效果:在报告中将测试用例归类到“登录功能”模块。
3. @allure.story(“子功能名称”)
  • 作用:细化功能模块中的子功能,通常用于描述具体的功能点。
  • 用法
    import allure
    
    @allure.feature("登录功能")
    class LoginCase(unittest.TestCase):
        
    @story("用户登录")
    def test_user_login():
        # 测试用户登录的代码
        pass
    
  • 效果:在报告中进一步细分功能,例如将“登录功能”下的“用户登录”作为子功能展示。
4. @allure.title(“测试用例标题”)
  • 作用:为测试用例自定义标题,便于在报告中快速识别。
  • 用法
    import allure
    
    @allure.feature("登录功能")
    class LoginCase(unittest.TestCase):
        
    @story("用户登录")
    @title("验证用户登录成功")
    def test_login_success():
        # 测试登录成功的代码
        pass
    
  • 效果:在报告中显示自定义的标题,例如“验证用户登录成功”。
5. @allure.description(“测试用例描述”)
  • 作用:为测试用例添加详细描述,帮助理解测试用例的背景和目的。
  • 用法
    import allure
    
    @allure.feature("登录功能")
    class LoginCase(unittest.TestCase):
        
    @story("用户登录")
    @title("验证用户登录成功")
    @description("测试用户登录功能,验证输入正确用户名和密码后的行为")
    def test_login():
        # 测试登录功能的代码
        pass
    
  • 效果:在报告中显示详细的测试用例描述。
6. @allure.severity(severity_level)
  • 作用:定义测试用例的严重性级别,例如阻塞、严重、普通等。
  • 用法
    import allure
    
    @severity(SeverityLevel.BLOCKER)
    def test_critical_function():
        # 测试关键功能的代码
        pass
    
  • 效果:在报告中标记测试用例的严重性级别,例如“BLOCKER”。
7. @allure.step(“步骤描述”)
  • 作用:为测试用例中的某一步骤添加描述,便于在报告中展示详细步骤。
  • 用法
    import allure
    
    @testcase("https://example.com/testcase/456")
    def test_linked_case():
        # 测试用例的代码
        pass
    

import allure

def test_login():
    with step("输入用户名"):
        username = "testuser"
        attach("用户名", username)  # 可选:附加信息到报告中

    with step("输入密码"):
        password = "password123"
        attach("密码", password)  # 可选:附加信息到报告中

    with step("点击登录按钮"):
        # 模拟点击登录按钮的代码
        pass
  • 效果:在报告中显示具体的测试步骤,例如“步骤1:初始化数据”。
8. @allure.issue(“问题链接”)
  • 作用:为测试用例关联相关的问题或缺陷链接。
  • 用法
import allure

@issue("https://example.com/issue/123")
def test_with_issue():
    # 测试相关问题的代码
    pass
  • 效果:在报告中提供问题链接,便于追踪问题。
9. @allure.testcase(“测试用例链接”)
  • 作用:为测试用例关联测试用例管理工具中的用例链接。
  • 用法
import allure

@testcase("https://example.com/testcase/456")
def test_linked_case():
    # 测试用例的代码
    pass
  • 效果:在报告中提供测试用例的链接,便于查看详细用例信息。
10. @allure.link(“链接地址”, name=“链接名称”)
  • 作用:为测试用例添加任意链接,例如文档、需求等。
  • 用法
import allure

@link("https://example.com/docs", name="相关文档")
def test_with_link():
    # 测试代码
    pass
  • 效果:在报告中提供相关链接,便于访问额外资源。

执行

import pytest
import os
if __name__ == '__main__':
    
    # pytest.main():以编程方式运行 pytest;
    # './Case':指定测试用例的目录(假设测试用例存放在 ./Case 文件夹中)
    # -v:verbose 模式,显示详细的测试执行信息
    # --alluredir=./Report/allure_raw:指定 Allure 原始数据的输出目录
      pytest.main(['./Case', '-v', '--alluredir=./Report/allure_raw'])
    
    # os.system():执行系统命令。
    # allure generate:使用 Allure 命令行工具生成 HTML 报告
    # -o ./Report/allure_html:指定 HTML 报告的输出目录(./Report/allure_html)
    # --clean:清理输出目录(如果已存在)。
    os.system('allure generate ./Report/allure_raw -o ./Report/allure_html --clean')
    
    os.system('allure open ./Report/allure_html')  # 使用默认浏览器自动打开 Allure 报告

环境部署两张图片没有发上来,可以参考其他文章进行环境部署

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值