首页 > 代码库 > Scenario:模块化定义Fitnesse测试用例的能力和局限

Scenario:模块化定义Fitnesse测试用例的能力和局限

首先普及一下概念,什么是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

《实例化需求》中关于Fitneese的描述:

FitNesse套件(活文档)覆盖的所有功能,通过了完整的系统测试和用户验收测试,在生产环境上线时也没有发现任何缺陷。系统测试时发现了几个核心计算组件以外的错误。业务人员之所以觉得用户验收测试非常好,是因为出现计算错误时,我们都非常确定根本问题是在计算代码的上游。使用了FitNesse后,很容易诊断出缺陷的根源,从而可以更加利落快速地交付到生产环境中。

原文链接:http://www.douban.com/group/topic/35316487/

1.Scenario是什么

Fitneese的SliM UserGuide中介绍了 Scenario

原文是这么介绍Scenario的:

A Scenario table is a table that can be called from other tables; namely Script Table and Decision Table.

The format of a Scenario table is the same as the format of a Script Table, but with a few differences. You can see a Scenario table in action here.

Scenario是一种Table,可以被Script Table 和 Decision Table调用。

由此很多人都对Scenario报了很大的期望,希望能用Scenario模块化封装测试步骤。

2.Scenario能力展示

下面是我结合Script示例和Scenario示例写的一个Scenario演示用例:

wiki文本:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
!define TEST_SYSTEM {slim}
!path classes
 
|import|
|fitnesse.slim.test|
 
!4 定义scenario checkLogin: 登录并检查结果
| scenario | checkLogin | u || p || ensure || logged |
| @{ensure} | login with username | @{u} | and password | @{p} |
| check @{logged} | login message | @{u} logged in. |
| show | number of login attempts |
 
!4 创建script实例,后面调用scenario都是针对这个实例
| script | login dialog driver | Bob | xyzzy |
 
!4 Invoking a scenario from a !-DecisionTable-!
| checkLogin |
| u | p | ensure | logged |
| Bob | xyzzy | ensure |  |
| Bob | zzyxx | reject | not |
| Cat | xyzzy | reject | not |
 
!4 Invoking a scenario from a !-ScriptTable-!
| script |
| checkLogin | Bob || zzyxx || reject || not |
| checkLogin | Bob || xyzzy || ensure ||  |
 
!4 script原示例
| script | login dialog driver | Bob | xyzzy |
| login with username | Bob | and password | xyzzy |
| check | login message | Bob logged in. |
| reject | login with username | Bob | and password | bad password |
| check | login message | Bob not logged in. |
| check not | login message | Bob logged in. |
| ensure | login with username | Bob | and password | xyzzy |
| note | this is a comment |
| show | number of login attempts |
| $symbol= | login message |
 
The fixture for this table is:{{{public class LoginDialogDriver {
  private String userName;
  private String password;
  private String message;
  private int loginAttempts;
 
  public LoginDialogDriver(String userName, String password) {
    this.userName = userName;
    this.password = password;
  }
 
  public boolean loginWithUsernameAndPassword(String userName, String password) {
    loginAttempts++;
    boolean result = this.userName.equals(userName) && this.password.equals(password);
    if (result)
      message = String.format("%s logged in.", this.userName);
    else
      message = String.format("%s not logged in.", this.userName);
    return result;
  }
 
  public String loginMessage() {
    return message;
  }
 
  public int numberOfLoginAttempts() {
    return loginAttempts;
  }
} }}}

测试用例页面:

测试用例页面

点击Test执行后:

执行结果

展开DecisionTable调用Scenario的测试结果:

DecisionTable调用Scenario

展开ScriptTable调用Scenario的测试结果:

ScriptTable调用Scenario

至此,我们看到Scenario可以把Script步骤封装起来,取个模块名,然后使用DecisionTable或ScriptTable调用。

3.Scenario的局限

请注意调用Scenario前的这一行:

创建Script实例

目的是在调用Scenario前先创建好Script实例。

如果去掉这一句,再执行,是这样的结果:

没有Script实例测试结果

再尝试一下,把创建Script实例的语句塞到Scenario中:

?
1
2
3
4
5
6
!4 定义scenario checkLogin: 登录并检查结果
| scenario | checkLogin | u || p || ensure || logged |
| script | login dialog driver | Bob | xyzzy |   <--这是新加的创建Script实例的语句
| @{ensure} | login with username | @{u} | and password | @{p} |
| check @{logged} | login message | @{u} logged in. |
| show | number of login attempts |

保存后执行测试:

无法测试

4.不满意怎么办?

我还想使用Scenario封装TableTable,比如RestFixture定义的TableTable, 
国外最著名的软件开发问答网站stackoverflow.com也在问: 
Can I make a scenario of RestFixture table in fitnesse?, or is there another way to make reusable components?

stackoverflow

我准备修改Fitneese代码,使得Scenario能直接封装ScriptTable和TableTable,请关注后续博客……