开源测试工具 YApi 服务端测试新增 globalCookie ,兼容自动化触发服务端测试功能

少年 · February 25, 2020 · Last by 少年 replied at March 16, 2020 · 4358 hits
本帖已被设为精华帖!

如果有用过 YApi,还试过测试功能,没准会提过一个类似的 issues: 为什么本地运行接口测试正常,但是服务端测试却不正常呢?

这个主要是因为本地是用浏览器来跑的,同在一个集合的接口用例,前面 set-cookie 以后,后面的 cookie 会直接从浏览器里面读,也就保持了前后一致性。但是,你用服务端来跑的时候,就算是同一个集合的测试用例,它的 cookie 值并没有完全保持前后一致,这也就导致了为什么本地跑可以,但是服务端测试不行。

但是很多时候我们做 ci 工具的时候,也就是我们想把接口测试做成,提交代码以后自动触发运行并失败告警的自动化流程里面去的时候,往往需要的都是它的服务端测试的功能,所以服务端测试的 cookie 前后一致性的功能,也就很有必要了。

然鹅,这个 globalCookie 并没有随着 YApi 的更新也一起加上,所以,又到了自己动手丰衣足食的环节。

原项目太大了没必要全部拉下来,这里我直接 fork 了一个 yapi 的 docker 部署,然后我们只需要修改一些代码,添加到 Dockfile 里面去,打出来的镜像也就具备了 globalCookie 的功能。

项目代码:yapi-globalCookie 【又到了欢迎来 star 的时刻!】

COPY open.js /yapi/vendors/server/controllers/

Dockerfile 里面加了这句话,看了一下 YApi 的代码,涉及到接口测试的运行方式主要跟这个 /yapi/vendors/server/controllers/open.js 的文件有关系,我们可以在执行服务端测试的时候,将 cookie 设置成全局变量,每当出现 set-cookie 的时候就保存下来,用于后面的请求,也就具备了 globalCookie 的功能。

var _globalCookies = false;

async webHandleTest(interfaceData) {
let requestParams = {};
let options;
options = handleParams(interfaceData, this.handleValue, requestParams);

if (_globalCookies) {
options.headers['Cookie'] = _globalCookies;
}

let result = {
id: interfaceData.id,
name: interfaceData.casename,
path: interfaceData.path,
code: 400,
validRes: []
};

try {
options.taskId = this.getUid();
let data = await crossRequest(options, interfaceData.pre_script, interfaceData.after_script,createContex(
this.getUid(),
interfaceData.project_id,
interfaceData.interface_id
));
let res = data.res;

if (res.header['set-cookie']) {
let arrCookie = res.header['set-cookie'].toString().split(',');
var tmp = '';
for (let i = 0;i < arrCookie.length; i++) {
let idx = arrCookie[i].indexOf(';');
if (tmp.length > 0) {
tmp += '; ';
}
tmp += arrCookie[i].substring(0, idx);
}
_globalCookies = tmp;
}

result = Object.assign(result, {
status: res.status,
statusText: res.statusText,
url: data.req.url,
method: data.req.method,
data: data.req.data,
headers: data.req.headers,
res_header: res.header,
res_body: res.body
});
if (options.data && typeof options.data === 'object') {
requestParams = Object.assign(requestParams, options.data);
}

let validRes = [];

let responseData = Object.assign(
{},
{
status: res.status,
body: res.body,
header: res.header,
statusText: res.statusText
}
);

await this.handleScriptTest(interfaceData, responseData, validRes, requestParams);
result.params = requestParams;
if (validRes.length === 0) {
result.code = 0;
result.validRes = [{ message: '验证通过' }];
} else if (validRes.length > 0) {
result.code = 1;
result.validRes = validRes;
}
} catch (data) {
result = Object.assign(options, result, {
res_header: data.header,
res_body: data.body || data.message,
status: null,
statusText: data.message,
code: 400
});
}

return result;
}

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

遭遇了楼主相同的情况,谢谢楼主分享

陈恒捷 将本帖设为了精华贴 26 Feb 13:14
Han 回复

不客气hhh

我记得我之前还看到有一个可以设置全局token的插件。也不错的

dive 回复

欢迎分享~

少年 回复

想了想,设置全局的Cookie,可能有过期的问题,最真实的场景应该是:
Request 1:成功登录,拿到浏览器的cookie
Request 2:使用1中的cookie,持久访问。

如何把1中的cookie 设置成全局,楼主有好的办法吗?

Han 回复

跑的时候是跑整个测试集合,你在涉及到要登录的测试集合里面,把登录接口用例放在最开始就行,一跑就会自动登录来刷新cookie了。

少年 回复

https://github.com/shouldnotappearcalm/yapi-plugin-interface-oauth2-token
这个插件,解决了oauth2.0的鉴权问题,我觉得挺好的,推荐一下。

您好,我在https://docker-yapi.herokuapp.com/ 环境上面试了下,没有获取到cookie,是什么原因呢

少年 #10 · March 16, 2020 作者
味味 回复

这个域名不是我的,我只是改写了里面的 dockerfile,把插件放到了进去,方便你直接用这个 docker-compose 来安装和部署服务。要 pull 下来自己本地部署。

少年 YApi - DroneCI 接口自动化测试 中提及了此贴 20 Mar 18:06
需要 Sign In 后方可回复, 如果你还没有账号请点击这里 Sign Up