接口测试 雪球的 HttpApi 接口测试框架设计

思寒_seveniruby · 2015年11月12日 · 最后由 白虹李李 回复于 2017年08月01日 · 5362 次阅读
本帖已被设为精华帖!

最近问接口测试的人挺多. 我先把我们公司自己设计的接口测试框架的README.md文档贴出来. 供大家做个思路参考. 工具会在过阵子开源出来. 目前是100%的用例都来自于录制并生成的测试用例. 然后稍作修改和调整断言.

HttpApi 基于Http的接口自动化框架

使用介绍

#下载工具解压进入目录

#开启代理.监听8788端口
bin/httpapi proxy 8788

#配置浏览器代理或者移动设备代理. 移动端需要导入证书.然后进入手工测试.

#从录制的Har文件中导出测试用例到scala文件, 比如只过滤匹配url包含search或者list的接口数据
bin/httpapi export proxy.har search list

#编辑测试用例, 并放入到src/test/scala/下即可

#运行所有用例
bin/httpapi test
#运行部分测试用例
bin/httpapi test-only com.xueqiu.httpapi.trade.*

录制并生成测试用例

框架会利用代理录制出来基本的测试用例框架.

生成的测试用例有三种风格. csv dsl和api. 推荐使用dsl

api方式

这是标准的scala调用方式, 可以自由的编码, 适合熟悉scala的人. 也可以导入到java的maven项目中使用

目前因为精力有限, 一直没有给研发打包.

dsl方式

这是较为规整的语法结果, 以|作为分隔符的类table结构. 是scala的内部dsl风格.

csv方式

这是纯csv方式,不过csv自身的语义表达太弱, 无法处理太复杂的结构. 所以不建议使用. 你可以从部分的样例中了解它的细节用法.

Excel也不能做逻辑处理. 还是离不开语言的runtime支持.

总体推荐使用dsl风格

DSL方式编写测试用例

这是一个验证雪球券商账号绑定和解绑的简单测试流程示例

test("多个账户绑定"){
data{
"tid" | "account" | "password"
"PINGAN" | "account_demo " | "password_demo"
}
flow2() {
"Authorize" | "req" | "tid" | row("tid")
"Authorize" | "req" | "fund_account" | row("account")
"Authorize" | "req" | "account_password" | row("password")
"Authorize" | "res" | "result_code" | "60000"

"data/proxy.har" |"Bind" |"req" | "tid"| row("tid")
"Bind" | "res" | "result_code" | "60000"

"data/proxy.har" |"Unbind" |"req" | "tid"| row("tid")
"Unbind" | "res" | "result_code" | "60000"
}

flow2关键词

这是一个只有四列数据的dsl. 可以省略掉通用的proxy.har. 适合har文件不变的情况
中文dsl不过是中文的class而已. flow2是flow关键词的简化版, 已经不推荐使用原来的flow关键词了

test("中文Dsl"){
flow2("proxy.har") {
"登录" | "req" | "username" | ""
"登录" | "req" | "telephone" | "1560053xxxx"
"登录" | "req" | "password" | "password"
"认证" | "req" | "tid" | "PINGAN"
"认证" | "req" | "fund_account" | "account"
"认证" | "req" | "account_password" | "account_password"
"认证" | "res" | "result_code" | "60000"
}
}

flow2的参数为你录制的har文件地址, 可以是目录. 他会读取里面的每个http接口, 分析结构的请求和响应.

可以通过httpapi工具的录制模式或者chrome fiddler等工具生成. 里面的每一行代表了接口请求的构建和结果校验

请求数据会被当做接口请求的默认值, 响应数据会被当做期望值去校验

第一列为接口指定, 他支持两种定义格式. 命名接口和url

第二列为操作选项, 有若干选项. req config path res和send.

第三列为取值方式

第四列为设置值

第三列表示真实值的获取方式, 支持jsonpath kv结构和回调函数

第四列表示期望值或者设置值是什么

主要是如下的用法

url | req | key | value 
url | res | actual | expect

默认接口url命名接口

默认录制的测试用例会使用接口的path部分来指定使用具体的接口.

接口的定义是从录制生成的json格式的har文件中寻找定义.

url格式为去掉前阵和后缀的路径, 比如

flow2("proxy.har"){
"/url/demo/path/api" | "req" | "trace_id" | "trace_id_demo"
"/url/demo/path/api" | "req" | "client" | "1"
"/url/demo/path/api" | "req" | "_" | "1441611982405"
"/url/demo/path/api" | "req" | "access_token" | "token_demo"
"/url/demo/path/api" | "req" | "x" | "0.24"
"/url/demo/path/api" | "req" | "access_token_expires" | "-1"

"/url/demo/path/api" | "res" | "msg" | "操作成功"
"/url/demo/path/api" | "res" | "result_code" | "60000"
}

他会从proxy.har中寻找路径符合/url/demo/path/api的接口, 并把请求值初始化.

然后再根据你写的用例吧具体的参数值重新赋值. 这样的好处就是测试用例可以不用写太多赋值语句了.

config命名接口

"User" "Authorize"为预定义好的关键词. 表示某个固定的接口, 这类接口一般是经过了特定的处理. 比如制定了接口的url method, 预先初始化参数值等.

比如券商有十几种接口. 通过"Authorize"只需要指定这个接口的关键数据即可, 他会根据你填写的券商数据自动选择各家券商针对的接口url地址.
定义命名接口有2个形式. 直接写一个scala的类定义. 或者直接在测试用例中使用如下形式来指定

"baidu" | "config" | "url" | "http://www.baidu.com/not_exist?wd={a}/{b}/"
"baidu" | "config" | "method" | "get"

req

req表示是对请求的构造, 他回把后面的数据当做key和value添加请求中. 请求的构造会根据har文件中的请求的方式进行构建.

比如get方式就构建url?key=value&...

post方式就构建request body.

将来也会支持json格式和xml格式等.

如下例子会发送一个http://www.baidu.com/s?wd=mp3&time=2015请求

"baidu" | "config" | "url" | "http://www.baidu.com/s"
"baidu" | "config" | "method" | "get"
"baidu" | "req" | "wd" | "mp3"
"baidu" | "req" | "time" | "2015"

如下例子发送post数据wd=mp3&time=2015到http://www.baidu.com/s

"baidu" | "config" | "url" | "http://www.baidu.com/s"
"baidu" | "config" | "method" | "post"
"baidu" | "req" | "wd" | "mp3"
"baidu" | "req" | "time" | "2015"

path

有些接口比如REST风格的接口, 有些变量是在url路径里面, 比如/user/{id}, 所以增加了这个path的支持.

通过这样的dsl可以设定url中的变量数据

比如以百度的接口为例

"baidu" | "config" | "url" | "http://www.baidu.com/{a}/{b}/"
"baidu" | "config" | "method" | "get"
"baidu" | "path" | "a" | "1"
"baidu" | "path" | "b" | "xxx"

res

res表示把后面的key|value当做期望值进行比较.

key支持jsonpath和普通的key方式. 比如结果格式为

{
"result_code" : "60000",
"msg" : "",
"result_data" : [ ],
"total_income_balance" : 0,
"day_income_balance" : 0,
"day_income_rate" : null,
"total_income_rate" : null
}

判断result_code可以写成如下两种风格. 当然推荐用JsonPath

"/url/demo/path/api" | "res" | "result_code" | "60000"
"/url/demo/path/api" | "res" | "$.result_code" | "60000"
"/cubes/discover/user/recommend" | "res" | "$.[0].recommend_reason" | "雪球投资达人"

JsonPath语法参考 https://github.com/jayway/JsonPath

send

这个大多数情况并不需要使用. 在断言res的时候会只能发送请求.

只有没有断言或者没有后续其他请求的时候, 才需要使用send显式的发送请求

数据参数化与数据驱动data关键词

data关键词可以实现数据参数化和数据驱动. flow则是定义了业务流程.

比如在券商的接口测试流程中, 想添加更多的数据集合, 但是又不写重复的测试步骤. 那么就可以利用data{}和row来实现

第一行为表头, 其他行每行数据为一个集合. 会驱动flow{}完整的运行一次.

test("多个账户绑定"){
data{
"tid" | "account" | "password"
"PINGAN" | "account_demo" | "account_password"
"FZZQ" | "xxx" |"ddd"
}
flow2("data/proxy.har") {
"Authorize" | "req" | "tid" | row("tid")
"Authorize" | "req" | "fund_account" | row("account")
"Authorize" | "req" | "account_password" | row("password")
"Authorize" | "res" | "result_code" | "60000"

"Bind" |"req" | "tid"| row("tid")
"Bind" | "res" | "result_code" | "60000"

"Unbind" |"req" | "tid"| row("tid")
"Unbind" | "res" | "result_code" | "60000"
}

data{}中第一行表示每一列的表头. 以下每一行都是一组测试数据.

在flow{}中用row("name")来替换原先硬编码的数据.

断言

除了标准的返回结构外, 还支持对http状态码 头信息, 接口的结构做断言.

test("302测试") {
"baidu" | "config" | "url" | "http://www.baidu.com/not_exist?wd={a}/{b}/"
"baidu" | "config" | "method" | "get"
"baidu" | "path" | "a" | "1"
"baidu" | "path" | "b" | "xxx"
"baidu" | "res" | "_.code" | 302
"baidu" | "res" | "_.headers.Server[0]" | "Apache"
"baidu" | "res" | "_.code" | 404
}

支持对接口的返回格式做校验, 对于每个返回结果, 都会对结构做解析, 并生成一个唯一md5签名.

如果结构发生变化, 这个签名就会发生变化 每次运行测试的时候都会在log中打印res_schema_md5的值.

可以找到对应接口的值并补充到自己的测试用例中. 如果接口结构变化, 记得更新即可.

"pankou" | "res" | "_.res_schema_md5" | "e4d000c6c9c4dae275cdc3ec53869e53"

在flow中res后面的最后两列表示真实值的访问方式和预期值. 默认是相等的关系.

如果自己想定义的更复杂的断言. 可以使用自定义断言. 比如

"Authorize" | "res" | "$.result_code" | { (actual:Any) => actual should equal ("80000") }

最后一列修改为scala的表达式, 这是一种匿名函数. 当然也可以写成命名函数, 这样可以编写更多复杂的处理.

val two_items_equal=(actual:Any) => actual should equal ("80000") 
"Authorize" | "res" | "$.result_code" | two_items_equal

常见的断言方式如下

## 字符串校验
string should startWith ("Hello")
string should endWith ("world")
string should include ("seven")
string should startWith regex "Hel*o"
string should endWith regex "wo.ld"
string should include regex "wo.ld"
## 数字校验
one should be < 7
one should be > 0
one should be <= 7
one should be >= 0

## 范围校验
sevenDotOh should equal (6.9 +- 0.2)
sevenDotOh should === (6.9 +- 0.2)
sevenDotOh should be (6.9 +- 0.2)
sevenDotOh shouldEqual 6.9 +- 0.2
sevenDotOh shouldBe 6.9 +- 0.2

## 可选值校验
Array(1) should contain oneOf (1,2,3)

所有支持的断言方式可参考 http://doc.scalatest.org/2.0/index.html#org.scalatest.Matchers

完整的测试用例

编写的测试用例本质是scala文件. 采用scala是因为它强大的表达能力.

所以在case的任何地方都可以直接写代码.

完整的测试用例如下

//定义suite名字
package com.xueqiu.httpapi.trade
//引入依赖包
import com.xueqiu.httpapi.framework.DslData._
import org.scalatest.{BeforeAndAfterAll, FunSuite}

//定义测试类和公共步骤
class QuanShangFlowMiniDemo extends FunSuite with BeforeAndAfterAll {
//定义所有case的seetup. 只执行一次
override def beforeAll(): Unit = {
flow2("data/proxy.har") {
"User" | "req" | "username" | username
"User" | "req" | "password" | password
"Authorize" | "req" | "tid" | tid
"Authorize" | "req" | "fund_account" | fund_account
"Authorize" | "req" | "account_password" | account_password
"Authorize" | "res" | "result_code" | "60000"
}
}
//固定编码方式
test("历史") {
flow2("data/proxy.har") {
"list_history" | "req" | "_" | "1441611757463"
"list_history" | "req" | "client" | "1"
"list_history" | "req" | "x" | "0.154"
"list_history" | "req" | "pos" | ""
"list_history" | "req" | "end" | "1441611752611"
"list_history" | "req" | "start" | "1439019752611"

"list_history" | "res" | "msg" | ""
"list_history" | "res" | "result_code" | "60000"
}
}

//数据驱动方式
test("多个账户绑定"){
data{
"tid" | "account" | "password"
"PINGAN" | "account_demo_1" | "account_password_1"
"PINGAN" | "account_demo_2" | "account_password_2"
"PINGAN" | "account_demo_3" | "account_password_3"
}
flow2(){
"User" | "req" | "username" | username
"User" | "req" | "password" | password

"Authorize" | "req" | "tid" | row("tid")
"Authorize" | "req" | "fund_account" | row("account")
"Authorize" | "req" | "account_password" | row("password")
"Authorize" | "res" | "result_code" | "60000"

"Bind" |"req" | "tid"| row("tid")
"Bind" | "res" | "result_code" | "60000"

"Unbind" |"req" | "tid"| row("tid")
"Unbind" | "res" | "result_code" | "60000"
}
}
}

框架预定义变量

每个业务可以自己定义自己的FunSuite类环境. 用来定义自己业务的一些通用的操作.

比如定义全局变量 读取配置文件等.

tid 券商的tid. 
fund_account 券商账号
account_password= 券商账号密码

username 默认登录手机
password 默认登录密码

框架技术基础

json4s用于实现json的数据解析和json schema的校验,官方有详细的文档

play-ws实现httpclient的封装, 官方有大量的测试用例

gatling-recorder用于实现自动录制接口请求并生成代码, 后来发现他的代码很挫, 就用了另外一个架构更好的proxy lib.
scala-test 实现测试用例的管理和运行. 支持junit rspec和BDD的测试风格.

jenkins 实现持续集成结合

调试工具推荐

代理分析工具: charles, burp suite, windows上的fiddler. 推荐使用burp.

设计思路

接口测试的核心因素是业务流程, 请求构造, 响应断言. 这些数据可来源于如下途径

通过代理技术可以获得上述所有数据, 是成本最低的办法. 缺点是只能开发完成后弥补接口

Swagger定义了接口规范. 也包含上述数据, 但是缺少业务流程说明. 只适合资源型接口

War包类反射. 从War或者Jar包中可以反射出所有的接口. 但是业务流程未知.

考虑到目前的现状, 先从代理技术入手. 完善现有业务的接口测试防护. 做好回归和冒烟测试.

然后再利用流量复制和录制来获知更多的业务接口使用场景

选择scala作为框架语言是因为这是jvm体系上最灵活的语言, 动态性比较强, 语法灵活.

而且scala的测试体系的产品比较完备, 比如常见的gatling+zipkin+diffy+scalatest, 几乎覆盖了功能测试, 性能测试, 监控和数据分析.
所以最初就决定转向scala去设计这个框架, 语言并无好坏 关键是否适用场景

不过因为scala太过强大, 不利于新手学习. 建议先选择其他的语言作为过渡比较好.

TODO

支持更自由的语法结构, 使用robotframework的风格去写用例. 封装业务层的DSL

目前已经实现了一部分, 还未充分测试. 已有的dsl已经很好的满足了需求. 所以设计这个需求并不大.

test("BDD样式") {
用户 登录(username, telephone , password)
券商 认证(tid, fund_account, account_password)
券商 绑定()
股票 选择 "乐视"
股票 当前价格 100
股票 当前价格
股票 买入 100
股票 选择 "中车"
股票 卖出 200
用户 注销
}

test("基于原有的api形式进行更高层的封装"){
用户.登录.req.username=""
用户.登录.req.password=""
用户.登录.req.telephone=""
用户.登录.res.result_code="60000"
}

支持使用思维导图设计用例

进行中

支持所有的结构化支持

html xml等各种协议都可以支持. 可以考虑重用diffy的模块

更多计划

  • 支持自动识别token等关联字段
  • 支持swagger自动生成测试用例(重要)
  • restful自动化测试用例生成(重要)
  • 维护api和dsl两套体系. 文档要齐全(重要)
  • 支持复杂结构的断言生成. 已经支持map, 后续支持list (先手写)
  • 支持相同请求参数的配置化, 不用重复编写(延后)
  • 支持url的参数化(重要)
  • 支持Mock. 考虑moco框架(延后)
  • 使用Dynamic方法重新设计DslData, 支持api.req.key=value的方式(中等)
  • 增加api的create方法(中等)
  • 与Diffy结合. 自动生成用例和断言(重要)
  • 支持并发. 去掉影响并发的静态类的使用(延后)
  • 设计一个动态api的dsl, 是api形式的精简版本
  • 增加java版本的jar支持 (延后)
  • 支持用json写接口(延后)

灵感

来自于百度内部的SuperTest框架. SuperTest是行业接口测试框架的楷模, 我在百度时有幸维护过一段时间. 因为某些原因并没有开源出来.

httpapi几乎是它的jvm简化实现版本

因为我们公司是业务型的公司, 所以没有太多的精力去做一个完美的框架. 我们组也无意去全力开发框架. 更想把精力投入在业务相关的事情上.

在业务接口监控, 用户体验分析, 移动端测试还有更大的事情要做. 所以计划开源出来给大家借鉴. 期待行业能有更好用的产品.

年前就会把工具开放到github上. 最近在逐渐的完善细节.

根据使用效果来看, 组内招聘的业务测试新人都是具备一定开发基础的. 都具备java和eclipse的使用经验. 来部门后被我们安利到了IDEA上. 我并没有培训他们scala语言. 他们到现在并不会scala, 但是对这个框架运用的很熟练. 编写和补充测试用例非常快. 唯一吐槽的就是sbt的一些仓库被墙导致下载更新包容易卡住.
利用jenkins跑测试用例并生成报表. 帮我们发现了不少的接口问题. 定位问题非常的快. 对于公司新的项目, 后端和前端并行开发的情况下, 利用接口测试也做到了提前的质量保证, 保证了项目的平稳进展.

这个框架并不是特别简单, 在易用性和灵活性方面, 我选择了灵活性来保证金融领域复杂的业务可以得到充分的验证. 主要的设计者是我的主管@skytraveler和我, 我们也希望有更多人可以一起参与进来完善它. 后续会开源到github上testerhome组织里, 交给大家一起维护 .

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

自动生成用例那块不太了解,需要再好好求教 求教 ~~

#1楼 @xushizhao

替思寒同学回答:
har是保存http请求和响应的规范。 http://weizhifeng.net/har-12-spec-chinese-edtion.html
录制的过程是:架设代理,代理截获所有请求和响应,录制成har标准文件。
然后通过工具,从har中抽取出关键元素,并生成DSL。DSL并不包含http请求和响应的所有信息(如header,cookie等),只关注业务相关信息。

回放:测试框架会把DSL中的元素和har中的元素共同生成标准的httprequest。

这样做的目的是:录制回放机制让用例的生成变得简单(因为是录制出来的不是纯写出来的),并且让代码可读性更强。因为有了一步抽取DSL的动作。

#1楼 @xushizhao 其实本来是想用gatling-recorder的. 但是目前gatling使用了强大的akka. 我们还一时消化不了他的架构, 也没法跟scalatest一个很好的整合. 所以就用了其他的方案.

信息量太大 容我慢慢消化一下

满满的干货,期待放出源码

先回再看

先关注下,最好出一个测试平台

先关注,慢慢消化。

看到中车吓得一激灵~
学习了,感谢分享。

#9楼 @anikikun 哈哈, 今年被中车坑的人不少

希望越做越好!

又学习了一种新思路,看起来似乎不难上手,感觉这样比用excel维护用例再从excel读取执行要更加简洁。断言里面支持正则吗?

#12楼 @watman 支持, 使用的是标准框架的断言功能. 我未作任何修改

#13楼 @seveniruby 确实赞,求开源学习下。

好东西,谢谢分享,功力尚浅,期待开源后更进一步的学习

啥时开源哈 !

#13楼 @seveniruby 对于有登录态校验或者接口有依赖关系的场景需要解决的问题:1.参数化和动态关联,场景:接口B的某个请求参数从接口A的返回中获取,例如:在A接口的response中用正则表达式提取参数,用于替换B接口请求参数变量;2.动态参数的持久化,场景:接口A返回中截取的某个参数可能在多个用例的请求参数中用到;3.断言的参数化和正则表达式支持;4.对复杂请求参数的支持,因为请求参数不一定就是简单的数据类型。。。
对于个别前端产生的请求参数(虽然不多,但也要考虑):实现思路,反射实现动态调用方法、js方法等

#3楼 @seveniruby 生成HAR文件的其他方案是啥?

#18楼 @doctorq


libraryDependencies ++= Seq(
"org.json" % "json" % "20150729",
"org.json4s" %% "json4s-jackson" % "3.3.0.RC3", //json schema
"com.typesafe.play" %% "play-ws" % "2.4.2", //http client
"org.scalatest" %% "scalatest" % "3.0.0-M10",
"com.netaporter" %% "scala-uri" % "0.4.8", //uri.parse
//"org.json4s" %% "json4s" % "3.2.11"
//"org.json4s" % "json4s-jackson_2.11" % "3.3.0.RC3",
//"org.json4s" %% "json4s-native" % "3.2.11"
//"com.typesafe.play" %% "twirl-parser" % "1.1.1",
//"net.lightbody.bmp" % "browsermob-proxy" % "2.1.0-beta-2",
"net.lightbody.bmp" % "browsermob-core-littleproxy" % "2.1.0-beta-2",
"net.lightbody.bmp" % "browsermob-core" % "2.1.0-beta-2",
"com.github.tototoshi" %% "scala-csv" % "1.2.2",
//"com.fasterxml.jackson.core" % "jackson-databind" % "2.2.2",
"com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.6.1",
"org.yaml" % "snakeyaml" % "1.16",
"org.scalaz" %% "scalaz-core" % "7.1.3",
"com.fasterxml.jackson.dataformat" % "jackson-dataformat-yaml" % "2.5.4",
"com.twitter" %% "util-eval" % "6.26.0",
"com.typesafe.scala-logging" %% "scala-logging" % "3.1.0",
"com.dongxiguo" %% "fastring" % "0.2.4", //gatling也在是使用这个库, 用于模板生成
"org.scala-lang" % "scala-compiler" % "2.11.7",
"org.scala-lang" % "scala-library" % "2.11.7",
"org.scala-lang" % "scala-reflect" % "2.11.7",
//"org.clapper" % "classutil_2.11" % "1.0.5", //find class and load
//"com.typesafe.sbt" % "sbt-launcher" % "0.13.6", //导入到项目会导致IDE各种报错,暂时在lib下放置jar解决
"com.jayway.jsonpath" % "json-path" % "2.0.0",
"com.typesafe.akka" % "akka-stream-experimental_2.11" % "1.0",
"com.typesafe.akka" % "akka-http-core-experimental_2.11" % "1.0",
"com.typesafe.akka" % "akka-http-experimental_2.11" % "1.0",
"com.twitter" %% "finagle-httpx" % "6.28.0",
"com.propensive" %% "rapture" % "2.0.0-M1",//json dynmatic type support
"com.propensive" %% "rapture-json" % "2.0.0-M1",//json dynmatic type support
"com.propensive" %% "rapture-json-json4s" % "2.0.0-M1",//json dynmatic type support
//"io.gatling.highcharts" % "gatling-charts-highcharts" % "2.1.7", //准备和gatling保持兼容并支持让单测像自动化那样使用
"com.typesafe.slick" %% "slick" % "3.1.0",
//"org.slf4j" % "slf4j-nop" % "1.6.4",
"mysql" % "mysql-connector-java" % "5.1.12",
"com.thoughtworks.xstream" % "xstream-distribution" % "1.4.8",
"org.codehaus.jettison" % "jettison" % "1.3.7",
"org.pegdown" % "pegdown" % "1.0.2" //html report
)

@seveniruby 在github上没有看到,请问现在开源了吗?最近在调研这方面的实现,录制并生成测试用例这点很好,能够极大的提高测试效率,真诚期待开源

关注了此帖子许久,我想问下,怎么才能很好的设置检查点?有没有好的解决方案,正则吗?

楼主,你好,能 大致说下 思维导图生成测试用例的思路么?

思寒_seveniruby [该话题已被删除] 中提及了此贴 06月28日 16:29
陈恒捷 [该话题已被删除] 中提及了此贴 08月21日 01:50

在github上没有看到,啥时候有开源计划~~~~?

感谢分享,很详细

@seveniruby 好详细、规范,期待开源👍

开源了吗?给个地址呗

陈恒捷 接口测试的一些感悟 中提及了此贴 12月13日 10:29

太棒了,坐等黄老师开源~

还没开源吗?

#32楼 @wodeta33 因为rest-assured跟我做的差不多. 行业已经有一个了. 所以这个我就不打算开源了. 以免被人误会重复造轮子.

@seveniruby 原来如此,我去看看,感谢

#33楼 @seveniruby 好像python圈子里还没有这样的框架,要是搞出个python版的就好了

#35楼 @ycwdaaaa 你不是用java吗. dsl是次要的. api清晰可管理即可

#36楼 @seveniruby 恩,我主语言是java。就是感叹python的同学没有这么好用的框架可用

#37楼 @ycwdaaaa python如果有人好好设计下. 会比java好用不少的. java的语法太low了.太多历史包袱. 另外jython是可以使用这个框架的.

#38楼 @seveniruby 没错,而且我觉得现在python生态圈的发展也没有java那么好。所以缺失了一些很多好用的第三方模块。加上毕竟目前互联网应用还是java得天下。所以作为测试的语言,还是用java好一些。 但不得不说,不论是scala还是python,在语法上简直完爆了java

曾晖斌 接口测试的个人定义 + 话题讨论 中提及了此贴 05月11日 19:06

赞一个!

最近几天一篇一篇的看思寒老师的文章,收获很多。也扫清了很多疑惑。
逐步的明确下来了我们将要采用的方案:jenkins+testng+rest-assured+testlink。

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册