Saturday, October 29, 2011

I Spy with My Little Mockito

Recently I was stuck trying to get some code under test. There was some complex code, with random generating ids, side effects, etc. Generally all the things that make testing hard.

I'm using mockito and I am not familiar with all its features, but I did know that it was supposed to give me the ability to partially mock. So away I went.

Remember this is a very contrived example.

package controller;

public class ComplexClass {

    String someComplexCode() {
        long num = Math.round(Math.random());
        if (num % 2 == 0) {
            return "Even";
        } else {
            return "Odd";
        }
    }

    public String callsComplexCode(){
        String output=someComplexCode();
        return output;
    }
}

This is the code I want to add

package controller;

public class ComplexClass {

    String someComplexCode() {
        long num = Math.round(Math.random());
        if (num % 2 == 0) {
            return "Even";
        } else {
            return "Odd";
        }
    }

    public String callsComplexCode(){
        String output=someComplexCode();
        if("Odd".equals(output)){
            output+=" man out";
        }else{
            output+=" More";
        }
        return output;
    }
}

And here are my tests that I want to run

package controller;

import static org.junit.Assert.assertNotNull;

import org.junit.Test;


public class ComplexClassTest {


    @Test
    public void testCallsComplexCode(){
        ComplexClass complexClass=new ComplexClass();
        String output=complexClass.callsComplexCode();
        assertNotNull(output);
    }

    @Test
    public void testCallsNewComplexCodeEven(){
        ComplexClass complexClass=new ComplexClass();
        String output=complexClass.callsComplexCode();
        assertEquals("Even More",output);
    }

    @Test
    public void testCallsNewComplexCodeOdd(){
        ComplexClass complexClass=new ComplexClass();
        String output=complexClass.callsComplexCode();
        assertEquals("Odd man out",output);
    }

}

As you can see the tests will fail since the output is randomly generated. This is actually a big problem with legacy code. I don't really care right now abut the method someComplexCode and I don't want to refactor it without some tests in place or taking a long time to try to understand it. I just want to add code to callsComplexCode.

What I need is a way of mocking the class that I'm testing. Partial mocks to the rescue.

Partial mocks give us the ability to mock sections of the code and use the actually code for other sections. This allows us to get some of the class under test. In an ideal world we should be able to test everything from public interface, but I have to deal with legacy code and this is a very powerful tool to test my changes.

And here is the new test



package controller;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;

import org.junit.Test;


public class ComplexClassTest {


    @Test
    public void testCallsComplexCode(){
        ComplexClass complexClass=new ComplexClass();
        String output=complexClass.callsComplexCode();
        assertNotNull(output);
    }

    @Test
    public void testCallsNewComplexCodeEven(){
        ComplexClass complexClass=new ComplexClass();
        complexClass=spy(complexClass);
        doReturn("Even").when(complexClass).someComplexCode();
        String output=complexClass.callsComplexCode();
        assertEquals("Even More",output);
    }

    @Test
    public void testCallsNewComplexCodeOdd(){
        ComplexClass complexClass=new ComplexClass();
        complexClass=spy(complexClass);
        doReturn("Odd").when(complexClass).someComplexCode();
        String output=complexClass.callsComplexCode();
        assertEquals("Odd man out",output);
    }

}


Now I have the complex method under control and I can test my code.

Ok, sounds great but what are the drawbacks? Well all the methods to be mocked have to be visible to the test and non final. I wrote before about testing private method and I still tend to think its a bad practice, but I also think as a last resort its OK to use some of these techniques.

There is also a danger here is that we bypass code that really needs to be refactored. One of the reason this code is hard to test is its designed badly.

In the book Working Effectively with Legacy Code, Michael Feathers talks about using sprouts to bypass functionality we don't have the time to understand and growing new clean code in its place or around it. Also if some changes the someComplexCode our test will still pass since we are mocking the behavior. However,  to add some functionality and get that new code under test partial mocks could be a valuable tool.

Thursday, October 7, 2010

He Man Java Haters Club



If you ever watched Little Rascals, you know about the He-Man Woman Haters Club. Well now that there are a billion new languages for the JVM, I'm starting to see another club, the He-Man Java Haters Club, and it has a similar oath. First, I'm not saying Java is the one true language that replaces all others. Learning new languages is important. And its important even if you don't use them right away because it gives you a new way of looking at a problem, a new way of thinking. As Einstien said, "Problems cannot be solved by the same level of thinking that created them."

For instance, after I learned a little Haskell, I think I wrote better methods that didn't have side effects. As much as I would enjoy coding for a while in a Lisp based language, I realize that most of my work involves coding Java and since I am a consultant, most of my future work will also involve Java. So I try to include the essence of it in my programming until I can get a chance to program in it.

Does that make Java stupid or ugly or whatever negative adjective you can think of? The answer is no. Of course it has limitations, so does every language and if you don't see that you are missing the point. Java is an object oriented language, this is where it excels, it has a mature set of tools and a ready source of developers. That is why it is popular for enterprise level programs that need to model a business problem. That is why it works well in implementing the Model in the MVC pattern. It's also why new disruptive websites programs that need to evolve quickly and are starting to be written in other languages.

But hating Java is like hating the hammer because you can't use it as a screwdriver. Mainframe programming is still being used in some big companies. What made it a good tool before is why it is still around. It may have gotten a bad rep for trying to do everything, and it took it awhile to find its niche, but for certain problems it still works well.

So, learn the other languages. Figure out what they do well and add them to your toolbox. But don't do the same thing that the old language did, which is try to do everything with your shiny new tool. Don't be a one tool programmer, because if all you have is a hammer everything looks like a nail.

Saturday, May 15, 2010

The Code is Not a Requirement Document

The other day I got one of the infamous requirements conversations that developers have every so often. It goes like this.

BA - And your change should not affect the existing behavior of the system.
Developer - OK, what is the existing behavior of the system.
BA - UM, look at the code
Developer - So what is the final result so I can look at the code.
BA - UM, look at the code
Developer - What should I tell QA to test
BA - UM, look at the code


The code is not a requirement document. Unless the code is very simple, you cannot effectively tell what the final behavior is because the code is not a final state, it's a state machine. It takes inputs in the form of data and delivers an output. Based on the inputs it can deliver an infinite amount of outputs. This is why we have bugs in our software. We don't intentionally write code that will break, its usually that some input in the software takes us down another path that we didn't expect.

Yes, I will admit that many times this is possible and even probable for a method, maybe for a class, but it doesn't tell us all the interactions of our code. There are a host of interactions, UI, database, middle ware, back-end processes, etc. Add to this the ability of callbacks, dependency injection or manipulation of the data somewhere other than in the code and it quickly gets complex.

Even if I can decipher the code, it might anchor me into a horrible solution. Maybe the code I'm looking at is the worst possible way to solve this particular problem, maybe there are simpler, easier solutions, its hard to step back and look at a problem once I see the current code as the "solution".

I use the analogy of a car in the parking lot. I can tell you a lot about that car, make and model, where it is parked. However, if you ask me to start defining rules of behavior, basically the requirements, I would start to struggle. It would depend on the driver, which way do they drive to work, maybe what time they drive to work. What is the average speed, the maximum? Do they make right turns on red? Do they take the long way, because there is always congestion on the freeway? I would probably get many of the rules right, but that because I know how a car works and some of the driving laws in my area. But if its code that I don't know very well, then all bets are off.

Am I complaining, maybe a little. But I do enjoy working with this level of detail, that why I do this and get paid for it. Its complex and messy and hard, but it's also fun. As much as I enjoy untangling some code, it doesn't tell me what the intent was or what the business is trying to accomplish. Looking at the code to see what the requirements are works in some cases, but most of the time we just need to do the hard work of hashing out what exactly it is we are trying to program.

Thursday, April 15, 2010

Spicy curry for my javascript

I had came across currying when studying functional languages, and I struggled a bit with the concept. I always saw mathematical examples and complex explanations, but never a concrete example of how and why I should use it. Until the other day when I had an Aha moment.

So what is currying? It is a partial application of a function. For example you have a function that takes 2 arguments and you only pass one and wait until later to supply the second argument. This could be on a callback or in a closure.

Its also useful the other way, if you have a function that only takes 1 argument and you want to pass another argument. This is where I had my moment of zen. I was trying to get an event into a DWR callback function. The problem is the function only takes 1 argument supplied by the DWR call.

Since we are using Prototype, I discovered Prototype had a curry function also. By the way here is a good reference book on Prototype. I am starting to find the more I learn about Prototype the more I like it.

Well, enough talking, time for some code. For simplicity, I included the prototype.js in the same directory has my html.
<script type="text/javascript" src="prototype.js"></script>
<script type="text/javascript">
function baseMethod(msg){
    alert(msg);
}

baseMethod("Normal operation");

function wrappedMsg(times,msg){
    for(i=1;i<=times;i++){
        baseMethod(msg);
    }
};
var newBaseMsg=wrappedMsg.curry(2);
newBaseMsg("Curried Operation");
</script>
In the code we have a function that takes only one argument, like the DWR callback function. By wrapping the code I am able to change the behavior of the function and the use the newBaseMsg wherever I would use the DWR callback function.


If you aren't using Prototype don't despair. I found a good link that
explains it very well.
Replacing the prototype function with the curry function will accomplish the same thing.
<script type="text/javascript">
Function.prototype.curry = function() 
{ 
  var method = this, args = Array.prototype.slice.call(arguments); 
  return function() 
  { 
    return method.apply(this, args.concat(Array.prototype.slice.call(arguments))); 
  }; 
}; 
function baseMethod(msg){
    alert(msg);
}

baseMethod("Normal operation");

function wrappedMsg(times,msg){
    for(i=1;i<=times;i++){
        baseMethod(msg);
    }
};
var newBaseMsg=wrappedMsg.curry(2);
newBaseMsg("Curried Operation");
</script>

I think we forget sometimes that JavaScript has many attributes of a functional language that make it very powerful and can provide some elegant solutions to some problems we have.

Tuesday, February 16, 2010

Information Architecture (IA) That Sucks Less

If you have ever went to a site that was hard to use its probably because someone left it up to the developers to make the site "look OK". Often as a web developer on a small team, we don't have the resources of large enterprises. Tasks like usability and design often fall to the developer writing the web pages.

Since I've found myself in this position more than a few times, I decided I could learn a little about these fields that might help me suck less at it. I found a book called . Its a great introduction to Information Architecture (IA),this is a fairly new discipline and there are many views on what an IA is and what it should they be. Are they the designer that focuses on the look and feel or in my case the developer that makes is all work together? It could be creating the content or focusing on usability. In truth its a little of all of this, that's why its so hard. Maybe some of the larger projects would need a formal position, but I think we can go a long way by learning a little ourselves and making the interface of our sites suck less.

Theory of Constraints and The Efficient Programmer

The Theory of Constraints is a management theory that comes from the book The Goal. Basically it says in a process there are a few constraints that limit how fast the whole pipeline works. An example in software development would be waiting on the database team to design the tables or the waiting for BAs to write the requirements. If they are the slowest point then it doesn't matter how fast we code. The book also talks about optimizing points in the process may or may not help the entire process.

Why is this? Imagine a factory floor that produces widgets. The process has to go through 10 machines. One of the machines is 1/2 as slow as the rest. Its obvious that this will result in everything piling up in front of the machine. However, what if some engineers tweaked another machine so it was 2 times as fast. First a backup would occur in front of the machine that comes after the machine that runs faster and the other thing is that the process is not any faster. Since we still have one machine running at 1/2 the speed it doesn't speed up the overall process. The most efficient use of our resources would be to optimize the slow machine.

How does this relate to being an efficient programmer. I've seen efficient programmers get their work done and always try to get more work. Their utilization looks good, everyone comments on how fast they go through the code. However, do they ask questions of the lead who is already swamped. Do they bother other resources that our busy with fixing priority defects, do they do anything to improve the process. In other words are they optimizing their work at the expense of the overall process. In the goal it suggests that it may be better to idle a resource rather than have it pile up backlogs. I'm not suggesting that the person sits and twiddles their thumbs. I'm saying they should be aware of what time and resources they are pulling to get their task done and is pulling those resources away the best for the overall project. Could they work on unit tests or conducting a spike on a new technology, updating documentation or somehow improving the throughput of the entire process instead of a laser beam focus on getting their code done. Could they look at who has the most work and pair program or take some workload off of them. I feel this would be a better use of their time.

Tuesday, November 10, 2009

Keep Your Complexity Out of My JSP View - JSP Functions



The JSTL library comes with built in functions that are very useful. Hopefully these functions meet your needs, but sometimes you need to write your own. Sometimes you might want to expose some static util functions to your page. Well with JSP 2.0 you can write you own.

In my example I'm going to write a debug tag to be able to print out session and request variables. It also gives you a convenient point to set a debug point so you can inspect context variables.

The first thing to do is to write a tld file. This is just like we do for old JSP tags. I put the tld under WEB-INF/tld/ and I will reference that path when I declare it in the JSP page.

Here is my tld file
The main parts are under the function node. There is the name that you will use to call the function, the function-class is the java class that contains the function and the function-signature is the signature of the function. We need to use fully qualified names for the return and parameters.
<?xml version="1.0" encoding="ISO-8859-1" ?>
<taglib xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee web-jsptaglibrary_2_0.xsd"
version="2.0">
<tlib-version>1.0</tlib-version>
<jsp-version>2.1</jsp-version>
<short-name>fnt</short-name>
<uri>http://daneking.blogspot.com</uri>
<description>A debug function</description>
<function>
<name>debugPage</name>
<function-class>
viewhelper.JSPMethodCall
</function-class>
<function-signature>
java.lang.String callFactoryMethod(javax.servlet.jsp.PageContext)
</function-signature>
</function>
</taglib>



Now here is the java code to create a string of the session and request variables. I bolded the call to the implementation of the my method.

package viewhelper;

import java.util.Enumeration;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpSession;
import javax.servlet.jsp.PageContext;

public class JSPMethodCall {

private static final String CR = "<br/>";

private static String printSessionAttributes(HttpSession s,String header){
StringBuffer sb=new StringBuffer(header);
sb.append(CR);
Enumeration e=s.getAttributeNames();
while(e.hasMoreElements()){
String var=(String)e.nextElement();
sb.append(var);
sb.append(" = " + s.getAttribute(var));
sb.append(CR);
}
return sb.toString();

}
private static String printRequestAttributes(ServletRequest r,String header){
StringBuffer sb=new StringBuffer(header);
sb.append(CR);
Enumeration e=r.getAttributeNames();
while(e.hasMoreElements()){
String var=(String)e.nextElement();
sb.append(var);
sb.append(" = " + r.getAttribute(var));
sb.append(CR);
}
return sb.toString();

}
public static String callFactoryMethod(PageContext ctx){
HttpSession session =ctx.getSession();

StringBuffer sb=new StringBuffer(CR + "--- Debug Values ---" + CR);
sb.append(printSessionAttributes(session,"---Session ---"));
ServletRequest servletRequest = ctx.getRequest();
sb.append(printRequestAttributes(servletRequest,"---Request ---"));
return sb.toString();
}

}


And the finally the call from the JSP page. I've bolded the important parts where we call the function and the declaration of the tld page where we defined our function.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib uri="/WEB-INF/tlds/fntags.tld" prefix="fnt" %>


<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Calling Functions</title>
</head>
<body>
<c:set scope="session" var="sessionVar" value="sessionValue"/>
<c:set scope="request" var="requestVar" value="requestValue"/>
This is my function .....
${fnt:debugPage(pageContext)}

</body>
</html>


Many times we get so caught up in the latest widgets and technologies that we don't look at some of the basic things we can do to refactor out som complexity out of our views. Hopefully this is another tool to help you do that.