Friday, February 24, 2012

I Am On Fire with Testability - Part 1

I've been taking some time off building out features to focus on reducing the unit testing debt we have in our codebase, and along the way build out some core testing infrastructure to make it easier to sustain building out tests in concert with features (imagine that). Some great lessons have been learned, notably about making code testable (see previous post).

Along this journey, the ASP.Net MVC framework that we use has turned out to be one of the more elegant bodies of software I have used in a while, but I didn't really appreciate that until I tried testing code in it's context. The main principal at play here is that in MVC you are always using an abstraction/wrapper over the core ASP.Net classes. You don't have to use them (apparently if you are dumb or a sucker for pain) since you can always reference HttpContext.Current and do whatever you want to.

Light Painting With Fire

Long story short, whenever we bypassed the framework (and it's abstractions), we paid dearly. It turns out the MVC framework was designed with testability in mind, so if you go with the flow (man) you get to inherit that for free. It took a fair amount of refactoring to make sure nobody was touching ASP.Net constructs directly. Let's just say that I had to checkout 100+ files to remedy the situation.

Moral Of The Story: never reference HttpContext.Currentever ever ever. While this ASP.Net convenience function is handy and reliable, it makes your code inherently untestable. Why? Because it can't be mocked, and if it can't be mocked, it cannot be unit tested.

So what is a coder to do?  Every Controller and View has a Context (ControllerContext and ViewContext respectively).  These provide accessors to an HttpContext that derives from HttpContextBase which is an Abstract and thus mockable class.  So, if you want to work with the Request - ControllerContext.HttpContext.Request (or, even more conveniently the BaseController has a shortcut - HttpContext.Request).  Similarly, in Views you can reference the a Session like so: ViewContext.HttpContext.Session.  Neato peachy keen and a boon to testability!

So what do you need to do to fully mock the MVC application? We found all sorts of snippets of code around the intertubes that did this and that, even some attempts and a full blown mocking framework for MVC. Your mileage may vary with any of these, but at the core there are a few things you need to know. First off, you need to be able to take control of the

  • HttpSession
  • HttpRequest
  • HttpResponse

Everything pretty much pivots around these main classes. You have some choices to make about the "how" of mocking as well. You can use Mock Objects or Stubs.  Your choice depends on how much control you want over the objects themselves.  We use Moq which is pretty powerful in that it can Mock almost anything and you can add dynamic behaviors to objects with relative ease.  That said I like to mix in Stub (or pretend) objects that mimic real behavior.  For example, I want to Mock the HttpSession, which is a pretty dumb object (not a lot of logic) but it does have a storage mechanism.  By simply extending the Abstract base class, I can mimic real Session level storage.

public class MockHttpSession : HttpSessionStateBase
    {
     readonly Dictionary<string, object> _sessionStorage = new Dictionary<string, object>();

        public override object this[string name]
        {
            get
            {
                if (_sessionStorage.ContainsKey(name))
                {
                    return _sessionStorage[name];
                }
                return null;
            }
            set { _sessionStorage[name] = value; }
        }

        public override void Remove(string name)
        {
            if (_sessionStorage.ContainsKey(name))
            {
                _sessionStorage.Remove(name);
            }
        }
    }

Then I can use a real Mock and have it leverage this Stub
var Session = new MockHttpSession();
var Context = new Mock<HttpContextBase>();
Context.Setup(ctx => ctx.Session).Returns(Session);

At test setup time, I can set variables in the session storage, and the executing code is none the wiser.

For simple property set/get you can just leverage Moq's SetupAllProperties functionality. This will mimic the basic get/set on the object so that you can get/set on them without having to create a stub or define the dynamic functionality at setup. EG:

var Cache = new Mock<HttpCachePolicybase>();
Cache.SetupAllProperties();

So what does it look like to mock everything at once?  More on that in Part 2.

Friday, February 17, 2012

Test-Enabled Development

I'm going to coin a phrase that for me captures a more realistic and achievable form of development than Test-Driven Development (TDD). TDD is nice, in theory and I'm happy for those who are capable of truly executing on it. The reality for me has been that even in "green field" development projects where you are coding fun new things, the feature development quickly moves past the tests for said features. For the purists out there, yes this is an affront to Scrum (which I portend to follow), TDD and perhaps even good engineering discipline. However, many developers don't code for aesthetic reasons, they code to make products that serve customers which hopefully make money for them.

Fish, chillin'

So if we accept reality and the imperfections in process that tend to occur, how can we as quality-conscious developers still "do the right thing"?  My contention is that we can follow the practice of Test-Enabled Development (TED).

The principal of TED is that regardless of when you test your code, your code must be testable. More on what that entails shortly. The key point is that your code may be tested prior to impelementation (if you are a saint), during implementation (if you are pretty good) or after the fact (if you are lazy/under pressure to deliver). In all cases, your code should be amenable to testing.

So what characterizes code that is testable? In the world of strongly-typed languages like Java and C# we can do a few things right off the bat:
  • Interface-based programming - ensure all system components are defined with interfaces.  For one thing it encourages design by responsibility, secondly it provides a looser coupling, and most importantly, it allows for mocks, stubs and other chicanery on the testing front.
  • Don't use static references if possible, and avoid stateful behavior - let the state be brought to you.   In other words, mind your own business and let either the caller or some persistent store tell you what state the world is in.  That also encourages looser coupling and lets your tests set up the state/context that they need.
  • Factor code into discrete functions - huge methods that do 100s of things are bad for many reasons but from a testability standpoint they are a higher form of sin.
Bonus Points: use a Dependency Injection framework like Spring, Ninject, Unity, or whatever - then the test code can take control of what is real and what is mocked.

Sound like a lot to do?  It is, but once you get the patterns in place, the goodness is self-replicating and yields dividends down the road.  Further, in the worse case you have a very well architected but untested system, and if there's a rainy day or a sudden influx of engineering discipline you can actually effectively test the software.


    Thursday, December 24, 2009

    Mavenizing your XMLBeans Code Generation

    Automating your Code Generation


    XMLBeans provides a nifty code generator (scomp) that creates Java POJOs to represent XML Schema Types from XSD documents. You can run scomp from the command line, an ant build file, but if you work within the context of Maven projects, I recommend taking advantage of the XMLBeans mojo

    As with most things maven, if you follow the standard conventions, things just work. The trick to setting up your pom.xml to execute your code generation is to fit into the convention, and in this case it is not that difficult.

    Keeping the source around

    I happen to like having the generated source code in the context of my projects, and scomp lets you specify where you want it to place the source it generates. Maven has conventions around the directory structure for your source code, so we need to ensure our source goes to the right place - in this case it would be
    src/generated/java
    Generated code should be "throwaway", in other words we should be able to safely delete it, and run the code generator again. We can specify in our pom.xml that we would like to have the generated sources removed as part of the clean process. We do this by configuring the maven-clean-plugin.
    <plugin>
     <groupid>org.apache.maven.plugins</groupid>
      <artifactid>maven-clean-plugin</artifactid>
      <configuration>
       <filesets>
         <fileset>
          <directory>src/generated/java</directory>
         </fileset>
        </filesets>
      </configuration>
    </plugin>
    
    Now the sources will be cleaned out prior to any code generation.

    Generating the Java Source

    Now we can configure the XMLBeans plugin to do our bidding. First we tell Maven we want it to run at all - the plugin "plugs" itself into the proper lifecycle events in Maven so you don't have to worry about that. Then it's a matter of providing scomp with the appropriate options. Here again there are conventions that are good to follow, for example you may note the schema directory location and the .xsdconfig file location.

    <plugin> 
     <groupid>org.codehaus.mojo</groupid> 
     <artifactid>xmlbeans-maven-plugin</artifactid> 
     <version>2.3.3</version> 
     <executions> 
      <execution> 
       <goals> 
        <goal>xmlbeans</goal> 
       </goals> 
      </execution> 
     </executions> 
     <inherited>true</inherited> 
     <configuration> 
      <schemadirectory>src/main/xsd/MyServiceTypes</schemadirectory> 
      <sourceschemas> 
       <sourceschema>MyType.xsd</sourceschema> 
      </sourceschemas> 
      <xmlconfigs> 
       <xmlconfig implementation="java.io.File">src/main/xsd/xmlbeans.xsdconfig</xmlconfig> 
      </xmlconfigs> 
      <sourcegenerationdirectory>src/generated/java</sourcegenerationdirectory>
      <classgenerationdirectory>${project.build.directory}/generated-classes</classgenerationdirectory> 
      <javasource>1.5</javasource> 
      <nojavac>true</nojavac> 
     </configuration> 
    </plugin>
    

    Overriding the Package Names

    By default, XMLBeans uses the schema namespace as inspiration for creating your Java package names. In some cases this works well, but a schema designer may not take Java developer usability into account when creating XSD documents. For example, you may not appreciate a package name of "com.mylongcompanyname.services.public.purchaseorders.v356", and would prefer something like "com.mylongcompanyname.po". Happily, scomp will grant your wish by honouring any overrides you have defined in an xsdconfig file. In this case, we would create a file (xmlbeans.xsdconfig) with the following content:

    <xb:config xb="http://www.bea.com/2002/09/xbean/config">      
    
     <xb:namespace uri="http://services.mylongcompanyname.com/public/purchaseorders/v356">         
      <xb:package>com.mylongcompanyname.po</xb:package>     
     </xb:namespace>  
    </xb:config>
    

    Gratification

    Now you can run "mvn clean install" on your pom and marvel at the automation you just implemented.