Sunday, March 28, 2010

Programming by intention in automated test case part2

Hello,

In part1, I explained what is programming by intention technique is and showed one example. Now, we can move to automated test cases.

As you might guess, automated test cases are set of instructions. There are steps to go through until it reaches assertions. By using programming by intention technique, we can represent each step with a private method. Maybe making all the steps with private methods will not be possible, but you can make distinction pretty clearly. One benefit comes from doing so is that you can extract private methods that are used many places in your test framework and make them helpers or utility methods. Therefore, you can call helper methods instead of the function you defined in your test case, which make re-factoring pretty convenient for you.

Let's take a look at one simple test case in web application. You are testing a user changing his/her profile info in your application (birth day), and you are using some sort api that handles browser navigation(i.e. selenium).

Let me write how code looks like without using the technique

public void testProfileBirthdayChange(){

// creating a new selenium client instance
Selenium selenium = new DefaultSelenium(...,..,.,); selenium.start();
selenium.open("/");

// login
selenium.type(....email..);
selenium.type(.. password..);
selenium.click(...login button..);
selenium.waitForPageToLoad(...);

// go to profile page and change birthday
selenium.open(..profile page..);
selenium.click(.. profile change button); selenium.waitForPageToLoad(...);
String year = "1960";
String month = "09";
String day = "29";
selenium.type(.. year of birthday);
selenium.type(.. month of birthday);
selenium.type(.. day of birthday);
selenium.click(..save button);
selenium.waitForPageToLoad(...);

// move to home page again and come back to profile page selenium.open("/");
selenium.click(..profile page link);

// assert for changed birthday
assertTrue(selenium.getValueOf(birth year).equals(year)); assertTrue(selenium.getValueOf(birth month).equals(month)); assertTrue(selenium.getValueOf(birth day).equals(day)); }


This example is pretty easy and clear enough for you to change later. Let's see how this simple test case becomes simpler.

public void testProfileBirthdayChange(){
Selenium selenium = SeleniumHelper.getDefaultSelnium();

// log-in
login(selenium);

// go to profile page and change the birthday
String year = "1960";
String month = "09";
String day = "29";
changeBirthdayOnProfilePage(selenium, year, month, day);

// move to home page again and come back to profile page
goHomepageAndComebackToProfilePage(selenium);

// assert for changed birthday
assertTrue(selenium.getValueOf(birth year).equals(year));
assertTrue(selenium.getValueOf(birth month).equals(month));
assertTrue(selenium.getValueOf(birth day).equals(day));
}

Then you can go implement the private methods. You can create birthday random as well. The point is you can easily see the each step more clearly than previous one. And also some private methods might be used again in other test cases. You can extract login() method to be helper method because most of the web application requires login. If you have more and more steps to do, this technique help you keep track of your steps more easily. Also you can apply development change more flexible way. If just simple buttons or id name changes, you do not have to touch your steps, you can only change the implementation. If step changes, you can easily find where the new step needs to go because long implementation for each steps are in the private method.

No comments: