• 测试技术
  • 博客
  • 视频
  • 开源
  • 论坛
  • 沙龙
  • 下载
  • 杂志
  • 招聘

字号: | 推荐给好友 上一篇 | 下一篇

对 Ajax 应用程序进行单元测试

发布: 2008-4-03 17:20 | 作者: Andrew Glover | 来源: IBM | 查看: 76次 | 进入领测软件测试网论坛讨论

领测软件测试网

A/U!k0@ t(Q软件测试技术门户^H C3p0TF
软件测试技术门户,Uf ?0wp%Jb

分解业务逻辑和 UI 代码

e"By_ Z 软件测试技术门户'rI%k%k0C/x1^ z D

第一步是为每个 UI 组件创建访问器方法,如清单 2 所示。按照该方式,我可以在需要时获取它们。

x!cyB m:A4a4M软件测试技术门户$@ r9ro Ax dZ0jS#[
清单 2. 向 UI 组件添加访问器方法使其可用
T6UgE`av_B|m
                public class WordModule implements EntryPoint {  private Label label;  private Button button;  private TextBox textBox;  private Label outputLabel;    protected Button getButton() {   if (this.button == null) {    this.button = new Button("Submit");   }   return this.button;  }  protected Label getLabel() {   if (this.label == null) {    this.label = new Label("Word: ");   }   return this.label;  }  protected Label getOutputLabel() {   if (this.outputLabel == null) {    this.outputLabel = new Label();   }   return this.outputLabel;  }  protected TextBox getTextBox() {   if (this.textBox == null) {    this.textBox = new TextBox();    this.textBox.setVisibleLength(20);   }   return this.textBox;  }}

^5o)sKzO*M-e"n 软件测试技术门户g6Q_H:wo+q

现在我实现了对所有与 UI 相关的组件的编程式访问(假设所有需要进行访问的类都在同一个包内)。以后我可能需要使用其中一种访问进行验证。我现在希望限制 使用访问器,如我已经指出的,这是因为 GWT 并非设计用来进行交互测试。所以,我不是真的要试图测试某个按钮实例是否被单击,而是要测试 GWT 模块是否会对给定的单词调用服务器端代码,并且服务器端会返回一个有效定义。方法为将 onModuleLoad() 方法的定义获取逻辑推入(不是故意用双关语!)一个可测试方法中,如清单 3 所示:

#s4Y,A&g2H4s软件测试技术门户U0^ ?1Wlto0G(T
清单 3. 重构的 onModuleLoad 方法委托给更易于测试的方法
b2^gzh ?%~N
                public void onModuleLoad() {  HorizontalPanel inputPanel = new HorizontalPanel();  inputPanel.setStyleName("disco-input-panel");  inputPanel.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);  Label lbl = this.getLabel();  inputPanel.add(lbl);  TextBox txBox = this.getTextBox();  inputPanel.add(txBox);  Button btn = this.getButton();  btn.addClickListener(new ClickListener() {   public void onClick(Widget sender) {     submitWord();   }  });  inputPanel.add(btn);  inputPanel.setCellVerticalAlignment(btn,      HasVerticalAlignment.ALIGN_BOTTOM);  if(RootPanel.get("input-container") != null) {   RootPanel.get("input-container").add(inputPanel);  }  Label output = this.getOutputLabel();  if(RootPanel.get("output-container") != null) {   RootPanel.get("output-container").add(output);  }}
软件测试技术门户0R:t^%B+u8G]q8ld3h
软件测试技术门户fzy8A6A |(he rKo

如清单 3 所示,我已经把 onModuleLoad() 的定义获取逻辑委托给 submitWord 方法,如清单 4 定义:软件测试技术门户%ah,aKiv+@#w


za2tB tf清单 4. 我的 Ajax 应用程序的实质!
c w~V3Z6A:C
                protected void submitWord() {  String word = this.getTextBox().getText().trim();  this.getDefinition(word);}protected void getDefinition(String word) { WordServiceAsync instance = WordService.Util.getInstance(); try {   instance.getDefinition(word, new AsyncCallback() {   public void onFailure(Throwable error) {    Window.alert("Error occurred:" + error.toString());   }   public void onSuccess(Object retValue) {    getOutputLabel().setText(retValue.toString());   }  }); }catch(Exception e) {   e.printStackTrace(); }}

P\9LI ~A 软件测试技术门户2}`gH ^$D.j

submitWord() 方法又委托给 getDefinition() 方法,我可以用 JUnit 测试它。getDefinition() 方法从逻辑上独立于特定于 UI 的代码(对于绝大部分而言),并且可以在没有单击按钮的情况下得到调用。另一方面,与异步应用程序有关的状态问题和 Java 语言的语义规则也规定了我不能在测试中完全 避免与 UI 相关的交互。仔细查看清单 4 中的代码,您能够发现激活异步回调的 getDefinition() 方法操纵了某些 UI 组件 —— 一个错误警告窗口以及一个 Label 实例。

N p}8Ng["W

$Y(dK`SC7H我还可以通过获得输出 Label 实例的句柄,断言其文本是否是给定单词的定义,从而验证应用程序的功能。在用 GWTTestCase 测试时,最好不要 尝试手工强制改变组件状态,而应该让 GWT 完成这些工作。举例而言,在清单 4 中,我想验证对某个给定单词返回了其正确定义并放入一个输出 Label 中。无需操作 UI 组件来设置这个单词;我只要直接调用 getDefinition 方法,然后断言 Label 具有对应定义。

fQ0@g9D$r,Y

%non7Nhlp3K既然我已经编写好了计划进行测试的 GWT 应用程序,我需要实际编写测试,这意味着设置 GWT 的 GWTTestCase

q^6YkL9n8d e软件测试技术门户PT Q`H

}3L