序
关于自测的重要性,此处省下1万字,简而言之, 如果不想让 QA 小姐姐把 BUG 甩你一脸,那你就得学会高效自测。
另外呢,有一些水平很差的程序猿,你不让他有一个自测的环境,可以自己跑着,不停的 curl 着,不停的 postman着,他就不会编码---比如本拐。
但是无论 postman,还是curl,总是要费时间的,你要不停的去回车,去试————对于程序(懒)猿(人)来讲,任何重复的劳动都是不能忍受的.
在这里,向大家极力推荐 node.js ,因为两个重要的 npm 库,一个是 node-watch ,可以监测文件的变成,在文件有改变时发生相应的事件。 另一个呢,则是 request ,一个优秀的 http client 库,借助这两点,我们可以在写一个简单的 js脚本,当源码文件发生改变时,自动去调用相应的接口。
思路及源码
知道了几个库,还远远不够,我们想做的时,写一个简单的框架,可以将我们的case配置进去。 同时可以进行一些参数的传递。 那么,一个配置,我希望他是这样的:
module.exports = {
type: 'lua',
dir: '/data/guaiye/user/',
host: 'http://localhost:8080',
cases: [
{
name : '请求登录验证码',
index: 1,
key : 'req',
uri: '/v1/auth/require-checkcode',
method: 'post',
data: {
mobile : '13800000001',
source: 'testApp'
},
},
{
name : '验证码登录',
index: 2 ,
key : 'check',
uri: '/v1/auth/login-checkcode',
method: 'post',
data: {
mobile : '13800000001',
code: '#req.res.data',
source: 'testApp'
}
},
{
name : '验证token',
index: 3,
key: 'info',
uri: '/v1/auth/info-by-token',
method: 'post',
method: 'post',
data: {
source: 'testApp',
token : '#check.res.data.token',
}
},
{
uri: '/v1/auth/logout',
name : '登出',
method: 'post',
data: {
token : '#check.res.data.token',
}
}
]
}
那么,在希望可以按如此进行配置case的基础上,我们去写一个可以遍历这个case的脚本。 首先,简单封装一下request库:
const request = require('request')
let execReq = async(opt)=>{
return new Promise((resolve,reject)=>{
request(opt,(err,res,body)=>{
if (err){
reject(err)
}else{
resolve(body)
}
})
})
}
let getReq = async(url) =>{
return await execReq({
url:url,
method:'GET',
json:true,
headers:{
'content-type':'application/json'
}
})
}
let postReq = async (url,data)=>{
return await execReq({
url:url,
method:'POST',
json:true,
body:data,
headers:{
'content-type':'application/json'
}
})
}
module.exports = {
exec:execReq,
get:getReq,
post:postReq
}
在这个思路的基础上,写一个简单的app.js
const cfg = require ( './config') //我们的配置文件
const watch = require('node-watch') // watch神器
const _ = require('lodash')
const http = require('./tools/http') // 上面封装的http
const log = (msg) =>{
console.log(new Date().toLocaleTimeString()+':'+msg)
}
const run_test = async()=>{
log(`the .${cfg.type} file in ${cfg.dir} changed,run the test`)
log(`the host is ${cfg.host}`)
let all = {}
for(let i = 0 ; i < cfg.cases.length; i ++)
{
let testCase = cfg.cases[i]
let url = cfg.host + '/'+testCase.uri
let method =testCase.method || 'get'
let postdata = _.cloneDeep(testCase.data || {})
all[testCase.key]={}
try{
for( let p in postdata){
let str = postdata[p]
if (str.indexOf('#') == 0 ) {
let key = str.substr(1)
postdata[p] = _.get(all,key)
}
}
let data = await http[method](url,postdata)
all[testCase.key].req = postdata
all[testCase.key].res = data
console.log({name:testCase.name,url,method,req:postdata,res:data})
}catch(e){
console.log(e)
}
}
}
watch(cfg.dir , {recursive: true,filter : new RegExp(`\.${cfg.type}$`)},run_test)
run_test()
在这里用了一个小把戏,就是req的定义如果以 '#' 开始,则从测试的上下文中进行取值。
也是用了现成的lodash库。
OK,现在为止,大功告成,每当接一个新需求,我会配置一份测试文件,然后让自己的测试脚本跑进来,时刻看着代码的调试情况。
这个东西虽然简单,其实可以扩展的无限灵活,全当是抛砖引玉,给大家一个思路了。
关于老拐瘦
散养程序猿,野生架构狮
二流搬砖工,三流摄影师
假正经真逗比,装文艺实二逼
所以,这么一个公众号里,会有代码,有段子,有美图,有鸡汤,反正,乱七八遭的,没准碰上哪个刚好就烦到您了呢
啥也不说,扫码关注吧