🎉 🎂 🍰 TesterHome 创立 6 周年纪念日 🍰 🎂 🎉

接口测试 接口测试过程中如何快速进行 diff 测试?Node.js、Python、Java 三种语言进行接口对比测试

iqianxing · 2018年08月12日 · 最后由 niezp 回复于 2018年09月19日 · 1059 次阅读

背景

接口测试过程中,当接口版本发生变更时,如何快速进行 diff 测试?本文使用Node.js、Python、Java三种语言来讲解如何快速的进行接口diff测试.

原理

通过对接口返回结果添加断言来判断不同版本接口返回值是否相同,结合测试框架动态生成测试用例(测试数据参数化)来批量对比接口返回值。

方法

  1. Node.js
    >> 断言使用chai的assert.deepEqual方法.

测试过程中常用命令:

# 创建node.js项目
npm init
# 安装依赖包
npm install request mocha chai mochawesome --save
# 执行测试用例,并指定报告为mochawesome,报告默认存放到当前项目 mochawesome-report/ 目录中
mocha test\batchdiff.test.js --reporter mochawesome
  1. Python
    >> 断言使用unittest的assertDictEqual方法.

测试过程中常用命令:

# 安装依赖包
pip install requests pytest pytest-html
# 执行测试用例,并生成html报告,报告指定存放到当前项目 static/ 目录中
pytest test\test_batchdiff.py --html=static\jsondiff.html
  1. Java
    >> 断言使用junit的Assert.assertEquals方法.

本地测试项目为maven项目,maven依赖包如下:

<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.14.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.49</version>
</dependency>
<dependency>
<groupId>com.github.kevinsawicki</groupId>
<artifactId>http-request</artifactId>
<version>6.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-report-plugin</artifactId>
<version>2.22.0</version>
</dependency>

maven命令:

# 运行测试用例
mvn test
# 运行测试用例,生成html报告,报告默认存放到项目的 target/site 目录中
mvn surefire-report:report

Node.js diff测试示例

  1. 测试用例运行效果

  2. html报告

  3. 源代码

var assert = require('chai').assert;
var request = require('request');

describe("Node.js版本批量接口diff", function () {
this.timeout(0);
[
// diff apis
{
"oldapi": "https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v1/demo",
"newapi": "https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v2/demo"
},
{
"oldapi": "https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v1/hello",
"newapi": "https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v2/hello"
},
{
"oldapi": "https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v1/user",
"newapi": "https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v2/user"
},
{
"oldapi": "https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v1/1/list",
"newapi": "https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v2/1/list"
},
{
"oldapi": "https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v1/2/list",
"newapi": "https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v2/2/list"
},
{
"oldapi": "https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v1/3/list",
"newapi": "https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v2/3/list"
},
].forEach(function (kv) {
it(kv.newapi + " vs " + kv.oldapi, function (done) {
request.get(kv.newapi, {
json: true
},
function (err, res, body) {
request.get(kv.oldapi, {
json: true
},
function (oldapiError, oldapiRes, oldapiBody) {
assert.deepEqual(body, oldapiBody);
done();
}
);
}
);
});
});
});

Python diff测试示例

  1. 测试用例运行效果

  2. html报告

  3. 源代码

# -*- coding:utf-8 -*-
import unittest
import requests
from parameterized import parameterized, param
diffApis = [
# diff apis
{
"oldapi":"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v1/demo",
"newapi":"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v2/demo"
},
{
"oldapi":"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v1/hello",
"newapi":"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v2/hello"
},
{
"oldapi":"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v1/user",
"newapi":"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v2/user"
},
{
"oldapi":"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v1/1/list",
"newapi":"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v2/1/list"
},
{
"oldapi":"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v1/2/list",
"newapi":"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v2/2/list"
},
{
"oldapi":"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v1/3/list",
"newapi":"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v2/3/list"
},
]


class TestParameterized(unittest.TestCase):
@parameterized.expand(
[param("diff test",kv) for kv in diffApis])
def test_batchdiff(self, _, kv):
self.maxDiff = None
oldRes = requests.get(kv["oldapi"])
newRes = requests.get(kv["newapi"])
self.assertDictEqual(oldRes.json(), newRes.json())


if __name__ == '__main__':
unittest.main(verbosity=2)

Java diff测试示例

  1. 测试用例运行效果

  1. html报告

  2. 源代码

package com.test.apitest;

import com.alibaba.fastjson.JSON;
import org.junit.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import com.github.kevinsawicki.http.HttpRequest;

public class BatchDiffTest {
@DataProvider
public Object[][] data() {
Object[][] diffApis = new Object[][]{
{
"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v1/demo",
"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v2/demo"
},
{
"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v1/hello",
"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v2/hello"
},
{
"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v1/user",
"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v2/user"
},
{
"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v1/1/list",
"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v2/1/list"
},
{
"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v1/2/list",
"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v2/2/list"
},
{
"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v1/3/list",
"https://easy-mock.com/mock/5b6b06f9a40bfb27425bbb6a/jsondiff/v2/3/list"
},
};
return diffApis;
}

@Test(dataProvider = "data")
public void test_apiDiff(String oldApiUrl, String newApiUrl) {
String oldJsonString = HttpRequest.get(oldApiUrl)
.accept("application/json")
.body();
String newJsonString = HttpRequest.get(newApiUrl)
.accept("application/json")
.body();
Object oldJsonVo = JSON.parseObject(oldJsonString);
Object newJsonVo = JSON.parseObject(newJsonString);
Assert.assertEquals(oldJsonVo, newJsonVo);
}
}

Node.js、Python、Java对比效果分析

  1. 命令行日志显示的对比结果

    当接口返回结果不一致时:

    1) mocha+chai断言在日志中显示效果最好,日志输出json字段级别不一致的地方;

    2) python+unittest断言在日志中显示的是python dict对象,不太友好;

    3) java+junit仅在日志中显示两个对比的对象不一致,需要借助IDE对比返回值字段级别不一致的地方;

  2. html报告

    与命令行输出日志相似,当接口返回值不一致时:

    1) Node.js体系的mochawesome报告最好看,最直观,可以看到json字段级别不一致的地方;

    2) Python体系的pytest-html报告diff测试结果不友好,不能明显看出json字段级别不一致的地方;
    3) Java体系的Surefire Report不能看出json不一致的地方;

  3. 中文支持

    Node.js、Java语言输出日志、html报告中中文字符正常显示为中文字符,python输出日志、html报告中中文字符显示为中文字符对应的Unicode编码

参考资料

各种测试框架都有官方文档,从官方文档中可以获取到参数化的知识,下述参考资料仅供参考.

  1. mocha
  2. 测试框架 Mocha 实例教程
  3. pytest
  4. pytest官方帮助文档参数化
  5. pytest文档9-参数化parametrize
  6. Junit 4
  7. testNg参数化
  8. testng参数化方法:Parameters和DataProvider

申明

本文发布于个人微信公众号 发现Bug,欢迎关注。

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 1 条回复 时间 点赞

👍 ,谢谢分享。

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