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.

Tuesday, March 16, 2010

Programming by intention in automated test case part1

Today, I like to write a little bit about coding. Specifically about writing automated test cases like in test frameworks.

There is a technique called programming by intention. I came across this term for the first time from netobjectives.com. I'm not sure it is a well-known term or not. But, the idea about this technique is pretty strong and effective. There are many benefits you can get by doing this. I'll mention about these benefits later.

My understanding of this technique is to lay out the steps or process first and finish implementation later. This keeps your thinking process and coding staying on track. It is like writing a pseudo code, but it is writing actual codes. I guess the best way to explain this technique is using example.

Let's say you are writing a function called 'whatTypeOfTriangleIsThis(int a, int b, int c)' and this will return some numeric value representing certain type of triangle. If you write this in one function, you will have to use a lot of if statements. And you will keep thinking about cases to cover. But soon yon can figure out how to group them and handle them in each group, that's the idea. Let me lay out the steps

1. Are inputs valid? If not -1
2. Can inputs make triangle? If not -1
3. Is this equilateral? If yes 1
4. Is this isosceles? If yes 2
5. Is this scalene? If yes 3

I could write this function like

public int whatTypeOfTriangleIsThis(int a, int b, int c){
if(!areInputsValid(a,b,c) || !canInputsMakeTriangle(a,b,c))
return -1;

if(isThisEquilateral(a,b,c))
return 1;
else if(isThisIsosceles(a,b,c,))
return 2;
else return 3;
}


Now I go back to each private method and implement the rest.

I'll comeback for more explanation.
Bye.








Monday, March 15, 2010

Software Testing - mindset

I've been working as a test engineers for a few years. And if someone ask me "what is the most important thing for test engineers have to have?", I would say it is the mindset. What differentiates test engineers from development engineers? What are the things we(test engineers) are specialized in?

If you cannot answer those questions, you need to read the rest.

To answer those questions, I need to talk about bugs. What is a bug? Who writes a bug? We all know that there is no bug free software. Yes, we are humans and we make mistakes. Developers cannot write bug free code.

From my experience, there are two kinds of bugs. The first one is the mistake developers make while they are writing codes. He/she coded incorrectly and the code does not work the way it should. The other one comes when they miss some possible situations. He/she did not handle null case or did not handle really big input or did not handle negative value and so on.

The first is normally straight forward. We can easily get all the possible permutations or possible expectations from the spec or the context. I think the latter is the part we(test engineers) are specialized in. Possible situation is not about inputs for some functions. It's about considering all the possibilities that will affect the application. We are so good at figuring out what those pieces of code or thousands lines of code will face. We are also good at prioritizing the situation in terms of business perspective and software development perspective.

A good developer is capable of writing good code in any kind of application, environment or language.

A good test engineer is capable of coming up with good possible situations whether it is one method, components, client applications, web applications or enterprise applications.

Going back to mindset.
Test engineer's job is not making sure the application works as spec states. It's about understanding the aspects of the development process and figuring out important situations that the application will come across.