自动化工具 tep 用户手册帮你从 unittest 过渡到 pytest

dongfanger · 2020年12月23日 · 最后由 jeff 回复于 2021年01月23日 · 4265 次阅读
本帖已被设为精华帖!

unittest 和 pytest 是 Python 的 2 个强大的测试框架,经常用来做 UI 自动化或接口自动化。unittest 是 PyCharm 的默认集成工具,也是我们大多数人入门自动化的首选框架。pytest 提供了更丰富的功能,相对的上手难度也要高一点。如果学了 pytest 后,想快速用 pytest 写项目,用于工作实践,那么可以试试我写的这款测试工具:tep,try easy pytest。

tep 简介

在 Google 中输入python tep

tep 是一款测试工具,不是测试框架,它做的事情只是帮助你更轻松的使用 pytest 写项目代码,主要功能如下:

  • 项目脚手架
  • pytest 用例组织
  • 输出 HTML 测试报告
  • 基于 fixture 管理环境变量
  • 基于 fixture 共享公共函数
  • 访问 MySQL 数据库
  • 集成常用第三方包
  • 登录接口示例代码

工具安装

安装

tep 已经上传到了 PyPI(Python Package Index):

可以使用pip命令安装:

pip install tep

外网速度慢,pandas可能安装失败,推荐用国内镜像:

pip --default-timeout=6000 install -i https://pypi.tuna.tsinghua.edu.cn/simple tep

由于集成了第三方包,安装可能会花几分钟,请耐心等待。

Python 版本 3.6+

检查

安装完成后,检查是否安装成功:

tep -V
0.5.3

或者:

tep --version
0.5.3

升级

使用-U参数:

pip install -U tep

或者指定版本:

pip install tep==0.5.3

快速创建项目

tep 提供了脚手架,预置了项目结构和代码,打开 cmd,使用startproject命令快速创建项目:

cd some_directory
tep startproject project_name

创建后的项目结果如下:

当前版本主要用来做接口自动化,建议把不同业务系统建成多个项目。

1 个文件 2 处修改完成登录请求

tep 已经预置了登录相关代码,只需要打开fixtures\fixture_admin.py,修改 2 个地方的代码,就可以完成登录请求。

修改环境变量

编辑fixtures/fixture_admin.py

@pytest.fixture(scope="session")
def env_vars(config):
    class Clazz:
        def __init__(self):
            env = config["env"]
            self.mapping = {
                "qa": {
                    "domain": "https://qa.com",
                    "mysql_engine": mysql_engine("127.0.0.1",  # host
                                                 "2306",  # port
                                                 "root",  # username
                                                 "123456",  # password
                                                 "test")  # db_name
                },
                "release": {
                    "domain": "https://release.com",
                    "mysql_engine": mysql_engine("127.0.0.1",
                                                 "2306",
                                                 "root",
                                                 "123456",
                                                 "release")
                }
                # Add your env and variables
            }
            self.domain = self.mapping[env]["domain"]
            self.mysql_engine = self.mapping[env]["mysql_engine"]
            # Add properties

        def add(self, env, key, value):
            self.mapping[config["env"]][key] = value

    return Clazz()

mapping是个字典,预置了 2 个环境:qarelease,每个环境预置了 2 个变量:domainmysql_engine

domain

url = domain +uri,例如https://qa.com/api/users/login/的 domain 是`https://qa.com,uri 是/api/users/login/

首先把qa环境的domain值改为你的测试域名。

修改登录代码

继续编辑fixtures/fixture_admin.py

def _jwt_headers(token):
    return {"Content-Type": "application/json", "authorization": f"Bearer {token}"}


@pytest.fixture(scope="session")
def login():
    # Code your login
    logger.info("Administrator login")
    response = request(
        "post",
        url=url("/api/users/login/"),
        headers={"Content-Type": "application/json"},
        json={
            "username": "admin",
            "password": "123456",
        }
    )
    assert response.status_code < 400
    response_token = jmespath.search("token", response.json())

    class Clazz:
        token = response_token
        jwt_headers = _jwt_headers(response_token)

    return Clazz

# Code your login处开始修改代码,替换 API 路径/api/users/login/和请求参数json。如果你的登录接口不会返回 token,那么修改jmespath.search("token", response.json())为实际响应取值。

tep 预置登录返回了 2 个值:tokenjwt_headers

测试登录

打开tests/login_test.py

from loguru import logger


def test_login(login):
    logger.info(login.token)

执行后就会调用登录接口发起请求。

遇到问题无法解决请留言或加群。

编写测试用例

用例组织

测试用例全部放在tests目录下:

每个.py模块以test_前缀或_test后缀命名,每个test函数以test前缀命名。只要遵循这个规则,目录层次不影响。示例:

建议每个.py模块只包含 1 个test函数,也就是 1 条测试用例。

接口请求设计

每条测试用例可以包含单个或多个接口请求。tep 预置了 1 个 POST 请求示例代码,打开tests/post_test.py

import jmespath
from loguru import logger

from tep.client import request


def test_post(faker_ch, url, login):
    # description
    logger.info("test post")
    # data
    fake = faker_ch
    # request
    response = request(
        "post",
        url=url("/api/users"),
        headers=login.jwt_headers,
        json={
            "name": fake.name()
        }
    )
    # assert
    assert response.status_code < 400
    # extract
    user_id = jmespath.search("id", response.json())

每个请求由 5 部分组成,从上往下分别是描述、数据、请求、断言和提取。

借鉴了 JMeter 元件和参数化关联的设计思想。

描述

描述这个请求是干嘛的。

数据

初始化局部变量,例如使用 faker 库造测试数据。

请求

如果需要打印请求日志,可以from tep.client import requesttep.client.requestrequests.request除了记录日志外,没有做任何修改。

如果请求报错了,那么很可能是代码写错了。

也可以直接使用原生requestfrom requests import request

不同请求方法的代码如下:

request("get", url="", headers={}, json={})
request("post", url="", headers={}, params={})
request("put", url="", headers={}, json={})
request("delete", url="", headers={})

# 上传excel
request("post",
        url="",
        headers={},
        files={
            "file": (
                file_name,
                open(file_path, "rb"),
                "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
            )
        },
        verify=False
    )

更多用法参考requests.request

断言

断言使用 Python 标准断言assert 表达式,表达式跟if语句表达式一模一样。

提取

推荐使用jmespath提取 JSON 数据,也可以使用 Python[]中括号提取。

HTML 测试报告

批量执行用例

单个测试用例,在 PyCharm 中执行就可以了。多个测试用例批量执行,需要打开左下角的Terminal,输入命令来执行:

# 先进入tests目录
cd tests
# 批量执行
pytest

只收集不执行

如果只想统计用例条数,不执行代码,那么可以使用以下命令:

pytest --co

HTML 测试报告

tep 提供了--tep-reports参数来生成 allure 测试报告:

pytest  --tep-reports

报告文件存放在根目录的reports/中:

右键index.html选择:

就会打开浏览器显示测试报告了:

默认 allure 报告右上角的TREND是无法显示数据的,--tep-reports修复了这个问题,根据 history 数据生成TREND走势图。

自定义环境变量

静态添加

编辑fixtures/fixture_admin.py,在mapping字典中# Add your env and variables处添加环境变量,在# Add properties处添加属性,参考domainmysql_engine。示例:

动态添加

使用add()方法动态添加环境变量:

env_vars.add("my_var", 789)

使用环境变量

env_vars返回了类对象实例,通过.运算符来使用环境变量:

env_vars.domain
env_vars.mysql_engine
env_vars.my_var

不需要 import,而是给 test 函数添加参数,如def test(env_vars):

切换环境

conf.yaml文件中配置:

env: qa

默认为qa环境。

团队共享公共函数

通过 fixture 技术,我们可以把重复代码提取出来,在团队间进行复用。tep 重度使用了这个技术,在fixtures目录中,除了预置的fixture_admin.py,可以继续添加团队成员的 fixture:

新添加的fixture_your_name.py需要到根目录的conftest.py中注册才能生效:

# Import fixtures
exec("from .fixtures.fixture_admin import *")
exec("from .fixtures.fixture_your_name import *")

conftest.py 模块中建议全部定义成 fixture,不对外提供 function。

为了避免命名冲突和代码跟踪,团队成员的公共函数命名建议加上_yourname后缀。

访问 MySQL 数据库

首先在fixtures\fixture_admin.py中修改mysql_engine

"mysql_engine": mysql_engine("127.0.0.1",  # host
                             "2306",  # port
                             "root",  # username
                             "123456",  # password
                             "test")  # db_name

依次填写主机名、端口、用户名、密码、数据库名。

接着使用 pandas 来访问数据库,tests\mysql_test.py预置了示例代码:

from loguru import logger


def test_mysql(pd, env_vars):
    logger.info(pd.read_sql("select 1 from dual", env_vars.mysql_engine))

返回的数据可以通过data["列名"]["行号"]的方式读取。

如果想在 console 中以表格方式显示表数据,可以使用tep.dao.print_db_table()函数,如:

from loguru import logger
from tep.dao import print_db_table


def test_mysql(pd, env_vars):
    data = pd.read_sql("select 1 from dual", env_vars.mysql_engine)
    logger.info(print_db_table(data))

第三方包集成说明

tep 使用了 Poetry 来管理包和依赖:

目前已集成:

# 造测试数据
faker = "^4.1.1"
# 提取JSON数据
jmespath = "^0.10.0"
# 屏蔽HTTPS警告
urllib3 = "^1.25.9"
# HTTP/HTTPS请求
requests = "^2.24.0"
# HTML测试报告
allure-pytest = "^2.8.16"
allure-python-commons = "^2.8.16"
# 打印日志
loguru = "^0.5.1"
# 访问数据库
pandas = "^1.1.0"
# 配置文件
pyyaml = "^5.3.1"
# 为pandas访问数据库提供engine
sqlalchemy = "^1.3.22"
# 把数据库表打印成表格
texttable = "^1.6.3"
# 支持sqlalchemy使用
pymysql = "^0.10.1"

东方说

最早写这个工具的想法是以项目工程方式使用 pytest,并结合第三方包完成接口自动化落地。如果你也有类似的想法,那么可以参考 tep 的做法。tep 用户手册是针对于 tep 工具本身的使用说明,不包含 pytest 框架搭建和基本使用,如果想入门 pytest 并深度学习,可以阅读我写的 pytest 系列文章,共 8 篇。tep 的最新版本是0.5.3,还不够稳定,也存在 bug,我会坚持维护下去,既是实用工具,也是技术沉淀。对 tep 有任何建议或问题,欢迎留言或公众号后台回复 “加群” 讨论哦。

参考资料:

源码 https://github.com/dongfanger/tep

共收到 8 条回复 时间 点赞
恒温 将本帖设为了精华贴 12月26日 13:08
dongfanger pytest 用例数据依赖如何处理 中提及了此贴 12月28日 02:10

感谢恒温大佬加精!

这种帖子也加精?测试用例入参写死在代码里面?以后维护起来岂不是要改代码?数据库双重断言呢?

此生不换 回复

我也没想到被加精了,从读者了解到,文章亮点是给快速搭建自动化项目提供了便利。
tep 只是一款测试工具,不像测试框架逼着你非得这么干,数据代码分离可以通过 fixture 来实现,取决于个人需求和代码习惯。
断言也是一个道理,严谨的话就加上数据库断言呗。

安装失败了,提示:
ERROR: Could not find a version that satisfies the requirement tep
ERROR: No matching distribution found for tep

lin-cz 回复

试试 pip install tep==0.5.3

dongfanger 回复

也不行

lin-cz 回复

再试试这条命令
pip install --default-timeout=6000 -i https://pypi.tuna.tsinghua.edu.cn/simple tep

pip 最近有问题,如果是 3.8.7 版本 这样安装 pip install --use-feature=2020-resolver tep

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册