Wednesday, July 30, 2008

Have you tested your code ?

As I work daily, I am beginning to understand the difference between a programmer and a Development Engineer. How many times would you have written a test module for the API that you just coded ? AFAIK, it only used to be a manual testing to check whether everything is working fine. Let me take you to a new domain...lets call it the 'TestDomain' :-)

In a typical S/W company, you tend to write code that satisfies some business logic. It's no longer finding out the shortest path or the MST :-). The code might involve retrieving values from databases, usage of web services, etc. Hence, each module needs to be tested. To our rescue, comes a nice neat package "JMock" !Astounded by its power, I just love writing test cases now :-).

So, what is this JMock all about ?
JMock is a library that allows you test Java code with the help of mock objects.

Mock object ? Enlighten me pl.
Hmmm.... Say you need to test a module, Module 1

Module 1

class Module1{
Webservice service;

String ipAddr;
public setService(Webservice serv){
service = serv;
}

public String getIpAddr(){
return ipAddr;
}

public void function(){
ipAddr = service.getIPAddr();


if( ipAddr == blah...blah... ){

set ipAddr value = "val";

}
else {
throw Exception
}
}
}
There are 2 ways to test this module.
  • Initializing the service and checking whether the ipAddr value has been set or an exception is thrown
  • Mocking the service
We are here to discuss the 2nd point. Instead of initializing the service and making the call heavy, instead you can mock the service object, (i.e) JMock allows you to create a "mock" WebService object which to the Java code will look like a WebService object.

Still hazy :(
Basically, instead of hitting the service, you try to define how the service object will work given a set of parameters. To put it crudely, it essentially means, you are trying to override the WebService functions when passed with a specific set of parameters.

Nice :-), Eg?
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.jmock.integration.junit4.JMock;
import org.jmock.integration.junit4.JUnit4Mockery;

@RunWith(JMock.class)
class PublisherTest {
Mockery context = new JUnit4Mockery();

/* I am mocking the webservice object here */

final WebService webservice = context.mock(WebService.class )

/* Don't panic! Its simple :-) All I am asking it to do is, when the webservice object
calls the getIpAddr() function, DO NOT call the service, instead return the value I have specified */

context.checking(new Expectations() {{
one (webservice).getIpAddr();
will(returnValue("127.0.0.1");
}});

Module1 moduleObject = new Module1();

/* Set the service used to be the mock object :-) */
moduleObject.setService(webservice);

/* When I invoke this, the original service isn't called, the mock object takes over*/
moduleObject.function();

/* Assert statments follow here */
Assert.assertNotNull(moduleObject.getIpAddr());

}

src: jmock.org

Well JMock is a huuuuuuge library with so many functions and you can keep playing around with it. With this knowledge, you can go through the cheatsheet and get greater power. And ofcourse, I am always right here to help you out with anything related to JMock :-), anything :-)

Btw, I forgot to tell you something, NatPryce replies to mail like a lightning! Till date, he has sent me about 10 mails!!

Who is NatPryce ?
Go figure it out :P

PS: Could someone pl. tell me how to indent code snippets! The blogspot "Edit Post" tab is a piece of shit!!

Tuesday, July 29, 2008

Java vs C++

Life at Amazon.com has been pretty good except for a few intricately hidden bugs which at times are difficult to swat! Here's one nice bug, oops! (no pun intended) I wouldn't call it a bug. Fully geared up for the task given to me this morning, the keyboard had a bad day until I had to do a swap...

Well, what's there in a swap after all ? Just out of college, you do tend to show a lot of gimmicks, don't you ? I too, am a faithful follower of the policy and wrote

x^=(y^=(x^=y)); where x,y are integers.
Now, compile successful, build successful, Yaaaaaaaaay!!! - it's a 1000 line code, so the celebration kind of justified :-). But wrong answer :-(
So, I get down to the debugging stage, I do a

while( 1 ) { debug; }


After spending a lot of time (no way, am going to tell you how much I spent :P), I realised, there was a bug in my swap code!!. Can you imagine ? It was such a common question, almost appeared in every single CS written paper. But, this is Java dear :-)

Googling Java specifications lead me to a new finding:
"A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)), where T is the type of E1, except that E1 is evaluated only once"

Hence, whatever assignment happens in (x^=y) has almost nil effect w.r.t this statement!!!! This one-liner won't work

To be more precise, C++ rule states
"A compound assignment expression of the form E1 op= E2 is equivalent to E1 = (T)((E1) op (E2)), where T is the type of E1"

Step 1: x = x^y;
Step 2: y = y ^ ( x^y) = x;
Step 3: x = ('x' computed from Step1) ^ (y computed from Step2 ) =
= (x ^y)^x
=y

PS: I could have definitely explained it better using opcodes, but I want to keep it as simple as possible. As long as the meaning is conveyed, I am happy :-)

Let's see what Java does
Step 1: x = x^y;
Step 2: y = y ^ ( x^y) = x;
Step 3: x = (x) ^ (y computed from Step2 ) =
= x^x
= 0

This result is attributing purely towards the wicked statement at the end :-)

At the EOD, I said "Thank God, there are no #defines in Java, God knows how many gimmicks I would have shown with that and how many screeching bugs would have been inside!!"

I want to look at the bytecodes generated, googling how to look at it now:-). My 1st lesson, well learnt :D