汕尾海湾 发表于 2024-8-18 20:13:12

接口自动化测试实践

众所周知,接口自动化测试有着如下特点:


[*] 低投入,高产出。
[*] 比力容易实现自动化。
[*] 和UI自动化测试相比更加稳定。
如何做好一个接口自动化测试项目呢?
我以为,一个“好的”自动化测试项目,需要从“时间”、“人力”、“收益”这三个方面出发,做好“取舍”。
不能由于被测体系发生一些变更,就导致花费了几个小时的自动化脚本无法实行。同时,我们需要看到“收益”,不能为了总想看到100%的乐成,而少做或者不做校验,但是校验多了维护成本肯定会增多,可能每天都需要进行大量的维护。
所以做好这三个方面的平衡并不容易,常常能看到做自动化的同砚,做到最后就本末倒置了。
进步ROI

 
想要进步ROI(Return On Investment,投资回报率),我们必须从两方面入手:

[*] 淘汰投入成本。
[*] 增加使用率。
针对“淘汰投入成本”


我们需要做到:


[*]淘汰工具开辟的成本。尽可能的淘汰开辟工具的时间、工具维护的时间,尽可能使用公司已有的,或是业界成熟的工具或组件。
[*]淘汰用例录入成本。简化测试用例录入的成本,尽可能多的提示,如果可以,开辟一些批量天生测试用例的工具。
[*]淘汰用例维护成本。淘汰用例维护成本,尽量只用在页面上做简朴的输入即可完成维护动作,而不是进行大量的代码操纵。
[*]淘汰用例优化成本。当团队做用例优化时,可以通过一些统计数据,进行有针对性、有目的性的用例优化。

针对“增加使用率”

我们需要做到:


[*]手工也能用。不但是进行接口自动化测试,也可以完全用在手工测试上。
[*]人人能用。每一个需要使用测试的人,包罗一些非技术职员都可以使用。
[*]当工具用。将一些接口用例当成工具使用,好比“天生订单”工具,“查找表单数据”工具。
[*]每天测试。进行逐日构建测试。
[*]开辟的在构建之后也能触发测试。开辟将被测体系构建后,能自动触发接口自动化测试脚本,进行测试。
所以,我开辟了Lego接口测试平台,来实践本身对自动化测试的一些想法。先简朴欣赏一下网站,了解一下大概是个什么样的工具。

首页:


https://i-blog.csdnimg.cn/blog_migrate/18151ff8be1c66e3c11ed95eb196b878.jpeg

用例维护页面:


https://i-blog.csdnimg.cn/blog_migrate/a226963aadc905cbeeebf1ecf73a2cca.jpeg

自动化用例列表:


https://i-blog.csdnimg.cn/blog_migrate/519f4c3f076de4adf02f6cd4db1249a8.jpeg

在线实行结果:


https://i-blog.csdnimg.cn/blog_migrate/bdb85196b7699b4d17268cb1c8352d96.jpeg
用例数目统计:


https://i-blog.csdnimg.cn/blog_migrate/3e9b71aabd9357330f5c6a79e78cd2f5.jpeg

Lego的构成

Lego接口测试办理方案是由两部分构成的,一个就是刚刚看到的“网站”,另一个部分就是“脚本”。
下面就开始进行“脚本设计”部分的先容。
脚本设计
Lego的做法

Lego接口自动化测试脚本部分,使用很常见的Jenkins+TestNG的结构。
https://i-blog.csdnimg.cn/blog_migrate/8fa8e48de655877319171e9c8a76548e.jpeg

相信看到如许的模型并不陌生,由于许多的测试都是如许的构成方式。
将自动化测试用例存储至MySQL数据库中,做成比力常见的“数据驱动”做法。
许多团队也是使用如许的结构来进行接口自动化,沿用的话,那在以后的“推广”中,学习和迁移成本低都会比力低。
测试脚本

起首来简朴看一下目前的脚本代码:

public class TestPigeon {

String sql; int team_id = -1; @Parameters({"sql", "team_id"}) @BeforeClass() public void beforeClass(String sql, int team_id) { this.sql = sql; this.team_id = team_id;

ResultRecorder.cleanInfo();

} /**

* XML中的SQL决定了执行什么用例, 执行多少条用例, SQL的搜索结果为需要测试的测试用例

*/

@DataProvider(name = "testData") private Iterator<Object[]> getData() throws SQLException, ClassNotFoundException { return new DataProvider_forDB(TestConfig.DB_IP, TestConfig.DB_PORT,

TestConfig.DB_BASE_NAME,TestConfig.DB_USERNAME, TestConfig.DB_PASSWORD, sql);

} @Test(dataProvider = "testData") public void test(Map<String, String> data) { new ExecPigeonTest().execTestCase(data, false);

} @AfterMethod

public void afterMethod(ITestResult result, Object[] objs) {...} @AfterClass

public void consoleLog() {...}

} https://i-blog.csdnimg.cn/blog_migrate/323a62e7f527b24e3952ef7aa32d17dc.jpeg

有一种做法我不停不提倡,就是把测试用例直接写在Java文件中。如许做会带来许多题目:


[*] 修改测试用例需要改动大量的代码;
[*] 代码也不便于交接给其他同砚,由于每个人都有本身的编码风格和用例设计风格,如许交接,最后都会变成由下一个同砚全部推翻重写一遍;
[*] 如果测试平台更换,无法做用例数据的迁移,只能手动的一条条重新输入。
所以“测试数据”与“脚本”分离是非常有须要的。
网上许多的范例是使用的Excel进行的数据驱动,我这里为什么改用MySQL而不使用Excel了呢?
在公司,我们的脚本和代码都是提交至公司的Git代码堆栈,如果使用Excel的话,每次进行自动化测试用例的维护,都需要将修改好的代码和Excel文件推送到代码平台上,需要进行一些列的Add、Commit、Push等操纵,很显然不方便日常常常修改测试用例的情况。
使用MySQL就没有如许的烦恼了,由于数据与脚本的分离,只需对数据进行修改即可,脚本每次会在数据库中读取最新的用例数据进行测试。同时,还可以防止一些操纵代码时的误操纵。
这里再附上一段我本身写的DataProvider_forDB方法,方便其他同砚使用在本身的脚本上:

import java.sql.*;

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;


/**

* 数据源 数据库

*

* @author yongda.chen

*/

public class DataProvider_forDB implements Iterator<Object[]> {


ResultSet rs;

ResultSetMetaData rd;


public DataProvider_forDB(String ip, String port, String baseName,

String userName, String password, String sql) throws ClassNotFoundException, SQLException {


Class.forName("com.mysql.jdbc.Driver");

String url = String.format("jdbc:mysql://%s:%s/%s", ip, port, baseName);

Connection conn = DriverManager.getConnection(url, userName, password);

Statement createStatement = conn.createStatement();


rs = createStatement.executeQuery(sql);

rd = rs.getMetaData();

}


@Override

public boolean hasNext() {

boolean flag = false;

try {

flag = rs.next();

} catch (SQLException e) {

e.printStackTrace();

}

return flag;

}


@Override

public Object[] next() {

Map<String, String> data = new HashMap<String, String>();

try {

for (int i = 1; i <= rd.getColumnCount(); i++) {

data.put(rd.getColumnName(i), rs.getString(i));

}

} catch (SQLException e) {

e.printStackTrace();

}

Object r[] = new Object;

r = data;

return r;

}


@Override

public void remove() {

try {

rs.close();

} catch (SQLException e) {

e.printStackTrace();

}

}

} 设置文件

上面图中提到了“设置文件”,下面就来简朴看一下这个XML设置文件的脚本:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd"><suite name="Pigeon Api测试" parallel="false">


<test name="xxx-xxx-service">

<parameter name="sql"

value="SELECT * FROM API_PigeonCases

WHERE team_id=2

AND isRun=1

AND service='xxx-xxx-service'

AND env='beta';"/>

<classes>

<class name="com.dp.lego.test.TestPigeon"/>

</classes>

</test>


<listeners>

<listener class-name="org.uncommons.reportng.HTMLReporter"/>

<listener class-name="org.uncommons.reportng.JUnitXMLReporter"/>

</listeners></suite> https://i-blog.csdnimg.cn/blog_migrate/34bc880ffaf3f95e14576cb76c60c362.jpeg

对照上图来解释一下设置文件:


[*] SQL的话,这里的SQL主要决定了选取哪些测试用例进行测试。
[*] 一个
标签,就代表一组测试,可以写多个标签。
[*] “listener”是为了最后可以或许天生一个ReportNG的陈诉。
[*] Jenkins来实现逐日构建,可以使用Maven插件,通过命令来选择需要实行的XML设置。
如许做有什么好处呢?


使用SQL最大的好处就是机动

https://i-blog.csdnimg.cn/blog_migrate/34b3d0434d5674155d3572025b11318f.jpeg

如上面的这个例子,在数据库中会查询出下面这56条测试用例,那么这个标签就会对这56条用例进行逐一测试。
多标签时,可以分组展示



https://i-blog.csdnimg.cn/blog_migrate/3a753eed8daf8010de0ace8f835c8df9.jpeg

使用多个标签来区分用例,最大的好处就是也能在最后的陈诉上,达到一个分组展示的效果。

陈诉更雅观丰富



https://i-blog.csdnimg.cn/blog_migrate/3563e2305c43f32a6e269627736ca8af.jpeg
由于使用了ReportNG进行陈诉的打印,所以陈诉的展示要比TestNG自带的陈诉要更加雅观、并且能自定义展示样式,点开能看到具体的实行过程。


https://i-blog.csdnimg.cn/blog_migrate/e1a02a3bc6a8dc54f4067bb909dae9d0.jpeg

如果有实行失败的用例,通常报错的用例会在最上方优先展示。

支持多团队

 

https://i-blog.csdnimg.cn/blog_migrate/a44431623174ab6066ee3cb31818d82d.jpeg

当两个团队开始使用时,为了方便维护,将底子部分抽出,各个团队的脚本都依赖这个Base包,并且将Base包版本置为“SNAPSHOT版本”。使用“SNAPSHOT版本”的好处是,之后我对Lego更新,各个业务组并不需要对脚本做任何改动就能及时更新。
当更多的团队开始使用后,比力直观的看的话是这个样子的:
https://i-blog.csdnimg.cn/blog_migrate/b83744364a636116ddb65a316fbbf2c3.jpeg
每个团队的脚本都依赖于我的这个Base包,所以最后,各个业务团队的脚本就变成了下面的这个样子:


https://i-blog.csdnimg.cn/blog_migrate/4d972ff7015d05dedbce90f9e6c24b60.jpeg


[*]可以看到,使用了Lego之后:
[*]没有了Java文件,只有XML文件
[*]xml中只需要设置SQL。
[*]实行和调试也很方便。
[*]可以右键直接实行想要实行的测试设置。
[*]可以使用maven命令实行测试:
[*]mvn clean test -U -Dxml=xmlFileName 。
[*]通过参数来选择需要实行的xml文件。
[*]也可以使用Jenkins来实现定时构建测试。

由于,所有测试用例都在数据库所以这段脚本基本不需要改动了,淘汰了大量的脚本代码量。
有些同砚要问,有时候编写一条接口测试用例不但是哀求一下接口就行,可能还需要写一些数据库操纵啊,一些参数可能还得本身写一些方法才华获取到啊之类的,那不code怎么处理呢?
下面就进入“用例设计”,我将先容我如何通过统一的用例模板来办理这些题目。
用例设计
一些思考

 
我在做接口自动化设计的时候,会思考通用、校验、坚固、易用这几点。

通用



[*]简朴、方便
[*]用例数据与脚天职离,简朴、方便。
[*]免去上传脚本的动作,能避免许多不须要的错误和维护时间。
[*]便于维护。
[*]模板化
[*]抽象出通用的模板,可快速拓展。
[*]数据结构同等,便于批量操纵。
[*]专人维护、淘汰多团队间的重复开辟工作。
[*]由于使用了统一的模板,那各组之间便可交流、学习、做有效的对比分析。
[*]如果以后这个平台不再使用,或者有更好的平台,可快速迁移。
[*]可统计、可拓展
[*]可统计、可开辟工具;如:用例数统计,某服务下有多少条用例等。
[*]可开辟用例维护工具。
[*]可开辟批量天生工具。
校验

 
在写自动化脚本的时候,都会想“过细”,然后“写许多”的查抄点;但当“校验点”多的时候,又会由于许多原因造成实行失败。所以我们的设计,需要在包管充足的查抄点的情况下,还要尽可能淘汰误报。


[*] 充足的查抄点

[*] 可以查抄出被测服务更多的缺陷。

[*] 尽量少的误报

[*] 可以淘汰许多的人工查抄和维护的时间人力成本。

[*] 还要

[*] 简朴、易读。
[*] 最好使用一些公式就能实现本身想要的验证。
[*] 通用、机动、多样。
[*] 甚至可以用在其他项目的查抄上,淘汰学习成本。

坚固

 
实行测试的过程中,不免会报失败,实行失败可能的原因有许多,简朴分为4类:

https://i-blog.csdnimg.cn/blog_migrate/f93f23b200082f3225ea4c1056ed2f21.jpeg



[*]被测体系出错,这部分实在是我们希望看到的,由于这说明我们的自动化测试真正地发现了一个Bug,用例发挥了它的价值,所以,这是我们希望看到的。
[*]测试工具出错,这部分实在是我们不希望看到的,由于很大可能我们本日的自动化相当于白跑了。
[*]测试数据错误,这是我们要避免的,既然数据容易失效,那我在设计测试平台的时候,就需要考虑如果将所有的数据跑“活”,而不是只写“死”。
[*]不可抗力,这部分是我们也很无奈的,但是如许的情况很少发生。
那针对上面的情况:


[*]参数数据失效
[*]支持及时去数据库查询。
[*]支持批量查。
[*]IP出场发生变更
[*]自动更新IP。
[*]机动、可复用
[*]支持批量维护。
[*]接口测试实行前天生一些数据。
[*]接口实行完成后烧毁一些数据。
[*]支持参数使用另一条测试用例的返回结果。
[*]支持一些哀求参数及时天生,如token等数据,从而淘汰数据失效的题目。

通过这些手段,进步测试用例的坚固性,让每一条自动化测试用例都能很好的完成测试任务,真正发挥出一条测试用例的价值。

易用



[*] 简朴

[*] 功能强盛,但要人人会用。
[*] 非技术职员也要会用。

[*] 淘汰代码操纵

[*] 让自动化开辟职员留意力能更多的放在用例本身,而不是浪费在可有可无的开辟工作上面。

[*] 还要

[*] 设置能复用。
[*] 通用、易学。
[*] 一些数据能自动天生。

Lego接口自动化测试用例

说了这么多,那我们来看看Lego接口测试用例的样子。
一条Lego自动用例实行顺序大概是如下图如许:
https://i-blog.csdnimg.cn/blog_migrate/e417bb06b1eaf1c60e56eb4d92b0af45.jpeg

简朴区分一下各个部分,可以看到:


https://i-blog.csdnimg.cn/blog_migrate/3c4a527873afd47634c8eb536518b6c4.jpeg

那上面图中提到了两个名词:


[*] “参数化”
[*] “前后置动作”

下面会先对这两个名词做一个简朴的先容。

参数化

 
好比一个哀求需要用到的参数。

{

"sync": false,

"cityId": 1,

"source": 0,

"userId": 1234,

"productId": 00004321}  这个例子中有个参数"productId": 00004321,而由于测试的情况中,表单00004321很可能一些状态已经发生了改变,甚至表单已经删除,导致接口哀求的失败,那么这时候,就很恰当对"productId": 00004321进行参数化,好比写成如许:

{

"sync": false,

"cityId": 1,

"source": 0,

"userId": 1234,

"productId": ${myProductId}

}
所以对“参数化”简朴的理解就是:

   通过一些操纵,将一个“值”更换掉测试用例里的一个“替代字符”

${myProductId} 的值可以通过设置获取到:


[*] Key-Value

[*] 设置 Value=00004321。

[*] SQL获取

[*] 实行一个select语句来及时查询得到可用ID。

[*] 已有测试用例

[*] 某个接口接口测试用例的返回结果。


“参数化”实例


下面我们来看一个“参数化”的实例:

(1)起首我们在参数化维护页面中新建一个参数化,shopdealid。


https://i-blog.csdnimg.cn/blog_migrate/cb2b83c306e3d0a9b278baf598d7bf5e.jpeg
通过设置我们可以看到这个参数的值,是实行了一条SQL后,取用实行结果中DealID字段的值。

(2)在用例中,将需要这个表单号的地方用${shopdealid}替代。


https://i-blog.csdnimg.cn/blog_migrate/5e92d9736f36bed7d8f09fa51042f345.jpeg

那在编写测试用例的时候,各人可以看一下这个放大的图片,在这里的ProductID的值并不是硬代码一个固定的表单号,而是选择了刚才设置的参数化数据。

(3) 实行结果中,${shopdealid} 变为及时查询数据库的来的一个真实的表单号。


https://i-blog.csdnimg.cn/blog_migrate/663d9fb802b9c469cbfa4bc627bd54e5.jpeg
从结果中可以看到,我们的这个参数被更换成了一个有效的值,而这个值就是我们刚刚设置的那个SQL及时查询而来的。

“参数化”的场景


多个测试用例使用同一个参数进行测试
如50条测试用例都使用同一个id作为参数进行测试,这时候我们需要变更这个ID。

无参数化时:


[*] 需要修改50次,即每条测试用例中的id都得进行修改。
[*] 可能会有遗漏。
有参数化时:


[*] id部分用 ${myID} 替代。
[*] 需要修改的话,在“参数化维护”页面中维护 ${myID}这条数据就可以。修改一次,所有使用${myID}的用例都设置完成。

测试数据逾期导致测试用例实行失败

如一条用例参数需要传入token,但是Token会由于时间题目而导致逾期,这时候用例就失败了。

无参数化时:


[*] 常常修改Token,或是写一段id转Token的代码。
[*] 方法可能会重复编写。
[*] 多个团队之间可能实现方式也差别。

有参数化时:


[*] 使用参数化工具,Lego统一管理。
[*] 维护一个参数化 如:${测试用Token} = id:123。

数据库获取有效测试数据
参数中需要传入DealId作为参数,写死参数的话,如果这个DealId被修改引起失效,那这条测试用例就会实行失败。

不使用Lego时:


[*]测试情况中,一个订单时常会由于测试需要被修改数据,导致单号失效,最后导致自动化失败。
[*]编写相关代码来做好数据准备工作。
[*]在代码中编写读取数据库的方法获取某些内容。
在Lego上的方案:


[*]使用参数化,及时获取sql结果,查询出一条符合条件的dealId来实现。
[*]使用参数化,调用写好的“天生订单”接口用例实现,拿单号来实现。
[*]前后置动作,插入一条满足条件的数据。
前后置动作

 
“前后置动作”的概念就比力好理解了:
   在接口哀求之前(或之后),实行一些操纵
目前前后置动作支持6种范例:


[*] 数据库SQL实行

[*] 有时候在实行接口哀求前,为了包管数据可用,可能需要在数据库中插入或删除一条信息,这时候就可以使用前后置动作里的“实行SQL语句”范例,来编写在接口哀求前(后)的 Insert 和 Delete 语句。

[*] 已有测试用例实行
[*] 好比当前测试用例的哀求参数,需要使用另一条测试用例的返回结果,这时候就可以使用“实行测试用例”范例,写上Lego上某条测试用例的ID编号,就可以在当前用例接口哀求前(后)实行这条测试用例。
[*] 前后置动作中测试用例的返回结果可以用于当前用例的参数,对测试用例返回结果内容的获取上,也支持JsonPath和正则表达式两种方式。


[*]
[*] MQ消息发送

[*] 在接口哀求前(后)发送MQ消息。

[*] HTTP哀求
[*] 等候时间
[*] 自定义的Java方法

[*] 如果上面的方法还满足不了需求,还可以根据本身的需要,编写本身的Java方法。
[*] 可以在Lego-Kit项目中,编写本身需要的Java方法,选择“实行Java方法”,通过反射实现自定义Java方法的实行。


这里的SQL同时支持Select操纵,这里实在也是做了一些小的设计,会将查询出来的全部的结果,放入到这个全局Map中。

好比查询一条SQL得到下表中的结果:

https://i-blog.csdnimg.cn/blog_migrate/63fb8e84a070fd6d6565779a2907b4a9.png
那我们可以使用下面左边的表达式,得到对应的结果:


[*]${pre.name} ---- 得到 “张三”å
[*]${pre.age} ---- 得到 18
[*]${pre.number} ---- 得到 1122
也可以用:


[*]${pre.name} ---- 得到 “张三”
[*]${pre.age} ---- 得到 18
[*]${pre.number} ---- 得到 1122
[*]${pre.name} ---- 得到 “李四”
[*]${pre.age} ---- 得到 30
[*]${pre.number} ---- 得到 3344
如许的设计,更加资助在用例设计时,提供数据准备的操纵。

“前后置动作”实例


(1)起首我们在前后置维护页面中新建一个动作,获取库存上限未卖光团单 。


https://i-blog.csdnimg.cn/blog_migrate/557401483af4ea6f2035e3bcd3043376.jpeg
这个设置也是可以支持在线调试的,在调试中,可以看到可以使用的参数化:


https://i-blog.csdnimg.cn/blog_migrate/7b0d86ec2785bbce9f4f4c56e5f20c80.jpeg

(2)在测试用例中的前置动作,添加获取库存上限未卖光团单 。


https://i-blog.csdnimg.cn/blog_migrate/ddc70bbf2b24425ec9060257ada68430.jpeg

如许就可以在整个测试用例中,使用${pre.ProductID},来更换掉原有的数据信息。

(3)最后哀求接口,返回了实行乐成 。


https://i-blog.csdnimg.cn/blog_migrate/af496f1531821bd2d0ea27d556550f18.jpeg
Q & A

 
Q:那如果同样是获取三个参数,使用3个“参数化的Select操纵”和使用1个“前置动作的Select操纵”又有什么差别呢?

A: 差别在于实行时间上。
好比,我们查询最新的有效团单的“单号”“下单人”和“手机号”三个字段。

使用3个“参数化的Select操纵”:可能当实行${单号}的时候得到的订单号是“10001”,但是当实行到${下单人}的时候,可能有谁又下了一单,可能取到的下单人变成了“10002”的“李四”而不是“10001”的“张三”了,最后可能“单号”“下单人”和“手机号”三个字段去的数据并非同一行的数据。

而使用“前置动作的Select操纵”:就可以避免上面的题目,由于所有字段的数据是一次性查询出来的,就不会出现错位的情况。
Q : 那“参数化的Select操纵”和“前置动作的Select操纵”如许差别的取值时机又有什么好用之处呢?
A : 由于“前置动作”肯定是接口哀求前实行,“参数化”肯定是用到的时候才实行如许的特性。

所以在查抄点中,如果要验证一个数据库字段在经过接口调用后发生了变更,那使用“前置动作”和“参数化”同时去查询这个字段,然后进行比力,不同等就说明发生了变革。

所以根据使用场景,选择符合的参数化方式,很紧张,选择对了,能大大提升测试用例的测试数据坚固性。
实行各部分

 
回到一开始的流程图,可以按照一类一类来看实行过程。

测试发起

https://i-blog.csdnimg.cn/blog_migrate/0ca88fd7e626dd8a9767cc687868a0b8.png

测试发起基本还是使用的Jenkins,稳定、成熟、简朴、公司工具组支持,也支持从Lego的Web页面进行实行操纵。

数据 / 情况准备

 

https://i-blog.csdnimg.cn/blog_migrate/2f453439d15b173894a7bef202db1267.jpeg

使用 @DataProvider 的方式,从DB数据库中读取测试用例,逐一实行进行测试。

测试实行

 

https://i-blog.csdnimg.cn/blog_migrate/fdb7df0da6d4b944d7fbb5841e8cf78d.jpeg

在正式实行测试用例之前,会先进行一波参数更换的动作,在调用接口之后,还会实行一次参数更换动作。


https://i-blog.csdnimg.cn/blog_migrate/36dd3208f4a91196abd26e0f92b25e75.jpeg
参数更换后会进行前置动作的实行,然后在调用接口之后还会实行测试后动作,最后实行后置动作。


https://i-blog.csdnimg.cn/blog_migrate/972f0672cefaa6e499d99fe7e3eb8d5a.jpeg

接口哀求这部分就没什么好说的了,就是通过接口哀求的参数,哀求对应的接口,拿到返回结果。
这里的话是为了方便通用,所以要求返回的结果都是使用的String范例。如许做最大的好处就是。好比说我现在有一种新的接口范例需要接入。那只需要写一个方法可以或许哀求到这个接口,并且拿到String范例的返回结果,就可以很快将新的接口范例接入Lego测试平台进行接口测试。
查抄点校验
 

https://i-blog.csdnimg.cn/blog_migrate/b1458136c6d0bc4940420df4c7a45ef2.jpeg

查抄点部分是一条自动化测试用例的精髓,一条自动化测试用例是否能真正的发挥它的测试功能,就是看QA对这条测试用例的查抄点编写是否做了良好设计。在Lego平台上,目前我拥有的查抄点有6种差别的范例。


[*]非常查抄点
[*]当返回结果为非常时,则会报错。
[*]但是有时候为了做非常测试,可以将这个查抄点关掉。
[*]不为空查抄点
[*]顾名思义,当出现""、"[]"、"{}"、null 如许的的结果,都会报错。也可以根据本身用例的实际情况关闭。
[*]包罗查抄点
[*]不包罗查抄点
[*]“包罗”和“不包罗”查抄点是将接口的返回结果作为一个String范例来看,查抄所有返回内容中是否“包罗”或“不包罗”指定的内容。
[*]数据库参数查抄点
[*]顾名思义,不做过多的解释了。
[*]JsonPath查抄点
[*]这是我在Lego上设计的最具有特色的一种查抄点范例。

JsonPath的基本写法是:{JsonPath语法}==value


[*]JsonPath的语法和XPath的语法差不多,都是根据路径的方法找值。这里也是主要是针对返回结果为JSON数据的结果,进行查抄。
[*]具体的JsonPath语法可以参考:GitHub - json-path/JsonPath: Java JsonPath implementation 。
[*]说完了"JsonPath的语法",现在说一下"JsonPath查抄点的语法"。"JsonPath查抄点的语法"是我本身想的,主要针对以下几种数据范例进行校验:
(1) 字符串范例结果检验


[*]即是:==
[*]不即是:!==
[*]包罗:=
[*]不包罗:!=
比方:


[*]{$..name}==aa:查抄返回的JSON中第2个JSON的name字段是否即是aa。
[*]{$..type}=='14':查抄返回的JSON中每一个JSON的name字段是否即是aa。
[*]{$..type}==14 && {$..orderId}==106712:一条用例中多个查抄用&&连接。
[*]{$..orderId}!==12:查抄返回的JSON中每个JSON的orderId字段是否不即是12。
[*]{$..type}=1:查抄返回的JSON中每个JSON的type字段是否包罗1。
[*]{$..type}!=chenyongda:查抄返回的JSON中第2个JSON的type字段是否不包罗chenyongda。
(2) 数值校验


[*]即是:=
[*]大于:>
[*]大于即是:>=
[*]小于:<
[*]小于即是:<=
比方:


[*]{$..value}<5:查抄返回的JSON中第1个JSON的value字段的列表是否小于3。
[*]{$..value}>4:查抄返回的JSON中第2个JSON的value字段的列表是否大于4。
(3) List结果检验


[*]list长度:.length
[*]list包罗:.contains(param)
[*]list成员:.get(index)
比方:


[*]{$..value}.length=3:查抄返回的JSON中每个JSON的value字段的列表是否即是3。
[*]{$..value}.length<5:查抄返回的JSON中第1个JSON的value字段的列表是否小于3。
[*]{$..value}.length>4:查抄返回的JSON中第2个JSON的value字段的列表是否大于4。
[*]{$..value}.contains('222'):查抄返回的JSON中每个JSON的value字段的列表是否包罗222字符串。
[*]{$..value}.contains(1426867200000):查抄返回的JSON中第1个JSON的value字段的列表是否包罗1426867200000。
[*]{$..value}.get(0)=='222':查抄返回的JSON中第1个JSON的value字段的列表中第1个内容是否即是222。
[*]{$..value}.get(2)='22':查抄返回的JSON中每个JSON的value字段的列表中第3个内容是否包罗22。
(4) 时间范例处理
时间戳转日期时间字符串:.todate
比方:


[*] {$..beginDate}.todate==2015-12-31 23:59:59:查抄返回的JSON中beginDate这个时间戳转换成日期后是否即是2015-12-31 23:59:59。

当JsonPath返回的结果是列表的形式时

 
https://i-blog.csdnimg.cn/blog_migrate/fb75c921048bb6d5b7767abf2319f478.jpeg

除此之外,另有非常多的花样玩法
JsonPath中的查抄支持“参数化”和“前后置动作”,所以会看到许多如:
{$.param}='${param}' && {$.param}==${pre.param}
如许的查抄点:
“参数化”和“前后置动作”也支持递归设置,这些都是为了可以或许让接口自动化测试用例写的更加机动好用。
测试结果


https://i-blog.csdnimg.cn/blog_migrate/5841e2133155931d525c416846648969.png
使用ReportNG可以打印出很漂亮的陈诉。
陈诉会自定义一些高亮等展示方式,只需要在ReportNG使用前加上下面的语句,就可以支持“输出逃逸”,可使用HTML标签自定义输出样式。
System.setProperty("org.uncommons.reportng.escape-output", "false");
后期优化

当使用Jenkins实行后,通过Jenkins API 、和Base包中的一些方法,定时获取测试结果,落数据库,提供天生统计图表用。

网站功能

站点开辟

既然打算做工具平台了,就得设计方方面面,可惜人手和时间上的不敷,只能我一人利用放工时间进行开辟。也算是担任了Lego平台的产物、后端开辟、前端开辟、运维和测试等各种角色。
Jenkins+TestNG+ReportNG+我本身开辟的基本接口自动化测试Base jar包,基本上没什么太大难度。但是站点这块,在来美团点评之前,还真没开辟过如许的工具平台,这个算是我的第一个带Web界面的工具。边Google边做,没想到不久还真的架起来了一个简易版本。
使用 Servlet + JSP 进行开辟,前端框架使用Bootstrap,前端数据使用JSTL,数据库使用MySQL,服务器使用的公司的一台Beta情况Docker假造机,域名是申请的公司内网域名,并开通北京上海两侧内网访问权限。
功能上基本都是要满足的,界面上,虽然做不到惊艳吧,但是绝对不能丑,功能满足,但是长得一副80年代的界面,我本身都会嫌弃去使用它,所以界面上我还是花了一些时间去调整和设计。纯熟以后就快多了。
团体构成

 

https://i-blog.csdnimg.cn/blog_migrate/5397112da2578feeb00de6469fdd5252.jpeg

目前Lego由五个差别的项目构成,分别是“测试脚本”、“Lego-web页面项目”、“用于实行接口测试的base包”、“小工具集合Lego-kit”和“lego-job”,通过上图可以看出各项目间的依赖关系。
细化各个项目的功能,就是下图:


https://i-blog.csdnimg.cn/blog_migrate/20c4b49b137b0c1e817490865579392b.jpeg

简朴来说,网站部分和脚本是分离的,中间的纽带是数据库。所以,没有网站,脚本实行一点题目也没有;同样的,网站的操纵,和脚本也没有关系。

日常维护

Step 1

 

https://i-blog.csdnimg.cn/blog_migrate/b44297f5d5b265350e89dc69b5bb3498.jpeg

每天上班来会收到如许的测试邮件,通过邮件能知道昨晚实行的情况。如果有报错,可以点击“具体陈诉链接”,跳转到在线陈诉。

Step 2

https://i-blog.csdnimg.cn/blog_migrate/3b90cdbdbd089df1154e6b846a3d16bd.jpeg

在现陈诉可以直接看到实行报错的信息,然后点击“LEGO维护传送门”,可以跳转到Lego站点上,进行用例维护。
Step 3

跳转到站点上以后,可以直接展示出该条测试用例的所有信息。定位,维护、保存,维护用例,可以点击“实行”查看维护后的实行结果,维护好后“保存”即可。
仅仅3步,1~2分钟即可完成对一条实行失败的用例进行定位、调试和维护动作。
用例编辑

 

https://i-blog.csdnimg.cn/blog_migrate/007133d8b2576ac0873323bec2d65731.jpeg

通过页面,我们就可以对一条测试用例进行:


[*] 新建
[*] 复制
[*] 编辑
[*] 删除
[*] 是否放入逐日构建中进行测试

在线调试


https://i-blog.csdnimg.cn/blog_migrate/9b840fc950327594a18d0ff7d8dc2bcf.jpeg
lego-web项目同样的使用base进行的用例实行,所以实行结果和打印都与脚本实行的同等的。

用例天生工具

 
为了更方便的写用例,针对部分接口开辟了一键批量天生用例的小工具。

实行结果分析

 
通过Jenkins接口、Base包中底子Test方法,将结果网络到数据库,便于各组对测试结果进行分析。
https://i-blog.csdnimg.cn/blog_migrate/d143bc8996faa0399dcb57493d488d14.jpeg

这是每天实行后乐成率走势图:


https://i-blog.csdnimg.cn/blog_migrate/2dd15760963eeed2f24584769f0c3964.jpeg

也可以按月进行统计,天生统计的图表,资助各个团队进行月报数据网络和统计。

失败原因追踪

 
有了能直观看到测试结果的图表,就会想要跟踪失败原因。


https://i-blog.csdnimg.cn/blog_migrate/30e43177cd0e7f1eb3915286c889bd40.jpeg
所以在乐成率数据的右边,会有如许的跟踪失败原因的入口,也可以很直观地看到哪一些失败的原因还没有被跟踪。点开后可以对失败原因进行记录。


https://i-blog.csdnimg.cn/blog_migrate/ddd33a8d688ebc51f67a82f3c174b212.jpeg

最后会有天生图表,可以很清楚地看到失败原因以及失败范例的占比。

代码覆盖率分析

 
结合Jacoco,我们可以对接口自动化的代码覆盖率进行分析。


https://i-blog.csdnimg.cn/blog_migrate/b7077ebc1b60a23eeff446cea0022b04.jpeg
在多台Slave机器上设置Jacoco还是比力复杂的,所以可以开辟覆盖率设置辅助工具来资助测试同砚,进步服从。


https://i-blog.csdnimg.cn/blog_migrate/dc777d4c5a4c3b8f528a7b77be37b128.jpeg

用例优化方向

 
除了上面的图表,还会给用例优化提供方向。


https://i-blog.csdnimg.cn/blog_migrate/674c55e9f9b5aafa121c5b481301d91e.jpeg

通过用例数目统计的图表,我们可以知道哪些服务用例还比力少,哪些情况的用例还比力少,可以比力有针对性的进行测试用例的补充。


https://i-blog.csdnimg.cn/blog_migrate/7ccf8fa6287561b5c783ed7a7f32c958.jpeg
通不对败原因的图表,我们可以改善本身用例中的“参数化”和“前后置动作”的使用,增加测试用例的坚固性。


https://i-blog.csdnimg.cn/blog_migrate/8e02796b022fb3af5cf8a123c06be799.jpeg

通过线上接口调用量排序的图表。我们可以有效的知道优先维护哪些服务的测试用例,通过表格中,我们可以看到,哪些服务已经覆盖了测试用例,哪些没有被覆盖, 给各组的QA制定用例开辟计划,提供参考。


https://i-blog.csdnimg.cn/blog_migrate/0ee11179f9aa7a9f4031aaa8d303cd9e.jpeg
同时在维护接口自动化测试的时候,都会看到用例评分的情况,来协助QA进步用例编写的质量。

网络反馈/学习

别的,还做了“需求白板”,用来网络使用者的需求和Bug。除此之外,Lego平台已经不但是一个接口测试的平台,还可以让想学习开辟的QA领任务,学习一些开辟技巧,进步本身的代码能力。


总结


[*]为了淘汰开辟成本,使用比力常见的Jenkins+TestNG的脚本形式。
[*]为了简化code操纵,使用DB进行测试用例存储,并抽象出用例摸版。
[*]为了减低新建用例成本,开辟“用例维护页面”和“一键天生”等工具。
[*]为了减低维护成本,加跳转链接,维护一条用例成本在几分钟内。
[*]为了增加用例坚固性,设计了“参数化”、“前后置动作”等机动的参数更换。
[*]为了易用和兼容,统一“返回结果”范例,统一“查抄点”的使用。
[*]为了接口自动化用例设计提供方向,结合Jacoco做代码覆盖率统计,并开辟相关设置工具
[*]为了便于分析数据,从DOM、CAT、Jenkins上爬各种数据,在页面上用图表展示。
[*]为了优化用例,提供“用例打分”、“线上调用量排行”等数据进行辅助。
最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走:
https://img-blog.csdnimg.cn/direct/fc91b07c277d4aedb48a4c2242009da1.png​

这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战堆栈,这个堆栈也陪伴上万个测试工程师们走过最艰巨的旅程,希望也能资助到你!
https://img-blog.csdnimg.cn/direct/15f11b9000784d40a96da05717b0d9b0.jpeg

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 接口自动化测试实践