接口自动化测试框架搭建:Pytest 入门

目录

1. 为什么选择 Pytest?

Pytest 的主要特性:

2. 安装 Pytest

3. Pytest 项目结构设计

目录结构说明:

4. pytest的命名规则

5. 使用 Fixture 进行测试数据初始化

示例:使用 Fixture 初始化测试数据

fixture 执行顺序

6. Pytest 运行方式

6.1 在命令行中运行测试

常用运行命令 

6.2 通过 PyCharm 运行测试

6.3 通过配置文件运行测试

7. 编写第一个接口测试用例

7.1 示例接口测试用例

7.2 编写 GET 请求的测试用例

7.3 运行测试

7.4测试失败时的情况

8. 测试多个请求方法

8.1 POST 请求测试用例

代码解释

9. 封装 HTTP 请求方法

9.1 编写封装的请求工具类

9.2 重写测试用例

10. 使用配置文件管理 API 地址

10.1 创建配置文件

10.2 读取配置文件

10.3 在测试用例中使用配置文件

11. 总结

1. 为什么选择 Pytest?

        Pytest 是 Python 中非常流行的测试框架,因其简洁的语法、灵活的扩展能力以及丰富的插件生态广受开发者和测试工程师的欢迎。它支持编写和执行单元测试、集成测试等各种测试类型。通过与 Requests 库结合,Pytest 可以非常方便地实现接口自动化测试。相比其他测试框架,Pytest 更加轻量化,并且无需继承类或编写过多的 boilerplate 代码,非常适合接口测试。

Pytest 的主要特性:

  • 简单易用:只需使用简单的函数和断言即可编写测试用例,不需要继承复杂的类。
  • 支持断言:Pytest 使用 Python 内置的 assert 语句进行断言,语法简洁明了,让测试结果更易读、易调试。
  • 可扩展:通过插件机制,可以扩展功能,如生成测试报告、并行执行测试等。
  • 自动发现测试用例:只需按照命名规则编写测试用例,Pytest 可以自动识别并执行。
  • 灵活的 Fixture 支持:Fixture 提供了灵活的测试准备和清理机制。

2. 安装 Pytest

在开始使用 Pytest 之前,首先需要安装它。你可以通过 pip 命令安装:

pip install pytest

安装完成后,你可以使用以下命令检查安装是否成功:

pytest --version

如果输出 Pytest 的版本信息,说明安装成功。

3. Pytest 项目结构设计

为了构建一个可扩展的接口自动化测试框架,我们需要规划项目结构,确保代码的可维护性和易扩展性。通常的项目目录结构如下:

project_root/
│
├── tests/                       # 测试用例目录
│   ├── test_api.py              # 接口测试用例文件
│
├── config/                      # 配置文件目录
│   └── config.yaml              # 配置文件(如API地址等)
│
├── utils/                       # 工具类目录
│   └── request_helper.py        # 封装请求的方法
│
└── pytest.ini                   # Pytest 配置文件

目录结构说明:

  • tests/: 存放所有的测试用例。
  • config/: 存放配置文件,如接口的基础 URL 等全局配置。
  • utils/: 用于存放常用工具类函数,比如封装 HTTP 请求的方法。
  • pytest.ini: Pytest 的配置文件,用于配置运行规则。

4. pytest的命名规则

1)模块名(py文件)必须是以test_开头或者_test结尾
2)测试类(class)必须以Test开头,并且不能带init方法,类里的方法必须以test_开头
3)测试用例(函数)必须以test_开头

以下是一个简单的测试用例示例,文件名为 test_sample.py

Class TestSample:
    def test_addition():
        assert 1 + 1 == 2

    def test_subtraction():
        assert 2 - 1 == 1

5. 使用 Fixture 进行测试数据初始化

Pytest 提供了 fixture 功能,用于在测试运行前设置测试环境,或在测试运行后清理资源。Fixture 可以用于准备测试数据、建立数据库连接等。

示例:使用 Fixture 初始化测试数据

import pytest

# 定义 fixture
@pytest.fixture
def sample_data():
    return {"name": "pytest", "age": 5}

# 测试用例中使用 fixture
def test_check_sample_data(sample_data):
    assert sample_data["name"] == "pytest"
    assert sample_data["age"] == 5

在上面的例子中,sample_data 是一个 fixture,返回一个字典对象,并被测试函数 test_check_sample_data() 使用。每次运行测试时,Pytest 会自动调用该 fixture。

fixture 执行顺序

Fixture 可以指定执行的顺序,默认是每个测试用例前都会重新调用一次 fixture。如果你希望某个 fixture 在所有测试用例执行前只执行一次,可以使用 scope="module" 参数:

@pytest.fixture(scope="module")
def setup():
    print("Setup for the module")

6. Pytest 运行方式

Pytest 提供了多种运行方式来执行测试用例,可以通过命令行、PyCharm 的 UI 界面或配置文件来运行测试。

6.1 在命令行中运行测试

最常用的方式是在终端中直接运行 Pytest 命令:

运行测试,在终端中进入包含测试文件的目录,并执行以下命令:

pytest

Pytest 会自动扫描当前目录及其子目录中的测试文件,找到所有符合命名规则的测试用例并执行。

如果想运行某个特定的测试文件,可以指定文件路径:

pytest tests/test_sample.py

常用运行命令 

-v    输出调试信息。如:打印信息    pytest -v tests/test_sample.py
-q    输出简单信息。    pyets -q tests/test_sample.py
-s    输出更详细的信息,如:文件名、用例名    pytest -s tests/test_sample.py
-n    多线程或分布式运行测试用例    pytest -n 4(会使用 4 个线程并行执行测试用例)
-x    只要有一个用例执行失败,就停止执行测试    pytest -x tests/test_sample.py
– maxfail    出现N个测试用例失败,就停止测试    pytest --maxfail=2 tests/test_sample.py
–html=report.html    生成测试报告    pytest tests/test_sample.py --html=./report/report.html
-m   运行带标记的测试用例   pytest -m smoke(使用@pytest.mark.smoke装饰器进行打标记)
-k    根据测试用例的部分字符串指定测试用例,可以使用and,or    pytest -k “MyClass and not method”,这条命令会匹配文件名、类名、方法名匹配表达式的用例,这里这条命令会运行 TestMyClass.test_something, 不会执行 TestMyClass.test_method_simple

6.2 通过 PyCharm 运行测试

PyCharm 集成了对 Pytest 的支持,可以方便地在 IDE 中运行测试。

  1. 配置 Pytest 为默认测试框架

    • 在 PyCharm 的菜单中,选择 File -> Settings(或 PyCharm -> Preferences,对于 macOS 用户)。
    • Tools -> Python Integrated Tools 中,找到 Testing 部分,将 Default test runner 设置为 pytest接口自动化测试框架搭建:Pytest 入门_第1张图片
  2. 运行测试用例

    • 在 PyCharm 中打开测试文件,点击文件顶部的绿色运行按钮(或右键点击文件,选择 Run 'pytest in ...'),PyCharm 会自动运行该文件中的所有测试用例。
    • 你也可以右键点击项目中的文件夹,选择 Run 'pytest in ...' 来运行整个文件夹中的测试用例。接口自动化测试框架搭建:Pytest 入门_第2张图片

6.3 通过配置文件运行测试

你可以使用 Pytest 的配置文件 pytest.ini 来定制测试运行的行为。创建 pytest.ini 文件并配置一些选项:


[pytest]
addopts=-vs -m slow --maxfail=2 -q --html=./report/report.html
testpaths=testcase
test_files=test_*.py
test_classes=Test*
test_functions=test_*
makerers=第一次执行

代码解释 

  • [pytest]:用于标志这个文件是pytest的配置文件    
  • addopts:为 Pytest 添加全局的命令行参数,多个参数之间用空格分隔    
  • testpaths:指定 Pytest 要扫描的测试用例文件夹    
  • test_files:改变默认的文件搜索规则    
  • test_classes:改变默认的类搜索规则    
  • test_functions:改变默认的测试用例的搜索规则    
  • markers:用例的标记,可以自定义,但需要先注册此标记,运行时才不会出现warning报错

pytset.ini文件尽可能不要出现中文。

在使用配置文件后,你只需运行 pytest,Pytest 会按照配置文件中的规则运行测试。

7. 编写第一个接口测试用例

接下来,我们将编写一个简单的接口测试用例,使用 Requests 库发送 HTTP 请求,并使用 Pytest 进行测试。

7.1 示例接口测试用例

我们将测试一个公开的 API:https://jsonplaceholder.typicode.com/posts,它提供了一个模拟的 RESTful API,用于测试和演示。

7.2 编写 GET 请求的测试用例

首先,我们编写一个 GET 请求的测试用例,验证返回的数据和状态码是否正确。

创建一个名为tests/test_api.py文件,并编写如下代码:

import requests

def test_get_post():
    url = "https://jsonplaceholder.typicode.com/posts/1"
    response = requests.get(url)

    # 验证状态码是否为 200
    assert response.status_code == 200, f"Expected 200, but got {response.status_code}"

    # 验证返回的数据是否符合预期
    data = response.json()
    assert data["userId"] == 1, f"Expected userId to be 1, but got {data['userId']}"
    assert data["id"] == 1, f"Expected id to be 1, but got {data['id']}"

代码解释

  • test_get_post(): Pytest 自动识别以 test_ 开头的函数为测试用例。
  • requests.get(url): 发送 GET 请求并获取响应。
  • assert response.status_code == 200: 验证响应的状态码是否为 200,表示请求成功。
  • assert data["userId"] == 1: 验证响应的 JSON 数据中 userId 字段是否为 1。

7.3 运行测试

运行测试,在终端中进入包含测试文件的目录,并执行以下命令:

pytest

Pytest 会自动发现 tests 目录下的以 test_ 开头测试文件并执行。若测试通过,输出类似如下:

============================= test session starts ============================== 
collected 1 item 
test_api.py .                                                             [100%] 
============================== 1 passed in 0.12s ===============================

这表示测试用例成功通过,. 号表示测试通过。

7.4测试失败时的情况

如果测试失败,Pytest 将显示详细的错误信息,帮助你快速定位问题。例如,如果我们将 userId 的预期值改为 2,重新运行测试,输出将类似于:

=================================== FAILURES ===================================
_______________________________ test_get_post _________________________________

    def test_get_post():
        url = "https://jsonplaceholder.typicode.com/posts/1"
        response = requests.get(url)

        assert response.status_code == 200, f"Expected 200, got {response.status_code}"
        data = response.json()
>       assert data["userId"] == 2, f"Expected userId to be 2, got {data['userId']}"
E       AssertionError: Expected userId to be 2, got 1

test_api.py:10: AssertionError
=========================== short test summary info ============================
FAILED test_api.py::test_get_post - AssertionError: Expected userId to be 2, got 1
============================== 1 failed in 0.15s ===============================

从输出信息可以清楚看到,断言失败的原因是 userId 的预期值和实际值不符。

8. 测试多个请求方法

Pytest 还可以帮助我们测试其他 HTTP 请求方法,例如 POST、PUT、DELETE 等。下面我们来编写一个简单的 POST 请求测试用例。

8.1 POST 请求测试用例

以下是一个发送 POST 请求并验证响应的示例:

import requests

# 测试 POST 请求
def test_post_request():
    url = "https://jsonplaceholder.typicode.com/posts"
    data = {
        "title": "foo",
        "body": "bar",
        "userId": 1
    }
    response = requests.post(url, json=data)

    # 验证状态码
    assert response.status_code == 201, f"Expected 201, got {response.status_code}"

    # 验证返回数据的 title
    response_data = response.json()
    assert response_data["title"] == "foo", f"Expected title to be 'foo', got {response_data['title']}"
代码解释
  • requests.post(url, json=data): 发送 POST 请求,向服务器提交数据。
  • assert response.status_code == 201: 验证状态码为 201,表示资源创建成功。
  • assert response_data["title"] == "foo": 验证服务器返回的响应数据中的 title 是否为预期值 foo

9. 封装 HTTP 请求方法

为了提高代码的可维护性,我们可以将 HTTP 请求操作封装成工具类方法。这样在多个测试用例中复用同样的请求逻辑时,可以减少重复代码。

9.1 编写封装的请求工具类

utils/request_helper.py 中编写一个封装的请求方法:

import requests

class RequestHelper:
    
    @staticmethod
    def get(url, params=None, headers=None):
        try:
            response = requests.get(url, params=params, headers=headers)
            return response
        except requests.RequestException as e:
            print(f"HTTP请求出错: {e}")
            return None

9.2 重写测试用例

更新 tests/test_api.py 文件:

from utils.request_helper import RequestHelper

def test_get_post():
    url = "https://jsonplaceholder.typicode.com/posts/1"
    response = RequestHelper.get(url)

    assert response.status_code == 200
    data = response.json()
    assert data["userId"] == 1
    assert data["id"] == 1

10. 使用配置文件管理 API 地址

10.1 创建配置文件

config/ 目录下创建一个名为 config.yaml 的文件:

base_url: "https://jsonplaceholder.typicode.com"

10.2 读取配置文件

编写工具函数来加载配置:

import yaml

def load_config():
    with open("config/config.yaml", 'r') as file:
        return yaml.safe_load(file)

10.3 在测试用例中使用配置文件

更新 tests/test_api.py 文件:

from utils.request_helper import RequestHelper
from utils.config_loader import load_config

def test_get_post():
    config = load_config()
    url = f"{config['base_url']}/posts/1"
    response = RequestHelper.get(url)

    assert response.status_code == 200
    data = response.json()
    assert data["userId"] == 1
    assert data["id"] == 1

11. 总结

      通过本篇文章,我们了解了如何使用 Pytest 进行接口自动化测试,掌握了 Pytest 的多种启动方式,封装了 HTTP 请求方法,并学会了如何使用配置文件管理 API 地址。从基础的 GET、POST 请求测试到参数化测试,Pytest 提供了强大的测试功能,同时保持了简单易用的特性。在实际的接口测试项目中,Pytest 是一个非常适合的选择,尤其是在处理大量接口测试用例时。在后续文章中,我们将继续探讨 Pytest 的进阶用法。

你可能感兴趣的:(接口自动化,pytest,自动化,python)