为Fitnesse-20140630定制RestFixture代码

摘要:Fitnesse插件RestFixture在最新版Fitnesse输出测试结果为html文本,而非html。本博文记录定制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

准备开发环境

假定你已经正确安装JDK, Eclipse, Ant, Maven,安装步骤可以参见博文:

http://fitnessefan.iteye.com/blog/2102696

Eclipse中用Git下载 git.oschina.net上的FitnesseKit源代码

https://git.oschina.net/fitneesefan/FitnesseKit.git

步骤: 
Eclipse Menu > Window > Open Perspective > Other… > Git > Clone a Git Repository and add it to this view:

下载git仓库

克隆FitnesseKit到D:\git\FitnesseKit

编译并启动Fitneese

编译Fitneese?

1
D:\git\FitnesseKit\fitnesse >ant

编译RestFixture?

1
D:\git\FitnesseKit\RestFixture>mvn clean package

启动Fitneese?

1
D:\git\FitnesseKit\fitnesse >ant run

打开Fitnesse网站:

localhost:8001

添加测试wiki页

Fitnesse FrontPage页点击Edit按钮:

编辑FrontPage

插入代码:?

1
2
3
4
5
检查RestFixture是否已正确安装
| RestFixtureInstallTest |
 
百度地图服务API测试集
| BaiduMapApiSuite |

点击Save:

保存后

上图中可以看到:

附带说明一下Fitnesse的wiki语法:

两个大写字母开头的英文单词(比如HelloWorld)连在一起,称为WikiWord,直接指向链接:http://localhost:8001/HelloWorld,如果该wiki页存在,就指向它,否则显示为一个”?“,并指向创建改wiki页的链接。

点击 RestFixtureInstallTest的链接,看到:

在此输入图片描述

Edit后看到wiki文本为:?

1
2
3
4
5
6
7
8
9
10
!define TEST_SYSTEM {slim}
 
!path D:\git\FitnesseKit\RestFixture\target\dependencies\*
!path D:\git\FitnesseKit\RestFixture\target\smartrics-RestFixture- 3.1 -SNAPSHOT.jar
!path D:\git\FitnesseKit\RestFixture\extra\slf4j-simple- 1.6 . 6 .jar
 
 
 
| 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!"]|

点击Cancel,回到wiki页,

测试wiki页

点击Test运行测试:

在此输入图片描述

输出测试结果为html文本,而非html

修改RestFixture代码直到测试结果显示为正常的html

分析测试结果

测试结果表格:

Table:smartrics.rest.fitnesse.fixture.RestFixturehttp://www.w3school.com.cn
GET/example/xmle/note.xml200Content-Type:&nbsp;text/xml<br/><i><span class='fit_label'>expected</span></i><hr/><br/>Content-Length&nbsp;:&nbsp;209<br/>Content-Type&nbsp;:&nbsp;text/xml<br/>Last-Modified&nbsp;:&nbsp;Mon,&nbsp;29&nbsp;Jul&nbsp;2013&nbsp;17:25:37&nbsp;GMT<br/>Accept-Ranges&nbsp;:&nbsp;bytes<br/>ETag&nbsp;:&nbsp;"344628a4808cce1:28cc"<br/>Server&nbsp;:&nbsp;Microsoft-IIS/6.0<br/>X-Powered-By&nbsp;:&nbsp;ASP.NET<br/>Date&nbsp;:&nbsp;Sun,&nbsp;03&nbsp;Aug&nbsp;2014&nbsp;01:20:44&nbsp;GMT<br/><i><span class='fit_label'>actual</span></i>//body[text()="Don't&nbsp;forget&nbsp;the&nbsp;meeting!"]<br/><i><span class='fit_label'>expected</span></i><hr/><br/>&lt;?xml&nbsp;version="1.0"&nbsp;encoding="ISO-8859-1"?&gt; <br/>&lt;!--&nbsp;&nbsp;Copyright&nbsp;w3school.com.cn&nbsp;--&gt; <br/>&lt;note&gt; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;to&gt;George&lt;/to&gt; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;from&gt;John&lt;/from&gt; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;heading&gt;Reminder&lt;/heading&gt; <br/>&nbsp;&nbsp;&nbsp;&nbsp;&lt;body&gt;Don't&nbsp;forget&nbsp;the&nbsp;meeting!&lt;/body&gt; <br/>&lt;/note&gt;&nbsp; <br/><br/><i><span class='fit_label'>actual</span></i>

Markdown语法不支持表格,只能从Fitnesse中把html文本直接贴到这里。

分析上面的表格,发现测试结果对原wiki内容作了替换:

  • 第一行第一列(Table:smartrics.rest.fitnesse.fixture.RestFixture)被设置了绿色背景色
  • 第二行第二列(/example/xmle/note.xml)被替换为<a>标签,能正确显示html。
  • 第二行第四列(Content-Type:…)被替换为html文本,不能正确显示html。

*好像找到问题的线索了,对比一下第二行第二列为什么正确,而第二行第四列为什么不正确。

接下去笨办法:在所有文件中查找html字段:

Eclipse Menu > Search > Search… > File Search

search对话框

search结果

接下去经过痛苦无助的人肉搜索,找到关键代码:

ashtml

文件: D:\git\FitnesseKit\fitnesse\src\fitnesse\testsystems\slim\HtmlTable.java?

1
2
3
4
static boolean qualifiesAsHtml(String text) {
     // performance improvement: First check 1st character.
     return text.startsWith( "<" ) && HTML_PATTERN.matcher(text).matches();
   }

函数名qualifiesAsHtml意思是可以当做html 
函数代码意思是必须以”<“开头且符合HTML_PATTERN定义的html匹配正则表达式

在HTML_PATTERN上按F3键,或者鼠标右键菜单中选择Open Declaration,可以看到HTML_PATTERN的定义:?

1
2
3
4
private final static Pattern HTML_PATTERN = Pattern.compile( "^<(p|hr|pre|ul|ol|dl|div|h[1-6]|hgroup|address|" +
           "blockquote|ins|del|object|map||video|audio|figure|table|fieldset|canvas|a|em|strong|small|mark|" +
           "abbr|dfn|i|b|s|u|code|var|samp|kbd|sup|sub|q|cite|span|br|ins|del|img|embed|object|video|audio|label|" +
           "output|datalist|progress|command|canvas|time|meter)([ >].*</\\1>|[^>]*/>)$" , Pattern.CASE_INSENSITIVE | Pattern.DOTALL);

再回去看一下,测试结果表格:

  • 第二行第二列(/example/xmle/note.xml)的html文本为:

    <a href=“http://www.w3school.com.cn/example/xmle/note.xml”>/example/xmle/note.xml</a>

  • 第二行第四列(Content-Type:…)的html文本为:

    Content-Type:&nbsp;text/xml<br/><i><span class='fit_label'>expected</span></i><hr/><br/>Content-Length&nbsp;:&nbsp;209<br/>Content-Type&nbsp;:&nbsp;text/xml<br/>Last-Modified&nbsp;:&nbsp;Mon,&nbsp;29&nbsp;Jul&nbsp;2013&nbsp;17:25:37&nbsp;GMT<br/>Accept-Ranges&nbsp;:&nbsp;bytes<br/>ETag&nbsp;:&nbsp;“344628a4808cce1:28cc”<br/>Server&nbsp;:&nbsp;Microsoft-IIS/6.0<br/>X-Powered-By&nbsp;:&nbsp;ASP.NET<br/>Date&nbsp;:&nbsp;Sun,&nbsp;03&nbsp;Aug&nbsp;2014&nbsp;01:20:44&nbsp;GMT<br/><i><span class='fit_label'>actual</span></i>

显然第二行第四列(Content-Type:…)不能被识别为html。

接下去,有两条路可走:

  1. 修改Fitnesse中的qualifiesAsHtml函数,直接return true。
  2. 修改RestFixture中测试结果,套一个<span> tag。

第1条路我试过,编译成功,但是编译后自动单元测试和验收测试时,报了无数个测试结果失败。 
主要原因是”<"和">“是有关键用处的,看下面Fitnesse验收用例:

http://fitnesse.org/FitNesse.SuiteAcceptanceTests.SuiteSlimTests.TestComparators

比较符号

结果证明第1条路走不同,为了一个Fixture,更改Fitneese语法显然得不尝试。

接下去走第2条路:修改RestFixture中测试结果,套一个<span> tag

修改RestFixture代码

RestFixture实现为一个Slim TableTable,SlimTable的帮助文档在这里: 
slim tabletable

接下去在Project RestFixture中搜索"pass:“,很容易定位到:

D:\git\FitnesseKit\RestFixture\src\main\java\smartrics\rest\fitnesse\fixture\SlimFormatter.java?

1
102        expected.body( "pass:" + Tools.makeContentForRightCell(expected.body(), typeAdapter, this , minLenForToggle));

给测试结果套上一层<span> tag,把这一行修改为:?

1
102        expected.body( "pass:<span>" + Tools.makeContentForRightCell(expected.body(), typeAdapter, this , minLenForToggle) + "</span>" );

编译RestFixture:?

1
2
3
4
5
6
7
8
9
10
D:\git\FitnesseKit\RestFixture>mvn compile     
...
[INFO] Compiling 1 source file to D:\git\FitnesseKit\RestFixture\target\classes
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 25.678 s
[INFO] Finished at: 2014 - 08 -03T13: 13 : 07 + 08 : 00
[INFO] Final Memory: 18M/64M
[INFO] ------------------------------------------------------------------------

编译生成一个新的class文件: SlimFormatter.class 
编译结果class文件

mvn compile命令没有生成新的smartrics-RestFixture-3.1-SNAPSHOT.jar

所以需要修改 http://localhost:8001/RestFixtureInstallTest?

1
2
3
!path D:\git\FitnesseKit\RestFixture\target\smartrics-RestFixture- 3.1 -SNAPSHOT.jar
-->
!path D:\git\FitnesseKit\RestFixture\target\classes

再次运行测试用例 http://localhost:8001/RestFixtureInstallTest:

测试结果显示正确

耶!太完美了。

到此结束了吗?显然没有,接下去要执行 mvn package,打包生成smartrics-RestFixture-3.1-SNAPSHOT.jar。

修改单元测试代码并打包RestFixture

执行mvn package命令打包:?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
D:\git\FitnesseKit\RestFixture>mvn package
Results :
...
Failed tests:   shouldDisplayPassOnCheckIfExpectedAndActualMatch_whenDisplayingActual(smartrics.rest.fitnesse.fixture.SlimFormatterTest): (..)
   shouldDisplayPassOnCheckIfExpectedAndActualMatch(smartrics.rest.fitnesse.fixture.SlimFormatterTest): (..)
   shouldDisplayXmlDataInActual(smartrics.rest.fitnesse.fixture.SlimFormatterTest): (..)   
...
Tests run: 264 , Failures: 3 , Errors: 6 , Skipped: 0
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 14.866 s
[INFO] Finished at: 2014 - 08 -03T19: 32 : 44 + 08 : 00
[INFO] Final Memory: 18M/133M
[INFO] ------------------------------------------------------------------------
...

打包时,执行单元测试时,有3个测试失败。 
shouldDisplayPassOnCheckIfExpectedAndActualMatch_whenDisplayingActual函数在文件D:\git\FitnesseKit\RestFixture\src\test\java\smartrics\rest\fitnesse\fixture的第70行:?

1
2
3
4
5
6
7
public void shouldDisplayPassOnCheckIfExpectedAndActualMatch_whenDisplayingActual() {
     SlimCell c = new SlimCell( "something matching logically abc123" );
     ...
     assertThat(
             c.body(),
             is(equalTo( "pass:something&nbsp;matching&nbsp;logically&nbsp;abc123<br/><i><span class='fit_label'>expected</span></i><hr/><br/>abc123<br/><i><span class='fit_label'>actual</span></i>" )));
}

按照之前代码的修改,pass:xxx应改成pass:<span>xxx</span> 
assertThat语句对应修改为:?

1
2
3
assertThat(
             c.body(),
             is(equalTo( "pass:<span>something&nbsp;matching&nbsp;logically&nbsp;abc123<br/><i><span class='fit_label'>expected</span></i><hr/><br/>abc123<br/><i><span class='fit_label'>actual</span></i></span>" )));

再次执行mvn package,报告失败测试用例数为2个,说明修改正确。

继续修改另两个失败的测试用例,

  • 执行mvn package,报0个失败,6个错误,BUILD FAILURE。
  • 执行mvn clean package,报0个失败,0个失败,BUILD SUCCESS,smartrics-RestFixture-3.1-SNAPSHOT.jar生成了新版。

具体的修改内容可以到git中查看对应commit:

 

不知道什么原因,反正修改代码后,再次编译RestFixture时总是用mvn clean package就行了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值