RestFixture是Fitness的一个测试REST服务的插件,用于调用标准的http 
GET/POST等请求方法,并可以用XPath语法和Javascript语法检验http响应。本文介绍安装运行RestFixture的步骤,并给出测试用例示例。

首先普及一下概念,什么是Fitnesse,听一听.NET版Cucumber的创始人Aslak Hellesøy谈Fitnesse与Cucumber对比:

FIT/Fitnesse和Cucumber都执行高级语言编写的验收测试。FIT仅识别HTML,Fitnesse则通过提供Wiki语法来简化编写测试的过程。在FIT/Fitnesse当中,所有的测试都以表格的形式呈现。 
FitNesse比Cucumber的优势在于Wiki支持。

原文链接:http://www.infoq.com/cn/news/2009/11/interview-cucumber-for-dotnet

1.几句题外话

对于http请求的测试,有几种方式:

  1. 浏览器中输入http url,只适用于GET方法
  2. curl命令手工测试
  3. junit中直接用java network api调用GET/POST方法
  4. 在自动化测试框架中封装指令,如cucumber, fitnesse, robotframework

上述1、2手工测试,不能用于回归测试;3、4能用于回归测试,但要开发测试脚本代码,维护非常麻烦。

今日回想起两年前浅尝辄止的fitnesse,想碰运气看看有没有好的测试插件,结果真找到了用于Restful API测试的插件:RestFixture

2.Fitnesse 20111026+RestFixture 3.0 ——最佳拍档

2.1 http响应格式是xml的示例

废话少说,先上图: 

上面的测试用例的目的是:

并且 tag内容是

1
Don't forget the meeting!

note.xml的内容:

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="ISO-8859-1"?>
<!--  Copyright w3school.com.cn -->
<note>
    <to>George</to>
    <from>John</from>
    <heading>Reminder</heading>
    <body>Don't forget the meeting!</body>
</note>

fitnesse 测试用例wiki文本:

1
2
3
4
5
6
!define TEST_SYSTEM {slim}
 
!path D:\fitnesse\fitnesse-20111026\smartrics-RestFixture-3.0\lib\*
 
| Table:smartrics.rest.fitnesse.fixture.RestFixture | http://www.w3school.com.cn |
| GET | /example/xmle/note.xml | 200 | Content-Type: text/xml | //body[text()="Don't forget the meeting!"]|

2.2 http响应格式是json的示例

上面的测试用例的目的是:

调用百度地图Web API,根据IP获取地图地址信息,检查服务响应内容中的status字段必须是0,下面判断语句是javascript表达式:

1
jsonbody.status==0

GET访问的url:

  • http://api.map.baidu.com/location/ip?ip=202.198.16.3&coor=bd09ll&ak=60IFKTCwlIsSpDcGfkx36L8u

url返回的内容:

1
{"address":"CN|\u5409\u6797|\u957f\u6625|None|CERNET|1|None","content":{"address":"\u5409\u6797\u7701\u957f\u6625\u5e02","address_detail":{"city":"\u957f\u6625\u5e02","city_code":53,"district":"","province":"\u5409\u6797\u7701","street":"","street_number":""},"point":{"x":"125.31364243","y":"43.89833761"}},"status":0}

被调用Web API文档:

  • http://developer.baidu.com/map/wiki/index.php?title=webapi/ip-api#.E6.8E.A5.E5.8F.A3.E7.A4.BA.E4.BE.8B

fitnesse 测试用例wiki文本:

1
2
3
4
5
6
!define TEST_SYSTEM {slim}
 
!path D:\fitnesse\fitnesse-20111026\smartrics-RestFixture-3.0\lib\*
 
| Table:smartrics.rest.fitnesse.fixture.RestFixture | http://api.map.baidu.com |
| GET | /location/ip?ip=202.198.16.3&coor=bd09ll&ak=60IFKTCwlIsSpDcGfkx36L8u | 200 | Content-Type: application/json | jsonbody.status==0 |

2.3 用javascript处理json对象

我们再来看上面的GET响应文本:

1
{"address":"CN|\u5409\u6797|\u957f\u6625|None|CERNET|1|None","content":{"address":"\u5409\u6797\u7701\u957f\u6625\u5e02","address_detail":{"city":"\u957f\u6625\u5e02","city_code":53,"district":"","province":"\u5409\u6797\u7701","street":"","street_number":""},"point":{"x":"125.31364243","y":"43.89833761"}},"status":0}

\u5409\u6797|\u957f\u6625是什么?

按照百度API文档,应该返回这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
    address: "CN|吉林|长春|None|CERNET|1|None"
    content: { 
    address: "吉林省长春市"
    address_detail: { 
    city: "长春市"
    city_code: 53
    district: ""
    province: "吉林省"
    street: ""
    street_number: "" 
    }, 
    point: {      
    x: "125.31364243",     
    y: "43.89833761" 
    
    }, 
    status: 0 
}

原来\u5409\u6797|\u957f\u6625是 吉林|长春 encodeURI的结果

可以在 Chrome浏览器 > 菜单 > 工具 > JavaScript控制台(Firefox/IE/Opera都有对应的控制台) 中使用 String.replace函数来把\u5409变成"吉”:

下一步在Fitnesse中要见证奇迹了,RestFixture居然支持Javascript语法和全局函数,也可以调用String.replace函数:

1
2
3
4
5
6
7
!define TEST_SYSTEM {slim}
 
!path D:\fitnesse\fitnesse-20111026\smartrics-RestFixture-3.0\lib\*
 
| Table:smartrics.rest.fitnesse.fixture.RestFixture | http://api.map.baidu.com |
| GET | /location/ip?ip=202.198.16.3&coor=bd09ll&ak=60IFKTCwlIsSpDcGfkx36L8u | 200 | Content-Type: application/json | jsonbody.status==0 |
| let | bodyDecoded | js | response.body.replace(/\\u[\dabcdef]{4}/g, function(word){return String.fromCharCode(parseInt(word.substr(2),16))}) | |

RestFixture变量bodyDecoded的内容是中文化后的json:

1
{"address":"CN|吉林|长春|None|CERNET|1|None","content":{"address":"吉林省长春市","address_detail":{"city":"长春市","city_code":53,"district":"","province":"吉林省","street":"","street_number":""},"point":{"x":"125.31364243","y":"43.89833761"}},"status":0}

下面,还可以把bodyDecoded作为表达式文本计算,生成一个js对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
| let | printJsonMembers | js | !-
var jsonObject = eval('a=%bodyDecoded%');
var str1="";
function printObject(obj, indent){
  for(var i in obj){
    if(typeof obj[i] == "object"){
      str1+= indent + i+":"+"\n";
      printObject(obj[i], indent+"\t\t");
    } else
      str1+= indent + i +":"+obj[i] + "\n";
  }
}
printObject(jsonObject, "");
str1-! | |

这里要演示的第二个let行使用了第一个let行定义的变量:%bodyDecoded%,显然借鉴了Windows Bat文件的语法。

测试结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
address:CN|吉林|长春|None|CERNET|1|None
content:
        address:吉林省长春市
        address_detail:
                city:长春市
                city_code:53
                district:
                province:吉林省
                street:
                street_number:
        point:
                x:125.31364243
                y:43.89833761
status:0

3.RestFixture参考资料

3.1 RestFixture使用文档

RestFixture使用文档链接

https://cloud.github.com/downloads/smartrics/RestFixture/RestFixture-3.0.pdf

3.2 运行环境

fitnesse运行环境文件目录:

 

注意:其中的slf4j-simple-1.6.6.jar需要额外下载

启动fitnesse命令: 

D:\fitnesse\fitnesse-20111026>java -jar fitnesse.jar -p 11026

-p 11026 是让fitnesse网站使用11026端口,因为我要在后面的例子中使用多个fitnesse版本,所以用版本号作为端口。

3.3 相关安装包下载地址

RestFixture安装包下载地址:

slf4j-simple-1.6.6.jar下载地址:

Fitnesse安装包下载地址:

3.4 相关网址

  • Fitnesse 首页:
  • http://www.fitnesse.org/
  • Fitnesse安装包下载: Fitnesse首页 > Download > release 20111026 > fitnesse.jar
  • Fitnesse插件列表: Fitnesse首页 > Plug-ins
  • RestFixture首页: Fitnesse首页 > Plug-ins > SLiM Fixtures > RestFixture =>
  • https://github.com/smartrics/RestFixture
  • RestFixture安装包下载: RestFixture首页 > Wiki > Live documentation > download > smartrics-RestFixture-3.0-bin.zip
  • RestFixture使用文档: RestFixture首页 > Wiki > Live documentation > download > RestFixture-3.0.pdf

4.Fitnesse 20140630+RestFixture 3.0 ——水土不服

RestFixture在最新版Fitnesse 20140630 的运行结果: 

其中的GET行,只有第2、3列正确显示,4、5列显示为HTML文本,看上去十分杂乱,

旧版的Fitnesse是这样显示的:

后续的博客中,我会介绍如何让RestFixture 3.0在Fitnesse 20140630中也能打印出漂亮的测试结果。

为Fitnesse-20140630定制RestFixture代码

Fitnesse+RestFixture:Web服务回归测试利器的更多相关文章

  1. 如何测试Web服务.2

    -->全文字数:2700,需要占用你几分钟的阅读时间 ,您也可以收藏后,时间充足时再阅读- -->上一节讲了<Web服务基础介绍>,本节介绍可用于测试web服务的开源测试工具. ...

  2. RESTful风格的Web服务框架:Swagger

    Swagger与SpringMVC项目整合 为了方便的管理项目中API接口,在网上找了好多关于API接口管理的资料,感觉目前最流行的莫过于Swagger了,功能强大,UI界面漂亮,并且支持在线测试等等 ...

  3. 关于如何提高Web服务端并发效率的异步编程技术

    最近我研究技术的一个重点是java的多线程开发,在我早期学习java的时候,很多书上把java的多线程开发标榜为简单易用,这个简单易用是以C语言作为参照的,不过我也没有使用过C语言开发过多线程,我只知 ...

  4. 基于IIS构建Pyathon Web服务

    本文简单叙述了在Windows下,如何利用IIS构建Python Web服务. 其主要步骤如下: 1.在IIS下构建一个站点,如图: 2.配置Python文件的处理程序,如图: 3.最后,在对应站点根 ...

  5. Web服务

    Web服务的相关信息 Apache服务器是web服务的重要应用 在这也是讲的apache   这里需要安装一个http服务软件才行! Apache的根文档在/var/www/html 主配置文件 /e ...

  6. Python flask 基于 Flask 提供 RESTful Web 服务

    转载自 http://python.jobbole.com/87118/ 什么是 REST REST 全称是 Representational State Transfer,翻译成中文是『表现层状态转 ...

  7. 使用 ServiceStack 构建跨平台 Web 服务

    本文主要来自MSDN杂志<Building Cross-Platform Web Services with ServiceStack>,Windows Communication Fou ...

  8. webServices与Web服务

    本篇的内容在MSND中标注已是一项旧技术,而取而代之的是WCF, 那么我也放弃吧!但是这个属于Web服务的范畴,而WCF本质上也是一个Web服务来的,所以对于基础的东西还是不变的.那么这次就着重看看这 ...

  9. J2EE基础之Web服务简介

    J2EE基础之Web服务简介 1.什么是Web服务? 在人们的日常生活中,经常会查询网页上某城市的天气信息,这些信息都是动态的.实时的,它是专业的气象站提供的一种服务.例如,在网上购物时,通常采用网上 ...

随机推荐

  1. struts2学习笔记(4)——数据类型转换

    回过头来看昨天的那个例子. 在昨天的例子中,只转换了一个Point类,如果想转换多个Point类怎么办呢?在昨天的例子上面做一个小的修改. 首先在input.jsp页面中修改几个输入框. <s: ...

  2. Mininet 创建topo的时候指定host的ip

    示例,要创建一个3个交换机8个主机的拓扑,如下图: 可以用如下python代码创建上述拓扑,并指定ip: from mininet.topo import Topo class MyTopo( Top ...

  3. Ubuntu 取消sudo密码

    需求:在Ubuntu下装了FQ代理goagent之后,为了goagent能够开机启动.因为goagent需要sudo权限,所以要去掉sudo密码. 要修改的文件位于/etc/sudoers,先备份: ...

  4. java小程序:求完全数

    如果一个数等于它的不包括自身的所有因数之和,那么这个数就叫完全数.例如,6的不包括自身的所有因数为1,2,3,而且6=1+2+3,所以6是完全数. 大约2200多年前,欧几里德提出:如果2n-1是质数 ...

  5. Android:数据存储之SQLite

    Android在运行时集成了SQLite , 所以每个Android应用程序都可以使用SQLite数据库. 我们通过SQLiteDatabase这个类的对象操作SQLite数据库,而且不需要身份验证. ...

  6. 2、JPA的HelloWorld

    这一节写一个JPA的HelloWorld来体验一下. 一.建立工程 按照 1.创建一个JPA project(解决“at least one user library must be selected ...

  7. Map集合案例

    1.获取字符串中每一个字母出现的次数. 比如"aababcabcdabcde",结果为:a(5)b(4)c(3)d(2)e(1) 分析如下: package mapexercise ...

  8. kafka的环境搭建

    kafka是一个高吞吐量的消息系统.隔离消息接收和处理过程(可理解为一个缓存) 1.kafka伪分布的部署 1.1.下载并解压 1.2.启动zk bin/zookeeper-server-start. ...

  9. Android权限安全(7)binder,service,zygote安全相关简介

    binder 提供服务的service中的binder thread 检查调用者的uid 不是root,system就异常. service 也检查调用者的uid 不是root,system,只能注册 ...

  10. Fedora20 优化体验

    玩了些许天的fedora系统,到底是加深了对于linux系统的了解 为了便于大家对于fedora系统支持,我将这些天对于fedora的一些不适之处及改进的策略进行了一下小总结.便于新手对于fedora ...