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.
Software testing, just like other disciplines, requires deep understanding, practice and learning to be an expert. Let's see how far this journey goes.
Sunday, March 28, 2010
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.
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.
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.
Saturday, January 2, 2010
A string Permutations
This might be a good example of recursion.
So one example question would be:
Print all permutations of a given string. (i.e. "abc" would print "abc", "acb", "bac", "bca", "cab", and "cba")
I start thinking about patterns in terms of recursion.
1. There should be a base case and a recursive case.
2. For recursive case, I need to call the same function with sub version of original string.
3. Let's call the function name "printPermutation()".
4. The pattern I came up with is the following
if(current.length() == 1){
System.out.println(parent+current);
return;
}
6. Oh now, I need a simple function takes an index and a string. It will remove the character(index) from given string.
public static String removeCharAt(int index, String str) {
return str.substring(0, index) + str.substring(index + 1);
}
7. then recursive part would look like
for(int i =0; i <current.length(); i++)
printPermutation(removeCharAt(i, current), parent + current.charAt(i));
}
8. Following is my solution
public static void printPermutation(String current, String parent){
if(current.length() == 1){
System.out.println(parent+current);
return;
}
for(int i =0; i printPermutation(removeCharAt(i, current), parent + current.charAt(i));
}
}
public static String removeCharAt(int index, String str) {
return str.substring(0, index) + str.substring(index + 1);
}
What do you think?
So one example question would be:
Print all permutations of a given string. (i.e. "abc" would print "abc", "acb", "bac", "bca", "cab", and "cba")
I start thinking about patterns in terms of recursion.
1. There should be a base case and a recursive case.
2. For recursive case, I need to call the same function with sub version of original string.
3. Let's call the function name "printPermutation()".
4. The pattern I came up with is the following
- Go through the String from index 0 to index length -1
- And then take the character at index i and call printPermutation() with rest of the string
- Let's take a look at example string "abc"
- My logic is when index is at 'a' and call printPermutation() with "bc" and when index is at 'b' call printPermuation() with "ac" and so on.
- So the string will eventually become size of 1 then print all and return (this seems like base case)
- Then when the function takes size of 1 string, it needs to know what is the parent string is.(sort of path the function is taken)
- OK... So I wrote printPermutation() with two parameters: printPermutation(String current, String parent);
if(current.length() == 1){
System.out.println(parent+current);
return;
}
6. Oh now, I need a simple function takes an index and a string. It will remove the character(index) from given string.
public static String removeCharAt(int index, String str) {
return str.substring(0, index) + str.substring(index + 1);
}
7. then recursive part would look like
for(
}
8. Following is my solution
public static void printPermutation(String current, String parent){
if(current.length() == 1){
System.out.println(parent+current);
return;
}
for(int i =0; i
}
}
public static String removeCharAt(int index, String str) {
return str.substring(0, index) + str.substring(index + 1);
}
What do you think?
Thursday, December 31, 2009
Share the ideas about programming
New year's resolution? Yes..
It is a very fortunate thing that you are doing what you like to do everyday. If your job is doing what you are passionate about, you are absolutely a successful man. I'm a Software Test Engineer or Software Development Engineer in Test. Whatever it is I love what I'm doing everyday at work. I get excited when I put my finger on the keyboard.
Then what is my resolution for this year?
I like to share ideas with the world about solving programmatic problems. Nothing fantastic about this. Any topic. Testing, Algorithm, Data structure, Design patterns, puzzles whatever. I'll try and see how this will looks like on next new year's day.
Today?
Some problem I recently solved by searching internet.
Starting a Selenium server with Firefox profile to get around certificate issue:
The problem was:
"When I run a selenium test against test machine within a network, Firefox keep asking for certificate."
Here is the solution
1. start a firefox with -profileManager (i.e. c:/>firefox -ProfileManager)
2. create a new profile and start the firefox
3. go to any https://..... page on test machine which requires the certificate.
4. close the firefox and go to profile page which is located something like "user/Application Data/Mozilla/Firefox/profiles ...."
5. go to newly created profile folder and copy cert_override.txt and cert8.db to certain folder (i.e. c:/testMachine1Certs)
6. Start Selenium server with following code
RemoteControlConfiguration rcc = new RemoteControlConfiguration();
rcc.setFirefoxProfileTemplate(new File("c:\\testMachineCerts"));
server = new SeleniumServer(rcc);
server.start();
7. Now you don't have certificate problem any more~~
It is a very fortunate thing that you are doing what you like to do everyday. If your job is doing what you are passionate about, you are absolutely a successful man. I'm a Software Test Engineer or Software Development Engineer in Test. Whatever it is I love what I'm doing everyday at work. I get excited when I put my finger on the keyboard.
Then what is my resolution for this year?
I like to share ideas with the world about solving programmatic problems. Nothing fantastic about this. Any topic. Testing, Algorithm, Data structure, Design patterns, puzzles whatever. I'll try and see how this will looks like on next new year's day.
Today?
Some problem I recently solved by searching internet.
Starting a Selenium server with Firefox profile to get around certificate issue:
The problem was:
"When I run a selenium test against test machine within a network, Firefox keep asking for certificate."
Here is the solution
1. start a firefox with -profileManager (i.e. c:/>firefox -ProfileManager)
2. create a new profile and start the firefox
3. go to any https://..... page on test machine which requires the certificate.
4. close the firefox and go to profile page which is located something like "user/Application Data/Mozilla/Firefox/profiles ...."
5. go to newly created profile folder and copy cert_override.txt and cert8.db to certain folder (i.e. c:/testMachine1Certs)
6. Start Selenium server with following code
RemoteControlConfiguration rcc = new RemoteControlConfiguration();
rcc.setFirefoxProfileTemplate(new File("c:\\testMachineCerts"));
server = new SeleniumServer(rcc);
server.start();
7. Now you don't have certificate problem any more~~
Subscribe to:
Posts (Atom)