欢迎访问 API Testing
API Testing 文档
记录
该项目正在
积极开发中,很多功能尚待补充,我们希望您
参与其中!
API Testing 一个基于 YAML 文件的开源接口测试工具,同时支持运行在本地、服务端。
在选择工具时,可以从很多方面进行考量、对比,以下几点是该工具的特色或者优点:
- 开源与否,atest 采用 MIT 开源协议,是最流行的宽松开源协议之一。有些工具也许有非常丰富的功能、漂亮的界面,但相比于开源项目,免费的工具不定什么时候就有可能变为收费的;而且,你的使用感受几乎很难直接反馈到产品中,只能被动接受。
- 质量、可靠性,作为一款用于测试场景的工具,atest 本身的单元测试覆盖率达 89%,单测代码与业务逻辑代码量平分秋色;另外,每次代码改动都需要通过代码扫描、单元测试等流水线。
- 身材小巧,整个工具大小为 18M,支持 Windows、Linux、macOS 平台。
- 只有简单的可执行二进制文件,不像部分工具会给你的操作系统安装莫名其妙的系统启动项目、系统服务等。
- 基于 YAML 文件,提交到 Git 仓库后,天生支持团队协作,无需注册额外账号。
- 同时提供简单、高级两种模式的返回值断言,还包括 JSON Schema 以及针对 Kubernetes 资源的校验判断。
- 支持性能测试。
- 直接在 VS Code 中直接触发执行单个或整个测试文件。
如何使用?
那么,这个工具长什么样子呢,下面是命令行 atest
的参数说明:
API testing tool
Usage:
atest [command]
Available Commands:
completion Generate the autocompletion script for the specified shell
help Help about any command
json Print the JSON schema of the test suites struct
run Run the test suite
sample Generate a sample test case YAML file
server Run as a server mode
service Install atest as a Linux service
Flags:
-h, --help help for atest
Use "atest [command] --help" for more information about a command.
本地模式
执行一个测试用例集文件:atest run -p sample/testsuite-gitlab.yaml
,其中的参数 -p
支持模糊匹配多个文件。
如果希望对测试用例集执行性能测试的话,可以增加响应的参数:
atest run -p sample/testsuite-gitlab.yaml --duration 1m --thread 3 --report m
其中的参数 --report
可以指定性能测试输出报告,目前支持 Markdown 以及控制台输出。效果如下所示:
服务端模式
除了本地执行外,atest
还提供了基于 gRPC
协议服务端,通过下面的命令即可启动:
对于 Linux 操作系统,用户还可以通过下面的命令安装后台服务:
atest service (install | start | stop | restart)
当然,如果你对容器、Kubernetes 比较熟悉的话,本项目也提供了对应的支持。
这种模式,对于想要集成的用户而言,可以通过调用 gRPC
来执行测试。也可以安装 VS Code 插件,在编码与接口测试之间无缝切换,您可以搜索 api-testing
找到该插件。
插件会识别所有第一行是 #!api-testing
的 YAML 文件,并提供快速的执行操作,请参考如下截图:
如图所示,会有四个快捷执行操作:
run suite
会执行整个文件run suite with env
会加载 env.yaml
文件并执行整个文件run
执行单个测试用例(包括所依赖的用例)debug
执行单个测试用例,并输出接口返回值
当你安装了 VS Code 插件后,会自动下载并安装 atest
及其服务。当然,你也可以配置不同的远端服务地址。
文件格式
atest
定义的 YAML 格式,基本遵循 HTTP 的语义,熟悉 HTTP 协议的同学即可快速上手。下面是一个范例,更多例子请参考这里:
#!api-testing
name: Kubernetes
api: https://192.168.123.121:6443
items:
- name: pods
request:
api: /api/v1/namespaces/kube-system/pods
header:
Authorization: Bearer token
expect:
verify:
- pod("kube-system", "kube-ovn-cni-55bz9").Exist()
- k8s("deployments", "kube-system", "coredns").Exist()
- k8s("deployments", "kube-system", "coredns").ExpectField(2, "spec", "replicas")
- k8s({"kind":"virtualmachines","group":"kubevirt.io"}, "vm-test", "vm-win10-dkkhl").Exist()
用户可以自定义请求的 Header、Payload 等,可以对响应体做全面的断言判断。
后续计划
如果您已经耐心阅读到这里的话,可以再顺便了解下这个项目后续的一些想法。
通过更多的实际场景来打磨、优化 atest
对接口测试的便利性、可扩展性,以不丢失易用性为前提增强功能。例如:
- 优化错误提示、反馈
- 提供与 CICD 集成的最佳实践
- 增加 gRPC 等协议的支持
- 增加测试记录信息的持久化
- VS Code 插件支持测试用例编写的提示、格式校验
- 提供插件机制,增加对数据库等数据源的格式校验
最后期待您的反馈 https://github.com/LinuxSuRen/api-testing/issues
准备好开始了吗?
1.1 - 快速入门
只需几个简单的步骤即可开始使用 API Testing。
本指南将帮助您通过几个简单的步骤开始使用 API Testing。
执行部分测试用例
下面的命令会执行名称中包含 sbom
的所有测试用例:
atest run -p test-suite.yaml --case-filter sbom
1.2 - gRPC TLS verification
If you want to enable gRPC TLS, you need to generate your certificates in the workspace, or you can use an absolute path
1. 生成私钥
openssl genrsa -out server.key 2048
2. 生成证书(会提示即可,不必填写)
openssl req -new -x509 -key server.key -out server.crt -days 36500
国家名字
Country Name (2 letter code) [AU]:CN
省份全名
State or Province Name (full name) [Some-State]:GuangDong
城市名
Locality Name (eg, city) []:Meizhou
组织名
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Xuexiangban
组织单位名
Organizational Unit Name (eg, section) []:go
服务器or用户的名字
Common Name (e.g. server FQDN or YOUR name) []:kuangstudy
邮箱地址
Email Address []:24736743@qq.com
3.生成csr
openssl req -new -key server.key -out server.csr
4.配置openssl.cfg
1) 查找openssl在服务器的安装目录并且找到openssl.cnf
2) 编辑[ CA_default ] ,打开 copy_extensions = copy #取消注释
3) 找到[ req ],打开 req_extensions = v3.req #取消注释
4) 找到[ v3_req ],添加字段 subjectAltName = @alt_names
5) 添加新的标签在最底部 [ alt_names ]和标签字段
DNS.1 = localhost
5.生成本地私钥test.key
openssl genpkey -algorithm RSA -out test.key
6.根据私钥生成csr请求文件test.csr
openssl req -new -nodes -key test.key -out test.csr -days 3650 \
-subj "/C=US/ST=Denial/L=Springfield/O=Dis/CN=www.example.com" \
-config ./openssl.cnf -extensions v3_req
7.生成ca证书 pem
openssl x509 -req -days 365 -in test.csr \
-out test.pem -CA server.crt -CAkey server.key \
-CAcreateserial -extfile ./openssl.cnf -extensions v3_req
1.3 - gRPC测试用例编写指南
本文档将介绍如何编写api-testing
的 gRPC API 的测试用例。
阅读本文档之前,您需要先安装并配置好api-testing
,具体操作可以参考安装章节。如果您已经完成了这些步骤,可以继续阅读本文档的后续部分。
创建测试项目
创建一个基于服务反射的 gRPC 测试用例仅需在 yaml 文件的spec
路径下加入以下内容:
spec:
rpc:
serverReflection: true
rpc
字段一共有五个子字段
字段名 | 类型 | 是否可选 |
---|
import | []string | √ |
protofile | string | √ |
protoset | string | √ |
serverReflection | bool | √ |
字段import
和protofile
protofile
是一个文件路径,指向api-testing
查找描述符的.proto
文件的位置。
import
字段与protc
编译器中的--import_path
参数类似,用于确定查找proto
文件的位置与解析依赖的目录。与protoc
一样,您不需要在此处指定某些proto
文件的位置(以google.protobuf
开头的Protocol Buffers Well-Known Types
),它们已经内置在了api-testing
中。
字段protoset
protoset
字段既可以是一个文件路径,也可以是http(s)://
开头的网络地址。
当您的proto
数量繁多或引用关系复杂,可以尝试使用protoc --descriptor_set_out=set.pb
生成proto
描述符集合。本质上它是一个使用了wire
编码的二进制文件,其中包括了所有需要的描述符。
字段serverReflection
若目标服务器支持服务反射,将此项设为true
则不再需要提供上述三个字段。
注:api-testing
对三种描述符来源的优先级顺序为
serverReflection
> protoset
> protofile
编写gRPC API测试
与编写HTTP
测试用例类型,您需要在根节点的api
字段定义服务器的地址。
默认情况下api-testing
使用不安全的方式连接到目标服务器。若您想配置TLS证书,请参考文档关于安全
编写gRPC API
测试的方式与编写HTTP API
测试的方式基本相同。
- name: FunctionsQuery
request:
api: /server.Runner/FunctionsQuery
body: |
{
"name": "hello"
}
expect:
body: |
{
"data": [
{
"key": "hello",
"value": "func() string"
}
]
}
api
字段的格式为/package.service/method
,支持 gRPC 一元调用、客户端流、服务端流和双向流调用。
与api
字段同级的body
字段是以JSON
格式表示的Protocol Buffers
消息,代表将要调用的api
的入参。特别的,当您需要调用客户端流或双向流 API 时,请使用JSON Array
格式编写字段body
,如:
body: |
[
{
"name": "hello"
},
{
"name": "title"
}
]
编写返回内容验证
编写gRPC API
返回内容验证的方式与HTTP API
基本相同。对与gRPC API
来说,一切返回值都被视为map
类型,被放入api testing
特定的返回结构中:
expect:
body: |
{
"data": [
{
"key": "hello",
"value": "func() string"
}
]
}
api-testing
为JSON
比对编写了一套对比库,请参考此处compare
请注意,对于服务端流和双向流模式,服务器发送多条消息的情况下,此处的data
字段内的填写的目标数组,需同时满足与待验证数组长度相,两个数组同一下标的内容完全相同。
gRPC API
的verify
功能与HTTP API
保持一致,此处不再赘述。
1.4 - Mock 服务
Mock 服务在前后端并行开发、系统对接、设备对接场景下能起到非常好的作用,可以极大地降低团队之间、系统之间的耦合度。
用户可以通过命令行终端(CLI)、Web UI 的方式来使用 Mock 服务。
命令行
atest mock --prefix / --port 9090 mock.yaml
Web
在 UI 上可以实现和命令行相同的功能,并可以通过页面编辑的方式修改、加载 Mock 服务配置。
Mock Docker Registry
您可以通过执行下面的命令 mock 一个容器仓库服务container registry:
atest mock --prefix / mock/image-registry.yaml
之后,您可以通过使用如下的命令使用 mock 功能。
docker pull localhost:6060/repo/name:tag
语法
从整体上来看,我们的写法和 HTTP 的名称基本保持一致,用户无需再了解额外的名词。此外,提供两种描述 Mock 服务的方式:
面对对象
#!api-testing-mock
# yaml-language-server: $schema=https://linuxsuren.github.io/api-testing/api-testing-mock-schema.json
objects:
- name: projects
initCount: 3
sample: |
{
"name": "atest",
"color": "{{ randEnum "blue" "read" "pink" }}"
}
上面 projects
的配置,会自动提供该对象的 CRUD(创建、查找、更新、删除)的 API,你可以通过 atest
或类似工具发出 HTTP 请求。例如:
curl http://localhost:6060/mock/projects
curl http://localhost:6060/mock/projects/atest
curl http://localhost:6060/mock/projects -X POST -d '{"name": "new"}'
curl http://localhost:6060/mock/projects -X PUT -d '{"name": "new", "remark": "this is a project"}'
curl http://localhost:6060/mock/projects/atest -X DELETE
initCount
是指按照 sample
给定的数据初始化多少个对象;如果没有指定的话,则默认值为 1.
自定义
#!api-testing-mock
# yaml-language-server: $schema=https://linuxsuren.github.io/api-testing/api-testing-mock-schema.json
items:
- name: prList
request:
path: /api/v1/repos/{repo}/prs
response:
header:
server: mock
Content-Type: application/json
body: |
{
"count": 1,
"items": [{
"title": "fix: there is a bug on page {{ randEnum "one", "two" }}",
"number": 123,
"message": "{{.Response.Header.server}}",
"author": "someone",
"status": "success"
}]
}
启动 Mock 服务后,我们就可以发起如下的请求:
curl http://localhost:6060/mock/api/v1/repos/atest/prs -v
另外,为了满足复杂的场景,还可以对 Response Body 做特定的解码,目前支持:base64
、url
:
#!api-testing-mock
# yaml-language-server: $schema=https://linuxsuren.github.io/api-testing/api-testing-mock-schema.json
items:
- name: base64
request:
path: /api/v1/base64
response:
body: aGVsbG8=
encoder: base64
上面 Body 的内容是经过 base64
编码的,这可以用于不希望直接明文显示,或者是图片的场景:
curl http://localhost:6060/mock/api/v1/base64
如果你的 Body 内容可以通过另外一个 HTTP 请求(GET)获得,那么你可以这么写:
#!api-testing-mock
# yaml-language-server: $schema=https://linuxsuren.github.io/api-testing/api-testing-mock-schema.json
items:
- name: baidu
request:
path: /api/v1/baidu
response:
body: https://baidu.com
encoder: url
在实际情况中,往往是向已有系统或平台添加新的 API,此时要 Mock 所有已经存在的 API 就既没必要也需要很多工作量。因此,我们提供了一种简单的方式,即可以增加代理的方式把已有的 API 请求转发到实际的地址,只对新增的 API 进行 Mock 处理。如下所示:
#!api-testing-mock
# yaml-language-server: $schema=https://linuxsuren.github.io/api-testing/api-testing-mock-schema.json
proxies:
- path: /api/v1/{part}
target: http://atest.localhost:8080
当我们发起如下的请求时,实际请求的地址为 http://atest.localhost:8080/api/v1/projects
curl http://localhost:6060/mock/api/v1/projects
更多 URL 中通配符的用法,请参考 https://github.com/gorilla/mux
1.5 - 测试用例验证
atest
采用 https://expr.medv.io 对 HTTP 请求响应的验证,比如:返回的数据列表长度验证、具体值的验证等等。下面给出一些例子:
需要注意的是,data
指的是 HTTP Response Body(响应体)的 JSON 对象。
数组长度判断
- name: projectKinds
request:
api: /api/resources/projectKinds
expect:
verify:
- len(data.data) == 6
数组值检查
- name: popularHeaders
request:
api: /popularHeaders
expect:
verify:
- any(data.data, {.key == "Content-Type"})
更多用法.
字符串判断
- name: metrics
request:
api: |
{{.param.server}}/metrics
expect:
verify:
- indexOf(data, "atest_execution_count") != -1
更多用法.
1.6 - 插件
atest
会把非核心、可扩展的功能以插件(extension)的形式实现。下面介绍有哪些插件,以及如何使用:
在不同的系统中,插件有着不同的表述,例如:extension、plugin 等。
类型 | 名称 | 描述 |
---|
存储 | orm | 保存数据到关系型数据库中,例如:MySQL |
存储 | s3 | 保存数据到对象存储中 |
存储 | etcd | 保存数据到 Etcd 数据库中 |
存储 | git | 保存数据到 Git 仓库中 |
存储 | mongodb | 保存数据到 MongDB 中 |
atest
也是唯一支持如此丰富的存储的接口开发、测试的开源工具。
下载插件
我们建议通过如下的命令来下载插件:
上面的命令,会识别当前的操作系统,自动下载最新版本的插件。当然,用户可以通过自行编译、手动下载的方式获取插件二进制文件。
atest
可以从任意支持 OCI 的镜像仓库中(命令参数说明中给出了支持的镜像服务地址)下载插件,也可以指定下载超时时间:
atest extension orm --registry ghcr.io --timeout 2ms
1.7 - 代码生成
atest
支持把测试用例生成多种开发语言的代码:
该功能需要在 Web UI 上使用。
1.8 - 关于安全
通常在不使用 TLS 证书认证时,gRPC 客户端与服务端之间进行的是明文通信,信息易被第三方监听或篡改。所以大多数情况下均推荐使用 SSL/TLS 保护 gRPC 服务。目前atest
已实现服务端 TLS,双向 TLS(mTLS) 需等待后续实现。
默认情况下atest
不使用任何安全策略,等价于spec.secure.insecure = true
。启用 TLS 仅需 yaml 中添加以下内容:
spec:
secure:
cert: server.pem
serverName: atest
字段说明
secure
共有以下五个字段:
字段名 | 类型 | 是否可选 |
---|
cert | string | x |
ca | string | √ |
key | string | √ |
serverName | string | x |
insecure | bool | √ |
cert
为客户端需要配置的证书的文件路径,格式为PEM
。
serverName
为 TLS 所需的服务名,通常为签发证书时使用的 x509 SAN。
ca
为 CA 证书的路径,key
为与cert
对应的私钥,这两项填写后代表启用 mTLS。(mTLS 尚未实现)
当insecure
为false
时,cert
和serverName
为必填项。
2 - 安装
本节包含关于安装 API Testing 的内容。
2.2 - 通过 Helm 安装的方式使用 API Testing
You could install api-testing
via Helm chart:
helm install atest oci://docker.io/linuxsuren/api-testing \
--version v0.0.2-helm \
--set service.type=NodePort
or upgrade it:
helm upgrade atest oci://docker.io/surenpi/api-testing \
--version v0.0.2-helm \
--set image.tag=master \
--set replicaCount=3
SkyWalking
helm install atest oci://docker.io/linuxsuren/api-testing \
--version v0.0.2-helm \
--set image.tag=master \
--set service.type=NodePort \
--set service.nodePort=30154 \
--set skywalking.endpoint.http=http://skywalking-skywalking-helm-oap.skywalking.svc:12800 \
--set skywalking.endpoint.grpc=skywalking-skywalking-helm-oap.skywalking.svc:11800
3 - API
本节内容包含 API Testing 的 API。