The Dawn of ZK Application Test Suite:Mimic Library
Hawk Chen, Engineer, Potix Corporation
0.9.0 Freshly
Opening
In agile software development, developers modify their codes frequently for requirement change or refactoring, so they also perform unit test frequently to ensure the software quality. In ZK-based application, the composer which is tightly-couple with ZUL is hard to be unit tested because it is instantiated when a ZUL is requested by a browser. That means testers have to deploy the web application to a server before performing a unit test. But to run a unit test in an application server is time-consuming and could be agile developer's darkest time. Don't be depressed, let me light your path with twilight of ZK Test Suite - Mimic Library.
Introduction to Mimic Library
Mimic library enables the tester to test their composer without starting an application server. Tester can mimic user interactions to applications such as clicking or typing to verify composer's (controller layer) data and logic. It puts your project into a server emulator and provide utility classes to interact components on ZUL.
Limitation
- Functions that depend on the application server cannot work.
- Test cases are run in simulated environment, all functions that requires an application server cannot work properly. (i.e. JNDI, or JTA) If users’ AUT project adopts such container-provided services, they need extra work to make it work normally out of a container, i.e. use Test Double like fake object.
- Cannot test client’s behavior.
- In ZK-based application, some behaviors are handled by browser(JavaScript), e.g. popup menu. As server side is not aware of these behaviors, we cannot verify it from server side.
- Cannot test some visual effects.
Test a CRUD example application
To demonstrate how to test an application with mimic library, we create a simple todo list application. It allows us to add, update, delete, and view todo items. Each item has 3 fields: name, priority, and date.
File:Smalltalk-zats-todolist.png
todo.zul
<listbox id="listbox" rows="4" model="@{win$composer.allTasks, load-after='add.onClick, update.onClick, delete.onClick'}" >
<!-- other components -->
</lisbot>
<!-- other components -->
Item:
<textbox id="itemBox"
value="@{win$composer.selected.name, load-after='listbox.onSelect, add.onClick, update.onClick, delete.onClick, reset.onClick'}" cols="25" />
Priority:
<intbox id="priorityBox"
value="@{win$composer.selected.priority, load-after='listbox.onSelect, add.onClick, update.onClick, delete.onClick, reset.onClick'}" cols="1" />
Date:
<datebox id="dateBox" format="yyyy-MM-dd"
value="@{win$composer.selected.date, load-after='listbox.onSelect, add.onClick, update.onClick, delete.onClick, reset.onClick'}" cols="8" />
<!-- other components -->
Setup
Before writing test cases with mimic library, you have to include zats-mimic.jar and jetty.jar to your project.
Write a Test Case
The steps to write test case are:
- Setup web application content path
- Start a conversation with a ZUL
- Find a component
- Perform an action on a component
- Verify result by checking a component’s state
- Tear down
The test case is to verify composer's logic. In our example application, there are 4 main function: Add, Update, Delete, Reset, the test case verify them one by one.
public class TodoTest {
@BeforeClass
public static void init() {
Conversations.start("./src/main/webapp");
}
@AfterClass
public static void end() {
Conversations.stop();
}
@After
public void after() {
Conversations.clean();
}
@Test
public void test() {
//visit the target page
Conversations.open("/todo.zul");
//find components
ComponentAgent itemName = find("textbox");
ComponentAgent priority = find("intbox");
ComponentAgent date = find("datebox");
//add
itemName.as(TypeAgent.class).type("one-item");
priority.as(TypeAgent.class).type("3");
date.as(TypeAgent.class).type("2012-03-16");
find("button[label='Add'] ").as(ClickAgent.class).click();
//verify each listcell's label
ComponentAgent listbox = find("listbox");
List cells = listbox.getChild(1).as(Listitem.class).getChildren();
assertEquals("one-item",((Listcell)cells.get(0)).getLabel());
assertEquals("3",((Listcell)cells.get(1)).getLabel());
assertEquals("2012/03/16",((Listcell)cells.get(2)).getLabel());
//update
listbox.as(SelectAgent.class).select(0);
//verify select
assertEquals("one-item",itemName.as(Textbox.class).getValue());
assertEquals((Integer)3,priority.as(Intbox.class).getValue());
assertEquals("2012-03-16",date.as(Datebox.class).getRawText());
//modify the todo item
itemName.as(TypeAgent.class).type("one-item modified");
priority.as(TypeAgent.class).type("5");
find("button[label='Update'] ").as(ClickAgent.class).click();
assertEquals("one-item modified",((Listcell)cells.get(0)).getLabel());
assertEquals("5",((Listcell)cells.get(1)).getLabel());
//reset
listbox.as(SelectAgent.class).select(0);
assertEquals("one-item modified",((Listcell)cells.get(0)).getLabel());
find("button[label='Reset'] ").as(ClickAgent.class).click();
assertEquals("",itemName.as(Textbox.class).getValue());
assertEquals((Integer)0,priority.as(Intbox.class).getValue());
assertEquals(true, date.as(Datebox.class).getValue()==null);
//delete
assertEquals(2,listbox.getChildren().size());
listbox.as(SelectAgent.class).select(0);
find("button[label='Delete'] ").as(ClickAgent.class).click();
assertEquals(1,listbox.getChildren().size());
//The following line causes IllegalStateException: Components can be accessed only in event listeners
//find("textbox").as(Textbox.class).setValue("abc");
}
Download
Comments
Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License. |