python接口自动化之如何在 Pytest 中使用异步 Fixture 进行验证码识别与自动登录获取token

1. 简介

• 介绍本篇文章的内容:使用 pytest 进行异步验证码识别和登录的自动化处理。

2. 环境准备

• 需要的库和工具:pytest, pytest-asyncio, httpx, ddddocr, PIL。

3. CaptchaLogin 类的实现

import ddddocr
from PIL import Image
from io import BytesIO
from common.logging_util import ERROR,DEBUG

class CaptchaLogin:
    def __init__(self):
        self.ocr = ddddocr.DdddOcr()

    # 获取并识别验证码,最多重试10次
    async def fetch_and_recognize_captcha(self, client, max_retries=10):
        for attempt in range(max_retries):
            # 发送请求获取验证码图片
            captcha_response = await client.get("https://www.xxxx.com/rest/user/captcha", timeout=10)
            # 读取响应内容并转换为图像
            image = Image.open(BytesIO(captcha_response.content))
            # 保存验证码图片到本地
            image.save("captcha.png")
            DEBUG(f"验证码图片已保存为 captcha.png (尝试 {attempt + 1}/{max_retries})")

            # 打开保存的验证码图片并读取为字节
            with open("captcha.png", "rb") as f:
                image_bytes = f.read()
            # 使用 ddddocr 进行验证码识别
            image_token = self.ocr.classification(image_bytes).strip()
            DEBUG(f"识别出的验证码: {image_token}")

            # 如果识别成功,则返回识别的验证码
            if image_token:
                return image_token
            DEBUG("识别验证码失败或验证码为空,重试中...")
        # 达到最大重试次数仍未成功识别,打印错误信息并返回 None
        return None

    # 发送登录请求,最多重试10次
    async def attempt_login(self, client, max_retries=10):
        image_token = await self.fetch_and_recognize_captcha(client)
        if not image_token:
            ERROR("验证码接口错误")
            return None

        for attempt in range(max_retries):
            # 准备登录请求的数据
            login_data = {
                "username": "admin",
                "password": "admin",
                "imageToken": image_token
            }
            DEBUG(f"发送的登录数据: {login_data} (尝试 {attempt + 1}/{max_retries})")
            headers = {'Content-Type': 'application/json'}
            # 发送登录请求
            login_response = await client.post("https://www.xxxx.com/rest/user/login", json=login_data, headers=headers, timeout=10)
            DEBUG(f"登录响应状态码: {login_response.status_code}")
            response_json = login_response.json()
            DEBUG(f"登录响应 JSON: {response_json}")

            # 检查响应是否表示登录成功
            if response_json.get('code') == 200:
                # 登录成功,返回 token
                return response_json.get('data', {}).get('token')
            # 如果响应消息表示验证码错误,则重新获取验证码并重试
            if response_json.get('msg', '').lower() in ['验证码错误', '验证码无效']:
                DEBUG("验证码错误,重新获取验证码...")
                image_token = await self.fetch_and_recognize_captcha(client)
                if not image_token:
                    break
            else:
                DEBUG("登录失败,重试中...")
        # 达到最大重试次数仍未成功登录,打印错误信息并返回 None
        ERROR("登录验证码有误,请检查")
        return None

4. 编写 conftest.py 文件

conftest.py 是 pytest 测试框架中的一个特殊文件,用于定义共享的 fixture 和测试配置。它在 pytest 项目中起到以下几个关键作用:

主要作用

定义全局或局部的 Fixture

• conftest.py 文件允许你定义 fixture,这些 fixture 可以在同一目录及其子目录中的所有测试文件中共享使用。通过这种方式,可以避免在每个测试文件中重复定义相同的 fixture。

• 例如,数据库连接、配置初始化等常见的准备工作,可以通过 fixture 在 conftest.py 中进行定义。

实现测试的自动发现和配置

• pytest 会自动发现并加载 conftest.py 文件中的配置。这使得你可以通过简单的目录结构管理复杂的测试项目,而无需在每个测试文件中进行额外的配置。

• 例如,可以在 conftest.py 中配置命令行选项、钩子函数等,来影响测试的执行方式。

管理跨测试的共享状态

• conftest.py 文件可以管理跨测试的共享状态,例如在多个测试用例之间共享一个数据库会话,或者在测试开始和结束时执行特定的操作(如启动和关闭服务)。

• 这对于需要在多次测试运行之间保持某种状态的场景非常有用。

示例代码

以下是一个 conftest.py 文件的示例,它定义了一个登陆并获取token,并在会话范围内共享:

import asyncio
import pytest
import httpx
from common.captch_login import CaptchaLogin
from common.cache_util import local_cache
from common.logging_util import INFO,DEBUG,WARNING,ERROR

@pytest.fixture(scope="session", autouse=True)
def work_login_init():
    """
    Fixture,负责整体登陆流程控制:获取并识别验证码,然后使用识别的验证码尝试登录。
    如果登录成功,保存 token;否则保存 None。
    """
    # 创建 CaptchaLogin 类的实例
    captcha_login = CaptchaLogin()

    async def login_task():
        """
        异步任务,负责使用 httpx.AsyncClient 发送请求以获取并识别验证码,然后尝试登录并保存 token。
        """
        # 使用 httpx.AsyncClient 创建异步 HTTP 客户端
        async with httpx.AsyncClient() as client:
            # 调用 captcha_login 实例的 attempt_login 方法进行登录尝试
            token = await captcha_login.attempt_login(client=client)
            if token:
                # 如果成功获取到 token,则将其保存到本地缓存
                local_cache.set_data('token', token)
                DEBUG(f"获得的 token: {token}")
            else:
                # 如果未成功获取到 token,则将 None 保存到本地缓存
                local_cache.set_data('token', None)
                ERROR("获取 token 失败")

5. 运行测试

在运行接口自动化初始,pytest会先运行conftest中的代码,上述代码介绍了获取登陆token,并存到缓存中.

6. 总结

在自动化测试中,验证码识别和登录通常是一个挑战。特别是在需要处理异步请求的情况下,测试代码的编写变得更加复杂。本文将详细介绍如何使用 pytest 结合 pytest-asyncio 插件,实现一个完整的异步验证码识别和登录的自动化测试流程。通过分步讲解,你将学习如何构建一个能够自动获取、识别验证码并完成登录的测试框架。希望本文能为你的自动化测试提供有价值的参考。

  • 8
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的示例代码: 1. 安装依赖库 ``` pip install requests pip install pytest ``` 2. 创建项目结构 ``` . ├── api │ ├── __init__.py │ └── login.py ├── case │ ├── __init__.py │ └── test_login.py ├── common │ ├── __init__.py │ └── utils.py └── pytest.ini ``` 3. 编写代码 api/login.py ```python import requests class LoginApi: def __init__(self): self.url = 'http://localhost:8080/api/login' def login(self, username, password): payload = { 'username': username, 'password': password } response = requests.post(self.url, json=payload) return response.json().get('data').get('token') ``` common/utils.py ```python import pytest from api.login import LoginApi @pytest.fixture(scope='session') def token(): api = LoginApi() return api.login('test', '123456') ``` case/test_login.py ```python def test_login(token): assert token is not None ``` 4. 运行测试 在项目根目录下运行以下命令: ``` pytest ``` 输出结果: ``` ============================= test session starts ============================= platform darwin -- Python 3.8.5, pytest-6.2.2, py-1.10.0, pluggy-0.13.1 rootdir: /Users/username/project collected 1 item case/test_login.py . [100%] ============================== 1 passed in 0.17s ============================== ``` 这样就完成了一个简单的接口自动化测试,并且封装了登录获取 token 的 API 和使用pytestfixture 机制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值