资讯专栏INFORMATION COLUMN

Aest 功能强大的NodeJS Restful 接口测试工具

sihai / 819人阅读

1. Aest

项目地址:https://github.com/wangduandu...

功能强大的REST接口测试工具, Power By Jest, axios, superstruct, mustache, lodash

2. 特点

非常简单: 大部分工作量在于写配置文件

请求模板: 可以在配置文件中加入运行时变量,如/users/{{id}}

响应体结构验证: 支持对响应体的字段类型进行严格校验,多字段、少字段、字段类型不符合预期都会报错

非常详细的报错提示: 参见截图

3. 安装
yarn add aester
npm i aester -S
4. 使用 4.1. 编写测试用例
// filename 必须以 test.js结尾

const Ae = require("aester")
var testData = require("./test-data.js")

// 初始化配置文件
testData = Ae.init(testData)

describe("4XX 5XX error response test", () => {
  test("Get User Info without sessionId", async () => {
    await expect(Ae.send(testData.getOneUser, {id: "1"})).rejects.toHaveProperty("status", 403)
  })

  test("loginByEmail Fail Test", async () => {
    await expect(Ae.send(testData.loginByEmail, {password: "111"})).rejects.toHaveProperty("status", 401)
  })
})

describe("2XX success response test", () => {
  test("loginByEmail Success Test", async () => {
    // 对于符合预期的正向测试,不需要使用expect, 如果响应状态码是400以上,或者响应体结构不符合预期,
    // 该测试用例会自动失败
    const data = await Ae.send(testData.loginByEmail, {password: "000"})
    Ae.share("sessionId", data.sessionId)
  })

  test("Get User Info", async () => {
    await Ae.send(testData.getOneUser, {id: "1"})
  })
})

describe("2XX success response with error body struct", () => {
  test("StructError test", async () => {
    var data = _.cloneDeep(testData.getOneUser)
    data.resBodyStruct.test = "number" // set a error struct

    await expect(Ae.send(data, {id: "1"})).rejects.toHaveProperty("type", "StructError")
  })
})
4.2. 接口配置文件
// test-data.js
module.exports = {
  $baseUrl: "http://localhost:3000",
  loginByEmail: {
    desc: "login",
    req: {
      method: "post",
      path: "/login",
      headers: { "content-type": "application/x-www-form-urlencoded" },
      data: "email=wdd@cc.tt&password={{password}}",
      params: {
        _test: 1
      }
    },
    resBodyStruct: {
      sessionId: "string"
    }
  },
  getOneUser: {
    desc: "get user info",
    req: {
      path: "/users/{{id}}",
      headers: {
        "sessionId": "{{sessionId}}" // 如果share中有sessionId, 在请求发送时,会自动将{{sessionId}}替换成真正的值,否则会被替换成空字符串
      }
    },
    resBodyStruct: {
      id: "string",
      email: "string",
      password: "string",
      userName: "string",
      likes: "array",
      isAdmin: "boolean"
    }
  },
  createOneUser: {
    desc: "create user",
    req: {
      method: "post",
      path: "/users",
      headers: {
        "sessionId": "{{sessionId}}"
      }
    }
  },
  updateOneUser: {
    desc: "update user",
    req: {
      method: "put",
      path: "/users/{{id}}",
      headers: {
        "sessionId": "{{sessionId}}"
      }
    }
  },
  deleteOneUser: {
    desc: "获取用户信息接口",
    req: {
      method: "delete",
      path: "/users/{{id}}",
      headers: {
        "sessionId": "{{sessionId}}"
      }
    }
  }
}
4.3. 运行测试用例

在package.json加入

  "scripts": {
    "test": "jest"
  }

然后运行npm test

4.4. 生成html测试报告
yarn add jest-html-reporter -D
4.4.1. 方法1

然后在package.json中加入如下字段

"test:report": "jest --reporters="jest-html-reporter""

然后运行

npm run test:report
4.4.2. 方法2

创建jest.config.js在项目根目录

module.exports = {
  verbose: true,
  testEnvironment: "node",
  reporters: [
    "default",
    ["./node_modules/jest-html-reporter", {
      pageTitle: `operation api test ${process.env.testConfigEnv}`,
      includeFailureMsg: true // 详细错误提示
    }]
  ]
}

然后运行

npm test
5. 参看测试结果 5.1. 正常测试结果
 PASS  test/unit.test.js
 PASS  test/index.test.js

Test Suites: 2 passed, 2 total
Tests:       8 passed, 8 total
Snapshots:   0 total
Time:        1.864s
5.2. 接口报错测试结果
          "origin": "null",
          "readyState": 4,
          "requestBuffer": null,
          "requestCache": null,
          "responseBuffer": [Buffer],
          "responseCache": null,
          "responseHeaders": [Object],
          "responseTextCache": "Forbidden",
          "responseURL": "http://localhost:3000/users/1",
          "responseXMLCache": null,
          "send": true,
          "status": 403,
          "statusText": "Forbidden",
          "timeoutFn": null,
          "timeoutId": 0,
          "timeoutStart": 0,
          "totalReceivedChunkSize": 9,
          "uploadComplete": true,
          "uploadListener": false,
        },
      },
      "status": 403,
      "statusText": "Forbidden",
    }

      18 | })
      19 |
    > 20 | test("Get User Info", async () => {
         | ^
      21 |   await Ae.send(testData.getOneUser, {id: "1"})
      22 | })
      23 |

      at Env.it (node_modules/jest-jasmine2/build/jasmine_async.js:102:24)
      at Object. (test/index.test.js:20:1)
5.3. 接口返回响应体不符合预期测试结果

例如,resBodyStruct配置sessionId为number格式,但是返回的格式是字符串,将会如下格式的报错

    TypeError: Expected a value of type `number` for `sessionId` but received `"123456"`.

      60 |       if (conf.resBodyStruct) {
      61 |         let Scheme = struct(conf.resBodyStruct)
    > 62 |         let result = Scheme.validate(res.data)
         |                             ^
      63 |         if (result.length === 1) {
      64 |           reject(result[0])
      65 |         }

      at Function.Struct.validate.value [as validate] (node_modules/superstruct/src/superstruct.js:78:17)
      at src/index.js:62:29
6. Api 6.1. Aest.init(apiConfs)

初始化配置文件

const Ae = require("aester")

...
var conf = Ae.init(apiConfs)
6.2. Aest.send(apiConf, options)

发送请求。

options会与share合并,然后将对应变量渲染到请求模板中。

const Ae = require("aester")

...
Ae.send(testData.getOneUser, {id: "1"}
6.3. Aest.share(key, value)

设置共享变量

const Ae = require("aester")

...
var conf = Ae.share("token", "123123")
6.4. Aest.getShare()

获取所有共享变量

const Ae = require("aester")

...
var conf = Ae.getShare() // {token: "123123"}
7. 配置文件说明
key 必须? 说明
$baseUrl 请求baseUrl

desc | 否 | 接口说明
req | 是 | 请求对象
req.method | 否 | 请求方法,默认get
req.path | 是 | 请求路径
req.headers | 是 | 默认为空对象,默认设置"content-type": "application/json; charset=UTF-8"
resBodyStruct | 否 | 响应体格式校验对象

resBodyStruct字段说明

{
  key: keyType
}

字段类型支持如下

any: 任意

number: 数字

array: 数组

string: 字符串

boolean: 布尔值

null: null

undefined: undefined

object: 对象类型

在字段类型后加上?表示字段是否可选

如:

{
  sessionId: "string?" //sessionId是字符串,但是可以没有这个字段
}

更多字段类型验证参考:https://github.com/ianstormta...

8. 测试Aester
npm test

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/96817.html

相关文章

  • jest jenkins搭建自动化CI测试教程

    摘要:想做自动化接口测试时,我也按照打包镜像的套路走,感觉走到死胡同。终于自己走通了一遍。点击进去可以发现测试报告。注意测试报告并不是生成的。我的项目目录如下最后如果你也需要自动化接口测试工具可以试试我最近写的一个工具。 关于jest和jenkins集成,我走了一些弯路。之前一直用jenkins打包nodejs镜像。想做nodejs自动化接口测试时,我也按照打包镜像的套路走,感觉走到死胡同。...

    ztyzz 评论0 收藏0
  • 前后端分离模式

    摘要:采用前后端分离模式可以减后台负担,加快研发效率,当然,前提是前端能做好的话。还是基础不够导致的后端是否风格很多公司采用了前后端分离模式后,后端仍然采用以往的传统风格,这是不合理的,风格的应该是前后端分离的最佳实践。 showImg(https://segmentfault.com/img/bVFC8f?w=690&h=360);早期的web开发是不分前端后端的。互联网进入Web2.0时...

    fobnn 评论0 收藏0
  • 前后端分离模式

    摘要:采用前后端分离模式可以减后台负担,加快研发效率,当然,前提是前端能做好的话。还是基础不够导致的后端是否风格很多公司采用了前后端分离模式后,后端仍然采用以往的传统风格,这是不合理的,风格的应该是前后端分离的最佳实践。 showImg(https://segmentfault.com/img/bVFC8f?w=690&h=360);早期的web开发是不分前端后端的。互联网进入Web2.0时...

    DesGemini 评论0 收藏0
  • 前后端分离模式

    摘要:采用前后端分离模式可以减后台负担,加快研发效率,当然,前提是前端能做好的话。还是基础不够导致的后端是否风格很多公司采用了前后端分离模式后,后端仍然采用以往的传统风格,这是不合理的,风格的应该是前后端分离的最佳实践。 showImg(https://segmentfault.com/img/bVFC8f?w=690&h=360);早期的web开发是不分前端后端的。互联网进入Web2.0时...

    whlong 评论0 收藏0
  • 4.3 路由设计/RESTful API-博客后端Api-NodeJs+Express+Mysql实

    摘要:路由设计路由设计以用户注册为例介绍如何闭环用户注册开发注意点使用邮箱注册验证邮箱是否注册目前真实开发业务大部分都是手机号注册,这块由于没有购买短信服务首先,在文件夹下新建上图中对应真实业务逻辑现附上业务实现代码加密国际化工具类用户服务 路由设计 路由设计 以用户注册为例介绍如何闭环用户注册开发注意点:(1)使用邮箱注册(2)验证邮箱是否注册 【目前真实开发业务大部分都是手机号注册,这块...

    1fe1se 评论0 收藏0

发表评论

0条评论

sihai

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<