软件测试有多种多样的方法和技术,可以从不同角度对它们进行分类。其中,根据软件生命周期,针对不同的测试对象与目标,可将测试过程分为 4 个阶段:单元测试、集成测试、系统测试和验收测试。本文着重介绍了如何借用 pytest 与 httprunner 进行接口自动化测试。
一、 什么是接口测试
In computing, an interface is a shared boundary across which two or more separate components of a computer system exchange information. The exchange can be between software, computer hardware, peripheral devices, humans, and combinations of these.
根据 wiki 中的定义,接口是一个共享的边界,计算机系统的多个独立组件通过它交换信息。这些信息的交换可以基于软件、硬件、外部设备、人和它们之间的组合。根据上述定义,可以面向软件、硬件、交互设备等展开接口测试。软件的接口测试是面向独立组件之间接口的一种测试,主要用于检测内外部系统及内部各子系统之间的交互点。测试的重点在于检查逻辑正确性、交互依赖性、数据正确性.
基于以下几个情况,数栈引入自动化测试,以期提高测试效率,保障交付产品质量。
产品迭代迅速
目前数栈产品已经迭代至 Release4.3 版本。每过几个月进行一次产品 release 更新让回归测试的工作量持续上升。接口自动化测试可以很好的减少回归工作量。
应用系统日趋复杂
数栈目前自研 8 款产品和多个插件,产品之间的交互与产品 - 插件之间的交互日趋复杂。客观现实带来了更大的测试风险,测试消耗成本越来越高,花费的时间也越来越长。接口自动化测试可以提高测试效率。
部署环境多样
作为一款面向大数据的产品,除了开源的 Hadoop,还需要适配 TDH、CDH、HDP 等其他引擎。同时,各种客户的 POC 环境也需要大量人力支持。
接口测试可以使用的工具有很多,Postman、Jmeter、REST-Assured、SoapUI、httpclient 等等。数栈产品使用的是 HttpRunner 这个框架。相比较于前几类工具,它具有以下特点:
简单易用。
虽然前几款工具中有图形化界面可以让人直观的进行操作,但 HttpRunner 以 “关键字” 的优势可以让 QA 快速的上手框架,对代码能力要求低。根据对应的关键字填入相应的值,即可生成一条测试用例。
可扩展性强
HttpRunner 的 V3 版本支持了 pytest,可以方便的借助 pytest 插件解决接口测试中遇到的问题,如数据驱动、参数化等。jUnit 虽然也具有扩展性强的特点,但是 Java 语言对于 QA 来说太重,且学习成本比 HttpRunner 更高。
易于集成 CI
HttpRunner 支持 CLI 命令,可以方便的接入 Jenkins、Gitlab CI 等工具。
录制回放
通过 Charles、Fiddler 等工具将请求到处为.har 文件,然后通过 HttpRunner 提供的命令,就可以将.har 文件转换成 json/yaml 文件。
数栈产品曾使用过 Jmeter 作为接口自动化工具。Jmeter 拥有可视化图形界面,通过拖动组件信息就可完成用例编排,方便 QA 使用。但是 Jmeter 的内置函数不能满足于复杂的数栈产品,虽然可以选择 beanshell 来写工具脚本,但其难以调试,第三方包管理困难等问题使编写效率低下。同时 Jmeter 容易出现编码混乱、日志不易于查看等问题。
HttpRunner 作为一款优秀的开源框架,在 GitHub 上拥有 2.6k star,集简单易用、扩展性强、易于集成、录制回放等特性于一体,相比较于 Jmeter 更适用于数栈自动化实践。
数栈整体自动化测试架构如下图所示。从上到下可分为用户层、配置层、用例层、数据源。用户可以通过 Docker 镜像、Pipeline、定时任务来触发自动化任务。运行的结果记录到禅道,然后通过接入自研的 EasyV 进行展示。配置文件分为两类:一类是应用系统信息,如业务数据库信息、域名、账号密码等;另一类是数据源信息,用于用例的执行,现在支持的数据源有 MySQL、Oracle、Kafka、HBase 等等。从业务层面分,可以分为 8 个产品,每个产品编写各自的用例;从执行层面分,可分为接口测试和场景测试。若选择接口测试,则会运行所有产品的接口测试用例。下面拿接口测试用例进行举例说明。
一条接口测试用例可分为两部分:配置和测试步骤。先来看配置:
config = (
Config("测试创建项目接口")
.variables(
**{
"cookie": Cookie().get_cookie(),
"url": api.aiworks.aiworks_api.AiworksApi.create_project.value,
"tenant_name": ENV_CONF.uic.tenant_name,
"project_name": project_name
}
)
.base_url(ENV_CONF.base_url.rdos)
)
首先第一个遇到的问题就是获取 cookie。基本上接口都需要 cookie 或者 token 校验才能调用,因此将获取 cookie 的方法抽象提取成一个 get_cookie (),避免了每个用例写一遍登陆。这个方法就属于架构图中预置函数的模块。url、tenant_name、project_name 三个变量是后续测试步骤中所需要用到的变量值,这些都预先在 variables 中定义好。其中还可以看到有 AiworksApi、ENV_CONF 这几个文件。AiworksApi 是所有 Aiwork 产品的接口枚举类,对接口内容进行管理;ENV_CONF 包含了整个自动化项目的配置信息,是一个配置文件,属于配置层。
teststeps = [
Step(
RunRequest("开始请求创建项目接口")
.post("$url")
.with_headers(**{"cookie": "$cookie"})
.with_json(
{
"enableCycleSchedule": "$enableCycleSchedule",
"isSwitchJupyter": "$isSwitchJupyter",
"projectAlias": "$projectAlias",
"projectDesc": "$projectDesc",
"projectEngineList": "$projectEngineList",
"projectName": "$projectName",
"switchGpu": "$switchGpu"
}
)
.validate()
.assert_equal("status_code", 200)
.assert_equal("body.code", "$code")
.assert_contains("body.message", "$message")
.teardown_hook("${delete_project()}")
)
]
然后在测试步骤部分,整个 teststeps 由 Step 数组构成。可以看到创建项目这个接口只有一个 Step,整个 Step 分为 post、with_headers、with_json、validate、teardown_hooke5 个部分组成。其中,with_json 中 key-value 键值对的值全都是引用的方式来取得,而不是写死的固定值。这样就可以将用例与数据区分开来。而具体的值则通过 @pytest.mark.parameterize 这个装饰器传入,params 里定义了这个用例所需的所有字段值。整体用例编写思路为 “用例与数据分离”,避免修改测试用例需要改动大量的代码。
@pytest.mark.parametrize("params", params)
def test_start(self, params):
super().test_start(params)
所以整体来看,HttpRunner 框架提供了一个用例模版 -- 由多个关键字组成,使用者只需要将模版中的内容填充完整,就可以完成一条用例的编写。
自 2021 年 4 月自动化立项以来,已编写超过 900 条用例,8 个子产品接口覆盖率平均达到 60% 以上。每日通过 Jenkins 构建定时任务,在持续集成环境对最新的代码进行自动化测试。同时,自动化测试接入了测试环境、客户环境中使用。在提供环境信息完备的情况下,可以随时接入自动化,并运行得出报告给到 QA,大大减少了回归工作量,从原先 3-4 周的时间缩短到 1-2 周完成。
最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:
这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴上万个测试工程师们走过最艰难的路程,希望也能帮助到你!