基于Groovy+HttpRestful的超轻量级的接口测试用例配置的设计方案及DEMO实现
目标###
设计一个轻量级测试用例框架,接口测试编写者只需要编写测试用例相关的内容(入参及结果校验),不需要理会系统的实现,不需要写跟测试校验无关的内容。
思路###
测试用例分析####
一个用例由以下部分组成:
(1) 测试用例名称 ; (2) 接口名及URL/Path; (3) 接口入参; (4) 接口返回结果校验。
测试框架需要读取用例配置信息,根据指定接口及入参调用服务,并根据指定校验函数来对接口返回结果做检验,判断测试用例是否执行成功。
设计考量####
为了灵活调用不同接口,针对以上的配置,(2) 采用 http restful 的方式; (3) 采用 Map ; (4) 需要一套校验语法。这里暂时直接采用 groovy 脚本。
DEMO实现###
使用者需要做什么####
接口测试用例编写者只需要定义一个 TestCase 类即可。这个类含有如下信息:
(1) 待测试接口的 url : http://ip:7001 及 restful 路径 /xxx
(2) 带有 @Case 注解的方法。 里面返回一个 Map,
name: 测试用例名 ;
param: 入参map ;
check: 校验函数。 data 就是返回的顶层。
比如搜索测试用例类SearchTestCases:
package cc.lovesq.study.testcase.qa
import cc.lovesq.study.testcase.Case
class SearchTestCases {
def url = 'http://ip:7001'
def path = '/searchApp/order/search'
@Case
def get() {
return [
'name': 'testSearchOrderNo',
'param': ['shopId': 55, 'orderNo': 'E20180507200552032000001', 'source':'service-test'],
'check': { data ->
data.list.each {
order ->
order.orderNo == 'E20180507200552032000001'
}
}
]
}
}
详情测试用例类
package cc.lovesq.study.testcase.qa
import cc.lovesq.study.testcase.Case
class DetailTestCases {
def url = 'http://ip:7001'
def path = '/detailApp/orderInfo/byOrderNo'
@Case
def get() {
return [
'name': 'testSingleOrderDetail',
'param': ['shopId': 55, 'orderNo': 'E20180507200552032000001', 'source':'service-test', 'bizGroup': 'trade'],
'check': { data ->
data.mainOrderInfo.orderNo == 'E20180507200552032000001'
}
]
}
}
框架基本实现####
通过指定的 TestCase 类,读取其用例配置信息,识别其中的用例配置,通过Http调用接口,然后回调指定的校验函数来校验结果。
package cc.lovesq.study.testcase
import groovyx.net.http.ContentType
import groovyx.net.http.HTTPBuilder
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import static groovyx.net.http.Method.POST
class CaseExecutor {
static Logger log = LoggerFactory.getLogger(CaseExecutor.class)
def invokeAllCases(testCase) {
Object tc = testCase
tc.getClass().getDeclaredMethods().findAll {
// 识别测试用例: 带有 @Case
it.getAnnotation(Case.class) != null
}.each {
it ->
def caseInfo = it.invoke(tc, null)
def result = exec(caseInfo['name'], tc.url, tc.path, caseInfo['param'], caseInfo['check'])
println("case=${caseInfo['name']}, result=${result}")
}
}
def exec(name, url, path, param, check) {
def http = new HTTPBuilder(url)
def result
http.request(POST) {
uri.path = path
requestContentType = ContentType.JSON
body = param
response.success = { resp, json ->
def data = json.data.data
try {
log.info("Enter Test Case : {}", name)
check(data)
result = "success"
} catch (Throwable e) {
result = "failed"
} finally {
log.info("Exit Test Case : {}", name)
}
}
response.failure = { resp ->
println "Unexpected error: ${resp.statusLine.statusCode} : ${resp.statusLine.reasonPhrase}"
def errorInfo = """
Call error: ${resp.statusLine.statusCode} : ${resp.statusLine.reasonPhrase}
Name: ${name}
Url: ${url}
Path: ${path}
Param: ${param}
"""
log.warn(errorInfo)
result = "failed"
}
}
result
}
}
客户端运行测试用例集合:
package cc.lovesq.study.testcase
import cc.lovesq.study.testcase.qa.DetailTestCases
import cc.lovesq.study.testcase.qa.SearchTestCases
class ClientTest {
def static main(args) {
CaseExecutor caseExecutor = new CaseExecutor()
caseExecutor.invokeAllCases(new SearchTestCases())
caseExecutor.invokeAllCases(new DetailTestCases())
}
}
代码讲解###
- 使用了HttpBuilder 类来发送HTTP请求。需要添加POM配置:
<dependency>
<groupId>org.codehaus.groovy.modules.http-builder</groupId>
<artifactId>http-builder</artifactId>
<version>0.6</version>
</dependency>
使用注解 @Case 来表示测试用例。注解可以用于标识一类对象。
使用Groovy闭包来传递校验逻辑。闭包可以用来传递变化的逻辑。
自动加载用例集合###
实际应用中,往往不会直接 new 一个 XXXTestCases 对象,而是将这些对象标记为 Component 后,在应用启动时加载这些 TestCases,建立映射。只要对 CaseExecutor 做一些扩展即可。 如下代码所示:
@Component("caseExecutor")
class CaseExecutor implements ApplicationContextAware {
static Logger log = LoggerFactory.getLogger(CaseExecutor.class)
ApplicationContext context
def casePathMap = [:]
@PostConstruct
def init() {
Map<String, Object> components = context.getBeansWithAnnotation(Component.class)
log.info("{}", components)
components.each {
name, comp ->
try {
def property = comp.metaClass.getProperty(comp, 'path')
if ( property) {
casePathMap[property] = comp
}
} catch (e) {
log.warn("not having restPath, omit")
}
}
}
// other codes
@Override
void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context = applicationContext
}
}
小结###
本文讲解了一种基于Groovy+HttpRestful的超轻量级的接口测试用例配置的设计方案及DEMO实现。基于这种方法,可以配置化地快速增加指定服务接口的测试用例集合,而不需要额外编写冗余的测试代码。
基于Groovy+HttpRestful的超轻量级的接口测试用例配置的设计方案及DEMO实现的更多相关文章
- Yii2 基于RESTful架构的 advanced版API接口开发 配置、实现、测试 (转)
环境配置: 开启服务器伪静态 本处以apache为例,查看apache的conf目录下httpd.conf,找到下面的代码 LoadModule rewrite_module modules/mod_ ...
- Yii2 基于RESTful架构的 advanced版API接口开发 配置、实现、测试
环境配置: 开启服务器伪静态 本处以apache为例,查看apache的conf目录下httpd.conf,找到下面的代码 LoadModule rewrite_module modules/mod_ ...
- Yii2 基于RESTful架构的 advanced版API接口开发 配置、实现、测试【转】
环境配置: 开启服务器伪静态 本处以apache为例,查看apache的conf目录下httpd.conf,找到下面的代码 LoadModule rewrite_module modules/mod_ ...
- 使用Groovy+Spock构建可配置的订单搜索接口测试用例集
概述 测试是软件成功上线的安全网.基本的测试包含单元测试.接口测试.在 "使用Groovy+Spock轻松写出更简洁的单测" 一文中已经讨论了使用GroovySpock编写简洁的单 ...
- API接口开发 配置、实现、测试
Yii2 基于RESTful架构的 advanced版API接口开发 配置.实现.测试 环境配置: 开启服务器伪静态 本处以apache为例,查看apache的conf目录下httpd.conf,找到 ...
- 基于领域驱动设计(DDD)超轻量级快速开发架构
smartadmin.core.urf 这个项目是基于asp.net core 3.1(最新)基础上参照领域驱动设计(DDD)的理念,并参考目前最为了流行的abp架构开发的一套轻量级的快速开发web ...
- 基于领域驱动设计(DDD)超轻量级快速开发架构(二)动态linq查询的实现方式
-之动态查询,查询逻辑封装复用 基于领域驱动设计(DDD)超轻量级快速开发架构详细介绍请看 https://www.cnblogs.com/neozhu/p/13174234.html 需求 配合Ea ...
- 分享自己的超轻量级高性能ORM数据访问框架Deft
Deft 简介 Deft是一个超轻量级高性能O/R mapping数据访问框架,简单易用,几分钟即可上手. Deft包含如下但不限于此的特点: 1.按照Transact-SQL的语法语义风格来设计,只 ...
- Groovy元编程应用之自动生成订单搜索接口测试用例集
背景 在 "Groovy元编程简明教程" 一文中,简明地介绍了 Groovy 元编程的特性. 那么,元编程可以应用哪些场合呢?元编程通常可以用来自动生成一些相似的模板代码. 在 & ...
随机推荐
- 【教程】Win7-64位安装OpenSSL详细过程
1.下载ActivePerl 5.24.0.2400 http://www.activestate.com/activeperl/downloads 图片:ActivePerl-5.24.0.240 ...
- 火车头采集器如何采集QQ群成员中的QQ号
如何采集QQ群群员QQ号,采集QQ号,批量采集QQ号 众所周知,QQ群群员QQ号无法导出,即使会员也不可以,那我们只能通过三方工具来实现我们的要求,那今天我们讲讲如何通过火车采集器来采集QQ群群员QQ ...
- dedecms模板中 if else怎么写
在制作dedecms模板时,有时需要使用IF ELSE判断语句,但是dedecms模板中是无法使用使用IF语句的,否则会报错. 那么如何在dedecms模板中使用 if else呢?这就需要我们多走 ...
- CSS外边距属性,深入理解margin
margin See the Pen margin by wmui (@wmui) on CodePen. 该属性用于设置元素的外边距,外边距是透明的,默认值0.这是一个简写属性,属性值最多为4个,例 ...
- C++将时间格式转换成秒数
#include <stdio.h> #include <time.h> #include <string.h> #include <stdlib.h> ...
- 11.12git部分和redis
2018-11-12 09:54:58 这星期把luffycity看完,然后周末回学校 越努力,越幸运!永远不要高估自己! 具体可以参考 戳我啊!! 一些git常用命令: 目前已使用Git的四个命令 ...
- Java进程与线程的区别
每个进程都独享一块内存空间,一个应用程序可以同时启动多个进程.比如浏览器,打开一个浏览器就相当于启动了一个进程. 线程指进程中的一个执行流程,一个进程可以包含多个线程. 每个进程都需要操作系统为其分配 ...
- 有多个正整数存放在数组中,编写一个函数要求偶数在左边由小到大顺序放置,奇数在右边,也是由小到大顺序放置,Java实现
思路: * 1.首先分左右 * 2.分好再排序(左边和右边都单独排序) 第一步:分左右 可得注意了: 大体思路最先是从两头出发分成4种情况讨论(左or右,奇数or偶数)循环处理,出口是双层的嵌套循环( ...
- 关闭shift中英文切换 英文代码/中文注释随意切换着写。
x 背景 写代码的时候总是意外的就切成中文了,特别是代码中大小写切换的这种情况... 例如:"public static TimeZone CurrentTime..."publi ...
- WebService,ESB笔记
一.WebService是什么? WebService,是RPC的一样实现方式. RPC(Remote Procedure Call Protocol)--远程过程调用协议,它是一种通过网络从远程计算 ...