Showing posts with label unit testing. Show all posts
Showing posts with label unit testing. Show all posts

Tuesday, July 12, 2011

Mock Objects with Spock Screencast

This screencast demonstrates how to use Spock testing specifications and Groovy for mocking and stubbing behavior in unit tests. It covers creating the mock object syntax, setting expectations, verifying and spying on results, and argument matchers.

If you have any issues with video playback, then trying viewing it from the JBrains.tv website

Here are some useful links to read for this webcast:

I've made a lot of screencasts and blog posts over the years. If you like this, then there are many ways to see the other stuff I've done:

Phew, that's a lot of self-promotion :)

The screencast was created with Ubuntu 10.04, PiTiVi, Audicity, gtk-RecordMyDesktop, IntelliJ IDEA, and LibreOffice. OS from top to bottom.

Thanks for watching, and leave a comment!

Friday, April 15, 2011

Getting Started with Spock and Groovy

This screencast demonstrates how to create Spock testing specifications. It covers creating basic when/then blocks, given/when/then blocks, expect/where blocks, and data tables. It explains how to create Spock file templates and Spock Live Templates for IDEA.

If there are any playback issues then you might try watching it from the JetBrains.tv site.



Here are some useful links to read for this webcast:

To work with Spock, I use one file template and three live templates.

My file template creates a Spock Specification with the correct java package and javadoc:

idea file template

The text of the template is:

#if (${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end

import spock.lang.Specification

#parse("File Header.java")
class ${NAME} extends Specification {

}

My first Live Template is the when-then template:

when then

The text of the template is:

def "$NAME$"() {
when:
$END$

then:
true
}

The second template is the given/when/then template:

given when then template

The text of the template is:

def "$NAME$"() {
given:
$END$

when:
// TODO: add when

then:
true
}

The last template is the expect/where template:

The text of the template is:

def "$NAME$"() {
expect:
$END$

where:
// TODO add where block
}

I've made a lot of screencasts and blog posts over the years. If you like this, then there are many ways to see the other stuff I've done:

Phew, that's a lot of self-promotion :)

Thanks for watching, and leave a comment!

Tuesday, December 14, 2010

Mockito – Screencasts for Stubbing, Verifying, and Argument Matching

We're rolling out Mockito and trying to raise our testability at work and I'm set to give a presentation/training session tomorrow to a few new teams. In case you don't know, Mockito is a mock object framework for Java. It's competitors are EasyMock, JMock, and others if you're more familiar with those. If you haven't seen it then you may want to check out my old post "Mockito - Pros, Cons, and Best Practices". To prepare for my presentation I decided to record myself practicing my material and post it on youtube. Enjoy!

The first screencast is about creating mock objects and stubbing behavior. These are the absolute basics of mocking.


The second screencast is about verifying behavior, or verifying side effects, using Mockito. This is a little more advanced but still an essential API in working with Mockito. YouTube reports this video as 13 minutes long, but don't worry it is only 4:45. Some quirk of YouTube.


The final screencast is about argument matchers, which add flexibility to your stub and verify phases.


I hope you enjoyed these. They could be a little more practiced, but I'm happy enough with the quality. I recorded these on Ubuntu 10.4 using recordMyDesktop and mencode to convert from .ogv to .avi.

Friday, November 5, 2010

Advanced Mockito: Capturing State with Answer and Captors

Hmmm… I really need to mock out java.sql.ResultSet, I know I’ll just subclass it with a hand-rolled mock. Oh-no, the default implementation without method bodies is 650 lines of code long. WTF? Did you know there are 197 public methods on the java.sql.ResultSet interface? This is an absurdly large interface, possibly the largest in the JDK (if not drop a comment, I’d love to know what the largest is). The workaround is to throw one together in Mockito (or your mock framework of choice). My implementation turned out to be 21 lines of code long. Not bad at all. To do it I creatively used ArgumentCaptors, Answer objects, and anonymous inner classes to capture state... (read on for the full article).

The full article is posted over on the Canoo Blog. And don't forget to vote at dzone.

Wednesday, September 29, 2010

Mockito - Pros, Cons, and Best Practices

Mockito - Pros, Cons, and Best Practices

It's been almost 4 years since I wrote a blog post called "EasyMock - Pros, Cons, and Best Practices, and a lot has happened since. You don't hear about EasyMock much any more, and Mockito seems to have replaced it in mindshare. And for good reason: it is better.

A Good Humane Interface for Stubbing
Just like EasyMock, Mockito allows you to chain method calls together to produce less imperative looking code. Here's how you can make a Stub for the canonical Warehouse object:


Warehouse mock = Mockito.mock(Warehouse.class);
Mockito.when(mock.hasInventory(TALISKER, 50)).
thenReturn(true);

I know, I like a crazy formatting. Regardless, giving your System Under Test (SUT) indirect input couldn't be easier. There is no big advantage over EasyMock for stubbing behavior and passing a stub off to the SUT. Giving indirect input with mocks and then using standard JUnit asserts afterwards is simple with both tools, and both support the standard Hamcrest matchers.

Class (not just Interface) Mocks
Mockito allows you to mock out classes as well as interfaces. I know the EasyMock ClassExtensions allowed you to do this as well, but it is a little nicer to have it all in one package with Mockito.

Supports Test Spies, not just Mocks
There is a difference between spies and mocks. Stubs allow you to give indirect input to a test (the values are read but never written), Spies allow you to gather indirect output from a test (the mock is written to and verified, but does not give the test input), and Mocks are both (your object gives indirect input to your test through Stubbing and gathers indirect output through spying). The difference is illustrated between two code examples. In EasyMock, you only have mocks. You must set all input and output expectations before running the test, then verify afterwards.

// arrange
Warehouse mock = EasyMock.createMock(Warehouse.class);
EasyMock.expect(
mock.hasInventory(TALISKER, 50)).
andReturn(true).once();
EasyMock.expect(
mock.remove(TALISKER, 50)).
andReturn(true).once();
EasyMock.replay(mock);

//act
Order order = new Order(TALISKER, 50);
order.fill(warehouse);

// assert
EasyMock.verify(mock);

That's a lot of code, and not all of it is needed. The arrange section is setting up a stub (the warehouse has inventory) and setting up a mock expectation (the remove method will be called later). The assertion in all this is actually the little verify() method at the end. The main point of this test is that remove() was called, but that information is buried in a nest of expectations. Mockito improves on this by throwing out both the record/playback mode and a generic verify() method. It is shorter and clearer this way:

// arrange
Warehouse mock = Mockito.mock(Warehouse.class);
Mockito.when(mock.hasInventory(TALISKER, 50)).
thenReturn(true);

//act
Order order = new Order(TALISKER, 50);
order.fill(warehouse);

// assert
Mockito.verify(warehouse).remove(TALISKER, 50);

The verify step with Mockito is spying on the results of the test, not recording and verifying. Less code and a clearer picture of what really is expected.
Update: There is a separate Spy API you can use in Mockito as well: http://mockito.googlecode.com/svn/branches/1.8.3/javadoc/org/mockito/Mockito.html#13

Better Void Method Handling
Mockito handles void methods better than EasyMock. The fluent API works fine with a void method, but in EasyMock there were some special methods you had to write. First, the Mockito code is fairly simple to read:

// arrange
Warehouse mock = Mockito.mock(Warehouse.class);

//act
Order order = new Order(TALISKER, 50);
order.fill(warehouse);

// assert
Mockito.verify(warehouse).remove(TALISKER, 50);

Here is the same in EasyMock. Not as good:

// arrange
Warehouse mock = EasyMock.createMock(Warehouse.class);
mock.remove(TALISKER, 50);
EasyMock.expectLastMethodCall().once();
EasyMock.replay(mock);

//act
Order order = new Order(TALISKER, 50);
order.fill(warehouse);

// assert
EasyMock.verify(mock);


Mock Object Organization Patterns
Both Mockito and EasyMock suffer from difficult maintenance. What I said in my original EasyMock post holds true for Mockito:
The method chaining style interface is easy to write, but I find it difficult to read. When a test other than the one I'm working on fails, it's often very difficult to determine what exactly is going on. I end up having to examine the production code and the test expectation code to diagnose the issue. Hand-rolled mock objects are much easier to diagnose when something breaks... This problem is especially nasty after refactoring expectation code to reduce duplication. For the life of me, I cannot follow expectation code that has been refactored into shared methods.
Now, four years later, I have a solution that works well for me. With a little care you can make your mocks reusable, maintainable, and readable. This approach was battle tested over many months in an Enterprise Environment(tm). Create a private static method the first time you need a mock. Any important data needs to be passed in as a parameter. Using constants or "magic" fields hides important information and obfuscates tests. For example:

User user = createMockUser("userID", "name");
...
assertEquals("userID", result.id());
assertEquals("name", result.name();

Everything important is visible and in the test, nothing important is hidden. You need to completely hide the replay state behind this factory method if you're still on EasyMock. The Mock framework in use is an implementation detail and try not to let it leak.
Next, as your dependencies grow, be sure to always pass them in as factory method parameters. If you need a User and a Role object, then don't create one method that creates both mocks. One method instantiates one object, otherwise it is a parameter and compose your mock objects in the test method:

User user = createMockUser(
"userID",
"name",
createMockRole("role1"),
createMockRole("role2")
);

When each object type has a factory method, then it makes it much easier to compose the different types of objects together. Reuse. But you can only reuse the methods when they are simple and with few dependencies, otherwise they become too specific and difficult to understand.
The first time you need to reuse one of these methods, then move the method to a utility class called "*Mocker", like UserMocker or RoleMocker. Follow a naming convention so that they are always easy to find. If you remembered to make the private factory methods static then moving them should be very simple. Your client code ends up looking like this, but you can use static imports to fix that:

User user = UserMocker.createMockUser(
"userID",
"name",
RoleMocker.createMockRole("role1"),
RoleMocker.createMockRole("role2")
);

User overloaded methods liberally. Don't create one giant method with every possible parameter in the parameter list. There are good reasons to avoid overloading in production, but this is test. Use overloading so that the test methods only display data relevant to that test and nothing more. Using Varargs can also help keep a clean test.
Lastly, don't use constants. Constants hide the important information out of sight, at the top of the file where you can't see it or in a Mocker class. It's OK to use constants within the test case, but don't define constants in the Mockers, it just hides relevant information and makes the test harder to read later.

Avoid Abstract Test Cases
Managing mock objects within abstract test cases has been very difficult for me, especially when managing replay and record states. I've given up mixing mock objects and abstract TestCase objects. When something breaks it simply takes too long to diagnose. An alternative is to create custom assertion methods that can be reused. Beyond that, I've given up on Abstract TestCase objects anyway, on the grounds of preferring composition of inheritance.

Don't Replace Asserts with Verify
My original comments about EasyMock are still relevant for Mockito: The easiest methods to understand and test are methods that perform some sort of work. You run the method and then use asserts to make sure everything worked. In contrast, mock objects make it easy to test delegation, which is when some object other than the SUT is doing work. Delegation means the method's purpose is to produce a side-effect, not actually perform work. Side-effect code is sometimes needed, but often more difficult to understand and debug. In fact, some languages don't even allow it! If you're test code contains assert methods then you have a good test. If you're code doesn't contain asserts, and instead contains a long list of verify() calls, then you're relying on side effects. This is a unit-test bad smell, especially if there are several objects than need to be verified. Verifying several objects at the end of a unit test is like saying, "My test method needs to do several things: x, y, and z." The charter and responsibility of the method is no longer clear. This is a candidate for refactoring.

No More All or Nothing Testing
Mockito's verify() methods are much more flexible than EasyMock's. You can verify that only one or two methods on the mock were called, while EasyMock had just one coarse verify() method. With EasyMock I ended up littering the code with meaningless expectations, but not so in Mockito. This alone is reason enough to switch.

Failure: Expected X received X
For the most part, Mockito error messages are better than EasyMock's. However, you still sometimes see a failure that reads "Failure. Got X Expected X." Basically, this means that your toString() methods produce the same results but equals() does not. Every user who starts out gets confused by this message at some point. Be Warned.

Don't Stop Handrolling Mocks
Don't throw out hand-rolled mock objects. They have their place. Subclass and Override is a very useful technique for creating a testing seam, use it.

Learn to Write an ArgumentMatcher
Learn to write an ArgumentMatcher. There is a learning curve but it's over quickly. This post is long enough, so I won't give an example.

That's it. See you again in 4 years when the next framework comes out!

Monday, September 27, 2010

Clearer Unit Tests: Assert, Guard, and Throw

I hate the book “xUnit Test Patterns” for being over 800 pages long. I am convinced a good editor can turn any 800 page book into a 700 pager with the exact same content… that includes you Leo Tolstoy! The problem is that xUnit Patterns is still the definitive reference to test concepts and implementation. There is no better book on testing available, but the sheer weight and size the book means few have actually read it. Well I have, and I highlighted the damn thing just to prove it. In this post you’ll find 3 techniques to improve test clarity that, in my opinion, are underutilized in the development world today.


Surf over to http://canoo.com/blog to read the rest of the article, or go straight to the Dzone link if you're inclined to vote it up. Thanks!

Wednesday, April 21, 2010

Spock Framework Mock Objects: Better Groovy Based Testing

I wrote an article on the Canoo blog called "Spock and Test Spies: A Logical Choice".


If you are interested in alternative (and better) mock object frameworks in Groovy then check it out. Spock is a heavy user of Groovy AST Transformations, so those interested in transformations may also want to take a peek.

And if you have come here simply to vote the article up on DZone, then click away!

Tuesday, March 23, 2010

Unrolling Spock: Advanced @Unroll Usages in 0.4

Some of the Spock Framework 0.4 features are starting to see the light of day, with the Data Tables being explained last week in a nice blog post from Peter Niederwieser. One of the new features that I had not seen before is the new advanced @Unroll usage. Mixed with Data Tables, it produces some very cool results, and it can still be used with 0.3 style specs as well. Here's the juice:

JUnit Integration and @Unroll
Spock is built on JUnit, and has always had good IDE support without any effort from you as a user. For the most part, the IDEs just think Spock is another unit test. Here's the a Spock spec for the new Data Tables feature and how it shows up in an IDE.

import spock.lang.*

class TableTest extends Specification {

def "maximum of two numbers"() {
expect:
Math.max(a, b) == c

where:
a | b | c
3 | 7 | 7
5 | 4 | 5
9 | 9 | 9
}
}
The assertion will be run 3 times: once for each row in the data table. And JUnit faithfully reports the method name correctly, even when the method names has a space in it:

The problem with data driven tests and xUnit is poor error location. When a test fails you will receive an error stating which method is the culprit... but what if the method runs an assertion across 50 or 60 pieces of data? The cause of a failure is almost never clear with data driven tests. At it's worst you have to step through several iterations of code waiting for an exception. Good tests have a clear point of failure, but good tests also do not repeat themselves with boilerplate. This is exactly why Spock has the @Unroll annotation. As a test author you get to write one concise unit test, and JUnit does the work of reporting results that help you isolate failures. Consider the same test method with the @Unroll annotation and the accompanying IDE output.
@Unroll
def "maximum of two numbers"() {
expect:
Math.max(a, b) == c

where:
a | b | c
3 | 7 | 7
5 | 4 | 5
9 | 9 | 9
}
When executed, JUnit sees three test methods instead of one: one for each row in the data table:

The end result for you as a test writer is accurate failure resolution. You can pinpoint exactly which row failed. This feature is available in Spock 0.3 and you can use it today. What is new in 0.4 is the ability to change the test name dynamically. Here is a full @Unroll annotation that changes the method name:
@Unroll("maximum of #a and #b is #c")
def "maximum of two numbers"() {
expect:
Math.max(a, b) == c

where:
a | b | c
3 | 7 | 7
5 | 4 | 5
9 | 9 | 9
}
Notice the #variable syntax in the annotation parameter. The # produces a sort of GString-like variable substitution that lets you bind columns from your data table into your test name. The annotation parameter references #a, #b, and #c, which aligns with the data table definition of a | b | c. Check out the IDE output:

Previously, the test name was just the iteration number within the test. The new @Unroll parameter allows you to make the test name much more meaningful. Your tests will improve because failures become more descriptive. Unrolled failure messages before simply had the iteration name embedded in them, while now they can have meaningful data that you prescribe.

My favorite part of playing with the new @Unroll was to see the default value of the parameter within the Spock source code:
java.lang.String value() default "#featureName[#iterationCount]";
Talk about eating your own dog food... the default value is a test name template, just like you could have written in your own test. Makes you wonder what other variables are in scope, huh?

Spock snapshot builds for 0.4 are available at: http://m2repo.spockframework.org. Get it before the link breaks.

Friday, February 19, 2010

Testing Asynchronous Code with GPars Dataflows

In my last post I showed how to use JConch 1.2 to unit test asynchronous code. It contains a locking/barrier mechanism that allows you to gracefully tell your unit test how to wait and proceed for off thread events without sleeping or polling. Whee!

As a small example, here is how the TestCoordinator would be used to test a mouse click event that happens on a different thread:

TestCoordinator coord = new TestCoordinator()

MyComponent component = new MyComponent()
component.addActionListener({ ActionEvent e ->
assert "click" == e.actionCommand
coord.finishTest()
} as ActionListener)

component.click()
coord.delayTestFinish(1, TimeUnit.SECONDS)

If you are living in a Groovy world, then you should consider using GPars Dataflow variables instead of the JConch TestCoordinator. The advantage of using Dataflows is that you get a similar thread coordination API but also get a variable capture API, allowing you to move assertion statements to the end of your unit test where they belong. If you are looking for a clean, minimalist approach to capturing off thread events, then dataflows might be exactly what you need:
import java.awt.event.*
import javax.swing.SwingUtilities
import groovyx.gpars.dataflow.DataFlowVariable

def event = new DataFlowVariable()

MyComponent component = new MyComponent()
component.addActionListener({ ActionEvent e ->
event << e
} as ActionListener)

component.click()

ActionEvent e = event.val
assert e.source != null

assert e.actionCommand == "click"

A DataFlowVariable is a little like a Java Future mixed with an immutable, thread safe object. The DataFlowVariable has an underlying value which can be set once, and only once, and trying to access that value will block the caller until the value is available. In this example, setting the value is done in the event handler with the "event << e" line, and accessing the value is done in the "event.val" line. Getting the "val" will block the caller until a value is available. (Remember, in Groovy .val property access is translated into a getVal() method call).

The advantage of using Dataflows in testing, when compared to Java, is that you get a nicer thread synchronization API than what the java.util.concurrent primitives provide. The advantage of Dataflows, when compared to JConch, is that you get to move your assertion methods back to the end of the unit tests. William Wake described a format for unit tests called Arrange-Act-Assert, and it is still one of the best guidelines to writing clear and understandable unit tests. Assertion methods belong at the end of your test and arrangement code belongs at the beginning (note how many mock object frameworks subvert this ordering!). Capturing a variable is a good way to move the assertions to the end of the method, but in most frameworks it requires copious amounts of accidentally complex code.

The downside of using Dataflows is that you once again have to set an @Timeout value on your unit test in the event that you never get a value (otherwise your tests will hang). OH WAIT, that is totally wrong. The GPars authors did provide a timeout value on DataFlowVariable#getVal():
ActionEvent e = event.getVal(4, TimeUnit.SECONDS)
I had you there for a second though, right? Be warned, if the timeout value is exceeded then getVal() returns null, it does not throw an exception.

The only downside to using DataFlow concurrency that I can see is that you actually need to understand a little bit about DataFlow concurrency. Who would have thought? DataFlowVariable is just the tip of the iceberg when it comes to GPars DataFlow support, and is not even the primary use case. The Dataflow User Guide is a good read and will explain a lot more about the concepts and GPars' implementation.

Feel free to try this yourself. You don't even need to download any jars or change your project files. Just add the correct Grapes to the top of your unit test:
@Grab(group='org.codehaus.gpars', module='gpars', version='0.9')
@GrabResolver(name='jboss', root='http://repository.jboss.org/maven2/')
If you need more help, then check out the full example.

Happy Testing!

Tuesday, February 9, 2010

Asynchronous Unit Test Coordination with JConch 1.2

Slowly but surely, JConch Java Concurrency Library is becoming a depot for multithreaded and asynchronous testing on the Java platform. First there was SerialExectorService, allowing you to test with a Java ExecutorService that never started threads (example, javadoc). Then there was assertSynchronized, allowing you to make easy unit test assertions about your object's synchronization policy (javadoc, example).

And now JConch 1.2 offers TestCoordinator: a tool for testing asynchronous code and multi-threaded callbacks. The TestCoordinator solves the problem of how to properly wait for asynchronous method calls without littering your unit tests with wait/join calls or CyclicBarrier/CountDownLatch API calls. In this regard, it provides a useful unit testing abstraction over the great Java 5 concurrency primitives.

Note: If you'd like to skip all the prose then go straight to the example and unit tests that are part of JConch 1.2.

Writing good unit tests requires the same input as writing good production code: practice, dedication, and about 10,000 hours hours experience. Almost any component framework that requires some sort of event listener invariably has a unit test that looks like this:

MyComponent component = new MyComponent()

ActionEvent event
component.addActionListener({ ActionEvent e ->
event = e
} as ActionListener)

component.click()
Thread.sleep(1000)

assert event.source != null
assert "click" == event.actionCommand
OK, usually it's in Java and not Groovy, but you get the point. Life's too short to write Java at home. The simple format is 1) create a component with a listener that captures the input, 2) activate the component, and 3) put the thread to sleep for a while and hope that the event fires before your assertions get run. The obvious problem is that you end up with either slow or intermittently failing unit tests depending on how long you sleep (no, there really isn't a perfect sleep number that avoids both).

In the Java 4 days this was "solved" by monkeying with Object#wait and Object#notify method calls. Ewww. Java 5 introduced CyclicBarrier and CountDownLatch which solved the problem nicely albeit in a primitive way. It is an improvement, but we can do better than this:
@Test(timeout=5000)
public void testClick() {
CyclicBarrier gate = new CyclicBarrier(2)

MyComponent component = new MyComponent()

component.addActionListener({ ActionEvent e ->
assert "click" == e.actionCommand
gate.await()
} as ActionListener)

component.click()
gate.await()
}
This approach allows us to move the assertion methods inside the callback, because we're insured that either the callback will be called or the test will fail with a timeout (the @Test(timeout=5000) bit). It is simpler and hides some complexity, but there is still a bunch of primitives distracting the reader from the core content of the test... what is that (2) parameter on the barrier constructor? Is the timeout value clear or is it hidden within a method annotation? And just what does await() mean? There is a lot of primitiveness involved here, which is what TestCoordinator abstracts over:
import jconch.testing.TestCoordinator

TestCoordinator coord = new TestCoordinator()

MyComponent component = new MyComponent()
component.addActionListener({ ActionEvent e ->
assert "click" == e.actionCommand
coord.finishTest()
} as ActionListener)

component.click()
coord.delayTestFinish(1, TimeUnit.SECONDS)
As you can see, TestCoordinator acts alot like a barrier or latch, but without all the low level API. When you've activated your class under test then you call delayTestFinish(...); the unit test will wait unit the listener calls finishTest(). And if finishTest() has already been called (a frequent possibility with multithreaded systems), then delayTestFinish just proceeds. If the timeout value expires then the test fails. No funny timeout annotation. No funny API. Just a simple coordinator. You want to delay a test until a callback is finished, and the API is designed around this nomenclature.

There are two other options to delay as well:
coord.delayTestFinish(1000) // milliseconds
coord.delayTestFinish() // requires @Timeout value!
For those of you coming from GWT... yes, this is almost exactly the API of GWTTestCase. Use what works, I say.

For more info on TestCoordinator, check out the UnitTest and the example. Happy Testing!

Sunday, February 7, 2010

New in Groovy 1.7.1: Constructor Mocking and Half Mocks

The Groovy MockFor object got some fun new features this weekend: constructor mocking and "half-mocks". The tickets are marked for Groovy 1.7.1, so these features are available in the nightly builds or in the next few weeks as 1.7.1 is released. The easiest thing is, of course, to just build from source.

The first feature is Constructor mocking. It is now possible to specify a return value for mock constructor calls. Here is an example that uses a "Person" object. The "tom" variable is a real Person object, while the "mary" object is not. Thanks to this new feature, instantiating Mary returns to you Tom.

import groovy.mock.interceptor.MockFor

class Person {
String name
}

def tom = new Person(name:'Tom')

def mock = new MockFor(Person, true)

mock.demand.with {
Person() { tom }
}

mock.use {
def mary = new Person(name:'Mary')
assert tom == mary
}
There are two parts to getting this working: the "demand.with" block, where the person constructor is specified to return tom, and the true parameter passed to MockFor. To make MockFor backwards compatible, a flag was needed to control when to allow constructor mocking and when not to allow it. As you can see, after doing this, the tom and mary objects are equal (in fact, the same reference).

The problem with this feature alone is that calling tom.getName() results in a mock exception saying no demand is set. If Tom is a real instance of Person then why would you get a demand exception? Well, within the mock.use block Tom is a mock. The behaviour you probably expect is to have the real Tom methods pass through to the real implementation, which is why "half-mocks" were introduced. Check out how you can specify methods to ignore and pass through to the underlying object:
mock.ignore(~'get.*')
mock.demand.with {
Person() { tom }
}

mock.use {
def mary = new Person(name:'Mary')
assert mary.name == 'Tom'
}
The ignore method takes a pattern to match, and the mock ignores those methods, passing them on to the underlying implementation. So your mock is still a mock, not a real object, but methods are passed through as needed. This is the opposite of how EasyMock partial mocking works, where a partial mock is technically a subclass of the target class, and methods are routed by default to the real implementation. In Groovy, the method are routed by default to the mock.

Fun stuff, and thanks to Paul King for the work!

Thursday, December 3, 2009

Simple XML Testing from Java

2009 is coming to a close and I'm writing a blog post about Java and XML. The blog's called "behind the times" for a reason: no fancy dynamic languages, JSON, or REST. Straight up XML on Java action.

One of my favorite editions to our enterprise toolset this year was XMLUnit. We'd been using Groovy in testing, and multi-line strings led to a ton of expressiveness in test cases... but then we stopped using Groovy. I switched back to Java testing and was left with making String based assertions and doing String#contains() calls. Not ideal; enter XMLUnit.

XMLUnit supports XML based equality comparisons so that things like these two snippets are equal:

<root/>

<root></root>

As well as these:
<root>data</root>

<root>
data
</root>

In fact, there's a whole gaggle of options around what is a meaningful versus a meaningless difference. For instance, I often consider two dates equal as long as they are formatted correctly (ignoring those pesky timestamp issue is nice).

The problem with XMLUnit is that the API is not as nice for the simple case as it could be. What I want is a simple custom assertion that asserts two XML snippets as similar. Something like this:
XmlAssertions.assertXmlSimilar("<root/>", "<root></root>"); 
XmlAssertions.assertXmlSimilar("<root>data</root>", "<root>\ndata\n</root>\n");

This was as simple as creating a small utility class and hiding the XMLUnit API behind a nicer custom assertion:
import java.util.List;
import junit.framework.*;
import org.custommonkey.xmlunit.*;

public class XmlAssertions {

private static final String ERROR_MSG = "XML comparison failure. \nExpected: %s\nReceived: %s\n%s";

static {
XMLUnit.setIgnoreWhitespace(true);
}

public static void assertXmlSimilar(String expected, String actual) {
try {
Diff diff = new Diff(expected, actual);
List differences = new DetailedDiff(diff).getAllDifferences();
Assert.assertTrue(
String.format(ERROR_MSG, expected, actual, differences),
diff.similar());
} catch (Exception ex) {
Assert.fail(String.format(ERROR_MSG, expected, actual, ex.getMessage()));
}
}
}

The raw XMLUnit code is clearly not something you want to see within the body of a test method. The custom assertion seems simple, but it's made a real pleasure of writing XML based functional tests around all our web services. Feel free to steal my code here: http://svn.assembla.com/svn/SampleCode/xmlunit/XmlAssertions.java

Saturday, August 15, 2009

Testing OSGi Bundles with Pax Exam, Groovy and Gradle

You can't be an expert on everything. There are a few topics in life I've given up on, forever to be ignorant:

  • Botany - Don't ask me the name of any plant or tree. I won't know.
  • Hardware Specs - Telling me the model number and speed on your new laptop just makes me confused. I stopped reading the Computer Shopper years ago.
  • Maven - I'm happy to use it IF SOMEONE ELSE CREATES THE POM. Life's too short for that much XML.
So what was I to do with Pax Exam? This framework allows you to write JUnit or TestNG tests and then executes them in the OSGi container of your choosing. It's a cool framework but much of the documentation assumes a willingness to scroll through lines and lines of Maven XML. Ugh. Life's too short to grapple with build systems.

So the nut is cracked. I've got Groovy unit tests running across Equinox, Felix, and Knopflerfish from both Gradle and IntelliJ IDEA. No Maven in sight.

Writing Pax Exam Tests in Groovy

Once it was all configured, writing Pax Exam tests were simple. Start with a plain old JUnit 4 test and do two things:
  1. Annotate it to run with the Pax Exam JUnit runner
  2. Configure it to provision the Groovy-all JAR
Here it is, complete with imports and ready for a little copy-paste action.
import org.junit.runner.RunWith
import org.ops4j.pax.exam.junit.JUnit4TestRunner
import org.junit.Test
import org.ops4j.pax.exam.junit.Configuration
import org.ops4j.pax.exam.Option
import static org.ops4j.pax.exam.CoreOptions.*

@RunWith (JUnit4TestRunner)
class GroovyIntegrationTest {

@Configuration
public Option[] configure() {
[
provision(
mavenBundle().groupId('org.codehaus.groovy').artifactId('groovy-all').version('1.6.4')
)
] as Option[]
}

@Test
public void testFramework() {
println 'Hello from Pax-Groovy!'
}
}

A few things to notice... CoreOptions was statically imported, so the methods provision() and mavenBundle() are resolved. The configure() method returns an Array of Option objects, so the "as Option[]" cast is needed. And by default, the tests are going to run on Felix 1.8 (or thereabouts).

Before Pax Exam becomes useful you're going to want to provision your bundle as the system under test, get access to the BundleContext it was loaded with, and specify more containers to run on.

Provisioning your bundle and running on multiple containers is a matter of configuring the test differently:
@Configuration
public Option[] configure() {
[equinox(),
felix(),
knopflerfish(),
provision(
bundle(new File('./../out/production/Filter4osgi.jar').toURI().toString()),
mavenBundle().groupId('org.codehaus.groovy').artifactId('groovy-all').version('1.6.4')
)] as Option[]
}
Here I'm specifying Equinox, Felix, and Knopflerfish. There's also options for allEquinoxVersions, allFelixVersions, and allKnopflerfishVersions, as well as allFrameworks and allFrameworksVersions to test on the world. That options takes a few minutes to execute! Provisioning my own bundle can be done by loading it as a file URL. This example isn't very robust but it proves the concept.

The BundleContext is available as an injectable bean from Pax Exam. If you want the BundleContext in your unit test, to perhaps test that services were registered correctly, then add this as a field:
@Inject
BundleContext bundleContext
And here is a simple test to make sure that my filter4osgi library was correctly installed:
@Test
public void test_BundleIsLoaded() {

def found = bundleContext.bundles.find {
'filter4osgi' == it.symbolicName
}
Assert.assertNotNull('filter4osgi bundle not loaded!', found)
}
Running Pax Exam Tests from Gradle

The Gradle build was slick. Tell Gradle to load your bundle as a file URL and the rest is just boilerplate dependency management:
usePlugin 'groovy'

repositories {
mavenCentral()
flatDir dirs: [
'./../out/production', // filter4osgi jar built earlier
]
}

dependencies {
groovy group: 'org.codehaus.groovy', name: 'groovy-all', version: '1.6.4'
compile(
'org.ops4j.pax.exam:pax-exam:1.0.0',
'org.ops4j.pax.exam:pax-exam-container-default:1.0.0',
'org.ops4j.pax.exam:pax-exam-junit:1.0.0',
'junit:junit:4.5',
'org.osgi:org.osgi.core:4.0.1',
':filter4osgi:',
)
}
"gradle test" is the only target you'll ever need.

Running Pax Exam Tests from IntelliJ IDEA

Your unit tests will show up once for each container you're targeting. So my two tests run against 3 containers shows up as 6 tests in the test runner window, plus a sweet ASCII art logo:

One nice side effect of Maven is that IDEA can generate files off it, so you don't need to worry about the transative dependencies in the IDE, it's all configured for you. When using Gradle you do need to set up the IDE manually. I added the following JARs as dependencies and it all worked fine (with one exception):
commons-discovery-0.4.jar
commons-logging-1.1.jar
easymock-2.4.jar
junit-4.4.jar
log4j-1.2.12.jar
ops4j-base-lang-1.0.0.jar
ops4j-base-monitors-1.0.0.jar
ops4j-base-net-1.0.0.jar
org.osgi.core-4.0.1.jar
osgi-3.4.0.jar
pax-exam-1.1.0-SNAPSHOT.jar
pax-exam-container-default-1.1.0-SNAPSHOT.jar
pax-exam-container-rbc-1.1.0-SNAPSHOT.jar
pax-exam-container-rbc-client-1.1.0-SNAPSHOT.jar
pax-exam-junit-1.1.0-SNAPSHOT.jar
pax-exam-junit-extender-1.1.0-SNAPSHOT.jar
pax-exam-junit-extender-impl-1.1.0-SNAPSHOT.jar
pax-exam-runtime-1.1.0-SNAPSHOT.jar
pax-exam-spi-1.1.0-SNAPSHOT.jar
pax-exam-testng-1.1.0-SNAPSHOT.jar
pax-exam-tutorial-1.1.0-SNAPSHOT.jar
pax-runner-no-jcl-1.1.0.jar
You can surely discard a lot of these JARs. But I added the list of completeness. It's just the IDE setup. I did have one issue with running the tests in the IDEA. Between runs I needed to manually delete my $TEMP_DIR/paxexam_runner_[user] folder. It sounds like no one else is experiencing this issue and I'm using a snapshot I built myself from source. The mailing list has been pretty responsive but it's a mystery error for now.

That's the end of it, folks. I'm going to the back yard to sit in the kiddie pool with my daughter. It's hot as a mutha in my office.

Thursday, July 23, 2009

Is ignoring private access in Groovy evil?

The world's worst kept secret has got to be that Groovy ignores the private access modifier in code. You're free to access and invoke private methods, fields, and classes. A well known speaker called this "feature" insanely useful for unit testing.

I'm adding that it's also insanely evil. But it's not both insanely useful and insanely evil... it's either, depending on how you use it. I've spend all night in Gimp making a freakin' sweet graph showing the continuum, but before the big reveal we need to review some vocabulary.

The most useful addition from xUnit Patterns to the testing community is the classification of input and output as either direct or indirect. The easiest methods to test accept direction input (a method parameter) and return direct output (a return value). Think about testing Math#min(int, int). Damnably easy. Indirect input is when your system under test can't be fed input that it uses directly but can be fed an object that can locate that input. Thank about testing a class that uses EntityManager.find(Class, Object) to look up a row on the database. You can provide a mock entity manager that indirectly gives the system input. It's not too difficult but a lot harder than testing Math#min(int, int). Indirect output is when you cannot make assertions about the return value of the method to verify that it worked correctly. Instead you have to look at what side effects the method performed. Any time you are verifying mock method calls, or looking up that correct values were set back on the input values, then you are dealing with indirect output. This is the hardest to test.

So here is testing continuum for using Groovy to ignore private access modifiers:

This image took me like 4 hours to make so don't you dare laugh. Here's a useful key:

Not Using - Clearly, it is best not to use this feature. It's how Jesus would code. Yes, I'm serious. Jesus.

Indirect input in 3rd party library - So you're using a library that is hyper encapsulated and difficult to mock (like the JDK?). The library is unlikely to change frequently and you control when it changes. Sure, setting private values to provide your test with indirect input is useful. It'd be nice if there were more testable options, but at some point you have to wash your hands, stop trying to do the right thing, and just make a decision. A little like Pontius Pilate.

Indirect input in you own objects - Ignoring private in your own libraries can be insanely useful for getting some tests written quickly and out the door. But you're just creating tight coupling to the implementation of other objects... and you control those objects! Clearly there is a better option, and you have the control to perform that option. On an evil scale, it's a little like Saint Paul. Huh? A saint? That's not evil? Let me remind you: Paul killed a dude. With a rock. KILLED HIM. Yeah, go look up how Saint Stephen died. So, like Paul, you are clearly violating your principles in this scenario, but the situation is redeemable. Use private access cautiously, but then come back later and do the right thing. Bad decisions now won't stop you from being canonized later.

Indirect output in 3rd party library - The iteration is late, your test coverage is low, and you're stuck integrating with a shoddy 3rd party API where every method returns void. Slam some tests together and violate private access to write a fragile test coupled to implementation that looks freakishly similar to the production code. Did I just reimplement the system under test in mocks? Yup. What am I really testing? Nothing. Like Judas Iscariot, you've sacrificed your design principles for thirty pieces of silver. In 3 months, when maintenance is a nightmare, deny 3 times that you had anything to do with the code. If that fails, blame it all all on a contractor and move on.

Indirect output in your own objects - Dude c'mon. The only way to test your system that you wrote is to access private fields of objects you own? I don't buy it. This is where the difference between TDD and Test Always shows itself. I challenge anyone to evolve a system using test first that requires this sort of shenanigan. I just don't see how focusing on behaviors and testability would ever leave you like this. Whereas, trying to write tests for code after the fact might. Cain killed his brother and then denied it. That's pretty evil, just like accessing private fields on objects you own. You're given a great tool like Groovy for testing and this is how you choose to wield it? Like Abel, Groovy deserves better. When we catch you doing this, don't try to deny it. We'll know you're lying and we won't forget.

Indirect output in system under test - Old school Satan bad. This is just unjustifiable and with no benefits. What can your test possibly assert? That the code you wrote performs the way you wrote it? On a continuum of useless tests, that's like Pet Rock useless. And before you say, "I'm just laying down some unit tests so that I can refactor later," let me add that almost any refactoring you perform is bound to break the tests. Have fun with that. This usage just seems evil to me.

I don't often ask myself "What would Jesus do?" I try to live my live more like Pilate. I try my best but, hey man, sometimes stuff happens. Don't get hung up on it. Although, I'll admit to doing some pretty nasty stuff in the past, so a poll of my co-workers might reveal I'm more in the Paul range than I'd like to admit. How about you?

Groovy+Testing: Little Things, Big Impact

When it comes to unit testing, it's the little things that drive me nuts. Or maybe it's the little things that make testing enjoyable. Optimism is better, I suppose. Now I don't buy into all that tipping point garbage, but there are two Groovy features that I miss immediately when returning to Java. Almost every other rising language has them, they seem like trivialities to add to a language, and they aren't likely to be in Project Coin. (Beware, all 3 of the previous statements are suppositions). And these two features are... multi-line strings and default parameter values.

As ridiculous as it sounds, I'm going to spend several paragraphs extolling the virtues of two language features that are so simple they can be explained in a single sentence each.

Multiline Strings

Why am I constantly testing with XML snippets? This is a question I don't often ask myself in Groovy because XML snippets look really nice embedded in a test method:

def garage = new Garage(
new Car(CAR_NAME1, CAR_MAKE1),
new Car(CAR_NAME2, CAR_MAKE2),
new Car(CAR_NAME3, CAR_MAKE3)
)

def actual = serialize(garage, Garage)

def expected = """
<garage>
<car name="$CAR_NAME1" make="$CAR_MAKE1" />
<car name="$CAR_NAME2" make="$CAR_MAKE2" />
<car name="$CAR_NAME3" make="$CAR_MAKE3" />
</garage>"""

assertXmlEqual(expected, actual)

This test method clearly shows a garage full of cars being created and a garage full of cars being expected. There is symmetry and conciseness, and I find it pretty easy to see how the input relates to the expected output. Compare the Java version:
Garage garage = new Garage(
new Car(CAR_NAME1, CAR_MAKE1),
new Car(CAR_NAME2, CAR_MAKE2),
new Car(CAR_NAME3, CAR_MAKE3)
);

String actual = serialize(garage, Garage.class);

String expected =
"<garage>" +
" <car name=\"" + CAR_NAME1 + "\" make=\"" + CAR_MAKE1 + "\" /> " +
" <car name=\"" + CAR_NAME2 + "\" make=\"" + CAR_MAKE2 + "\" /> " +
" <car name=\"" + CAR_NAME3 + "\" make=\"" + CAR_MAKE3 + "\" /> " +
"</garage>";

assertXmlEqual(expected, actual);

Whee! Escaping quote characters is fun! I can't see how the expected block lines up with the input anymore, it's lost in a sea of accidental complexity, back slashes, and quotes. Yuck. And this is some pretty simple XML. The tests as documentation idea starts to suffer without multiline strings because the only thing that finds this format easy to read is the compiler. Speaking of documentation, how about copy and pasting the XML snippet into a user document or email? Or heaven forbid generating user documentation off the test case! You're just not going to do that with the Java version. In fact, I'd say most the time I don't even write the Java version like this... the escapes and quotes bring so much clutter that I just store XML snippets in separate XML files and read them in during each test:
Garage garage = new Garage(
new Car(CAR_NAME1, CAR_MAKE1),
new Car(CAR_NAME2, CAR_MAKE2),
new Car(CAR_NAME3, CAR_MAKE3)
);

String actual = serialize(garage, Garage.class);

String expected = readFromFile("MyTest.sample.xml");

assertXmlEqual(expected, actual);

It's no longer abrasive on the eye, but you also completely lose the ability to see the relationship between the input and the output. You aren't helping the tests document the system by hiding all the input from the reader!

Such a small thing and I find it so valuable, and it's nothing more than a notational convenience, a little syntactical sugar.

Default Parameter Values
Tiny feature; big effect on unit testing.

Unit testing is about building tons of data, all in different configurations or states of construction, and then throwing that data at the system under test, observing and verifying the results. Unit tests look a lot different from production code. In production code, subroutines exist to perform smaller pieces of a larger, decomposed problem. In test code, subroutines exist to build objects. The design principles between production and test are different, and it makes sense that some language features might be very useful in test but of more limited value in production. I find default parameter values fit within this category. Consider a set of test methods that need to build a login form (username, password fields) in different states:
JFrame frame1 = makeLoginWindow()
JFrame frame2 = makeLoginWindow("some username")
JFrame frame3 = makeLoginWindow("some username", "some password")

Making a function to build a Login Window in these various states can be done within a single function in Groovy, you just have to use default parameters.
private JFrame makeLoginWindow(String username = null, String password = null) {

JTextField userField = new JTextField()
JTextField passwordField = new JTextField()
if (username != null) userField.text = username
if (password != null) passwordField.text = password

JFrame frame = new JFrame()
frame.contentPane.add(userField)
frame.contentPane.add(passwordField)
return frame
}

Under the covers, this is still an overloaded method to the JVM. But that's alright. There is a single source for all the test data configuration, and navigating (ie reading) the test case is made easier by having a single source.

In a Java test case, you're stuck defining at least 3 methods. The real rock star programmers are going to chain the method calls together... ohhh:
private JFrame makeLoginWindow() {
makeLoginWindow(null, null);
}
private JFrame makeLoginWindow(String username) {
makeLoginWindow(username, null);
}
private JFrame makeLoginWindow(String username, String password) {

JTextField userField = new JTextField();
JTextField passwordField = new JTextField();
if (username != null) userField.setText(username);
if (password != null) passwordField.setText(password);

JFrame frame = new JFrame();
frame.contentPane.add(userField);
frame.contentPane.add(passwordField);
return frame;
}

Conceptually, we've just added 3 entities to the test case that didn't exist before. Navigating around labyrinths of production code is a necessary evil. There are other design constraints at play and stuffing everything into one place isn't always the right thing to do. But in the test tree, labyrinths of chained code are just evil, nothing necessary about it. Having to chase down dependencies undermines one the chief principles of testing: show clearly and simply how input is transformed to output. Default Parameters for the win.

Sadly, when advocating using Groovy as a testing language, these two features are unconvincing evidence of Groovy's superiority. They just don't seem like much. They aren't very exciting. So why are they the first things I miss when creating new Java test cases?

By the way: PHP has both these features. Ha!

Wednesday, July 22, 2009

When Testability and Readability Collide

Walter Harley was kind enough to leave a comment on my last post about testing busy constructors:

"...some of the attributes that support good testability also make for poor readability. For example, loosely coupled objects make it easy to supply mocks for testing; but they also make it hard to see what's going on in the production code."
I like any man who knows how to properly use a semi-colon. Grammar aside, this is a fair statement for a lot of projects. Why do so many programmers learn to loath dependency injection and IoC container configuration? Is it perhaps, that our default object model looks something like this:

In words, for each simple object (a user service in this example), you'll usually have an interface, a concrete class, a unit test, and a mock implementation. So we've created 4 entities, 3 of which are nonessential to solving the problem at hand. Oh, you're using a mocking framework so have one less than the diagram? A synthesized subclass is still kinda a subclass, isn't it? Whatever.

In my experience, this quad or triad of objects repeats itself fractal like across a Java project. It's uncommon to see an interface with multiple useful implementations and it's downright rare to see suites of components that operate on those abstractions. Names seem to spread out horizontally in my projects. Runnable, Callable, ActionListener, Transformer5, F, Predicate... aren't these all the same thing? Why are there so many names in the world?

In Java we write in names and think in names. There is no such thing as a function that accepts something and returns something. You always have to give it a name (Callable, Runnable, Transformer). And you write your APIs to those names. In Groovy you have closures to solve this problem, and you end up seeing a lot of code that works on that one unit of abstraction. But don't be fooled, it's not a problem with types. In F# and other functional languages it is entirely natural to reason about features by type instead of name. It's easy to write general algorithms that accept something with a certain signature as a parameter rather than a specific named. So my first assertion about readability and testability is that readability suffers in Java because of our culture of naming things, and we write our abstractions based on name instead of type.

Another factor to consider is the difference between a meaningful abstraction and a meaningless abstraction. Writing OO software is, on some level, about building models, whether it be of the problem domain, or the solution space, or the real world. An abstraction allows you to hide details that aren't needed. It allows you to write a general purpose algorithm or component that operate at a higher level than it's dependency. What possible complexity is the above UserService interface hiding from the programmer? None: it is an absolutely meaningless abstraction. And a system riddled with meaningless abstractions is just arbitrarily and needlessly complex. The problem might be in our perceived best practices...

Test Driver Development pushes you to use dependency injection as a way to vary the behavior of dependencies at test time. Fine. Using mock object frameworks guides you towards declaring interfaces for objects. Now the namespace starts to get cluttered, but modern IDEs easily support navigating hundreds, even thousands of classes, so it is no real problem to have a cluttered namespace. However, long-term TDD and mocking are creating a readability beast that results in a frustrating game of "find the dependencies" when changes need to be made. And the IDE masks the problem well into the days in which your codebase undeniably becomes "legacy code". Now the code is unreadable and retrofitting the legacy code with any modicum of meaningful abstraction makes those sections of the code look alien and feel out of place. We lost the battle and testability as a technique to plug the sinking ship rather than to guide an elegant design. So my second assertion about readability and testability is that readability suffers in Java because we have become supremely efficient and versed at producing meaningless abstractions.

Long term readability depends on finding type based abstractions, rather than name based ones, and then being diligent and intentional about coding to those abstractions. I don't know of any way to do this other than to think, and think hard, about the code we write every day. Sadly, some days I just don't feel up to the task.

Monday, July 20, 2009

Busy Constructors (are no problem to test)

For whatever reason, I was browsing Miško Hevery's old testability blog entries and found a nice top 10 list of developer practices that make code hard to test.

Too bad I totally disagree with Item #3: Doing work in constructor. There's nothing untestable about big long constructors. No, really. Consider this horrorshow constructor, in which a global DataSource is retrieved from a mingleton and a concrete class is instantiated:

import javax.sql.DataSource;

public class UserService {

private final DataSource dataSource;
private final UserSettings settings;

public UserService() {
dataSource = DatasourceFactory.getDefault();
settings = new UserSettingsImpl();
}
}
Don't get me wrong, this is a horrible design. For one, retrieving the data source from a global static method is an example of a mingleton, which is global state by any other name: near impossible to inject any sort of variable behavior or polymorphism into. And instantiating a concrete implementation class (new UserSettingsImpl()) tightly couples this service to that class, another undesirable trait. This service is incredibly tightly coupled to the dependencies it requires. You'll never be able to reuse this service in another context where the datasource and user settings are different. And writing a test would be reusing this service... so what possibly makes this easy to test?

Package local constructors mixed with an Extract Parameter refactoring is what makes this easy to test. Simply create a new constructor for the object and leave out a visibility modifier. This makes the method only visible to objects in the same package (like your unit test)! Then add all the fields created in the original constructor to the parameter list. Final fields are your friend here because then the compiler will check to make sure you did this correctly. If you want to get fancy, chain the original constructor call into the new one:
public class UserService {

private final DataSource dataSource;
private final UserSettings settings;

public UserService() {
this(DatasourceFactory.getDefault(), new UserSettingsImpl());
}

UserService(DataSource dataSource, UserSettings settings) {
this.dataSource = dataSource;
this.settings = settings;
}
}
This transformation preserves all the type signatures that were previously in the class, so all the clients that were compiled against the original code will continue to work just fine without recompiling. So even if the class you need to refactor is depended upon from everywhere, this is still a local refactoring. None of your refactor fearing coworkers even needs to know; it'll just be between us.

Did this buy us anything? Yes. All the dependencies of the class are now exposed for mocking and stubbing, without requiring changes to any calling code. Of course, your original constructor can't be tested, so if you have behavior or logic in the constructor that you need to test, then a little more creative refactoring is needed and it may not be supported with just automated IDE refactorings. Some might complain that we've modified the production code simply to enable testability... but to them I ask for alternatives. When weighing time commitments and code impacts, I find this "expose local constructor" refactoring to be of real benefit and frequently used.

Thursday, July 16, 2009

Big Flat Test Cases Suck (and what to do about it)

It seems like all 900 pages of xUnit Patterns was just published a little while ago... my how things have changed since May of 2007. Back then, when it came to organizing test methods, we only had three options. Beginners always created a test case per class; there was a one to one mapping between production classes and test classes, and I'd guess most people are still doing this. The enlightened testers were creating one test case per fixture, in which test methods were all in the same test class if they shared the same setUp() method. This was a response to the problem with test case per class, which was complexity. As the number of test methods increased the cohesion of the test case decreased. As more and more fields are added to the test to support different scenarios of testing, then each test method starts to use only a fraction of the fields available within the test case. Test case per fixture solves the problem by breaking out test methods into a new test case when new fixture and setUp() data is added. This was an improvement and was the recommended approach in Astel's Test Driven Development book. The really cool kids, however, were doing test case per feature. This entails grouping test methods together based on what feature or user story they implement. Kinda sounds like an easyb story, huh? Yeah, but it hadn't really caught on yet back then.

But don't be fooled! All three of these test organization methods are essentially the same: tests are going to be written as methods and enclosed in a class. How 2007... how xUnit-ish. See, all three approaches share the same deficiency.

Test cases grow. They grow really long. And they all grow in one direction: down the screen. Navigation isn't too bad an issue... any IDE test runner is going to navigate you right to the correct line number when a test fails. And you'll have a naming convention for tests, so keyboarding around the file isn't too tough. It's not simple though, and some speakers are suggesting it's better to use hugely long test names and add underscores to test methods to tell them apart easier. So this:

public void testInitialPositionSetCorrectlyUponInstantiation()
Is better as:
public void test_initial_position_set_correctly_upon_instantiation()
Sure, I guess that's nicer. But exactly what problem is this solving? For that matter, what is the problem with big, long test cases?

Pretend we do have tests grouped by feature and that we have to make a change to that feature. How many tests are going to fail? Is there any way to tell beyond scrolling through the file and reading all the tests? It would be much easier if you could clearly see how the tests all relate to one another. But a flat list doesn't show relationships. Maybe there is a naming convention for test methods that might help, but you're still reading all the method signatures and making a decision based on name.

A hierarchical test case would let you do this, though. Test dependencies would be self-evident if you could define a test scenario and then make test methods or other scenarios children to as many levels deep as you want. You could still have the ease of grouping test methods by class, because you'd get a nice one-to-one mapping between test classes and production classes. And you'd also get test case per feature because the tests for each feature could just be child scenarios under the main scenario. And you'd also get test case per fixture because each scenario could have setUp() data that is shared with all children scenarios. Can you say best of all possible worlds? An easyb example it is then!
scenario "testing a simple user service", {

scenario "testing service with 0 users", {

given "a zero user service", {
service = new UserService()
}

scenario "cannot remove a user", {
then "removing users triggers exception", {
ensureThrows(IllegalStateException) {
service.removeUser(0)
}
}
}

scenario "can add a user", {
given "a user", {
user = ["August", "Schells"]
}

scenario "adding a user once", {
when "he is added", {
service.addUser(*user)
}
then "user count is 1", {
service.userCount.shouldBe 1
}
}

scenario "adding the same user twice", {
when "he is added again", {
service.addUser(*user)
}
then "count is 2", {
service.userCount.shouldBe 2
}
}
}
}

scenario "testing a service with 10 users", {

given "a 10 user service", {
service = new UserService()
(1..10).each {
service.addUser("fname$it", "lname$it")
}
}

scenario "can remove a user", {
when "user is removed", {
service.removeUser(0)
}
then "count is decremented", {
service.userCount.shouldBe 9
}
}

scenario "can remove all users", {
when "user is removed", {
service.removeAllUsers()
}
then "count remove all users", {
service.userCount.shouldBe 0
}
}
}
}
This is a long example. I'm sorry, it sort of needs to be if you're going to show scenarios (think: test methods) nested within one another. Any parent scenario is capable of creating test data that is only visible within the scope of that scenario, including child scenarios. No more restrictions to just one setUp and one tearDown per test! And now, if you want to think about how test methods relate to each other, you can simply examine the indentation. The scoping rules of scenarios guarantees that related tests are going to be grouped together in the file. No more need to scroll through files reasoning about dependencies.

One note about this approach is that scenario given blocks (think: setUp()) do not create a fresh fixture; the scenario given block is run once for all the child scenarios to reuse, not one for each child scenario. This is a shared fixture pattern and creates chained tests, whereas the xUnit setUp does not. Perhaps there is a way for nested scenarios to have fresh fixtures from given blocks, but I'm unaware of it.

So regardless of your skepticism for behavior driven development, using Groovy and easyb for testing can bring benefits in test understandability and maintainability. Easy.