Wednesday, July 29, 2009

10 Second Code Review

Weighing in on code reviews are all the rage.

Along the lines of getting a group to start having code reviews... when I hear that code reviews are too time consuming my reply is, "Hogwash! I can do a code review in 10 seconds without even scrolling down the source file."

Just look at the import list in this worst case example:

import com.mycompany.services.UserService;
import com.mycompany.services.UserServiceImpl;
import javax.persistence.EntityManager;
import javax.swing.JFrame;
import com.thirdcompany.COMBridge;
import javax.swing.JLabel;
Dependency Inversion Principle - The presence of a service interface and a service implementation (UserService and UserServiceImpl) means the developer is probably instantiating the concrete dependency somewhere. Reject the code on grounds of not using the IoC container.

Separation of Concerns - The presence of EntityManager (persistence) and a JFrame (user interface) means that code working with the database is intermingled with user interface display. Reject the code on grounds of poor separation of concerns.

Programming to Interfaces - The COMBridge import from a 3rd party package indicates that risk-laden dependencies have not been abstracted out of the core business logic. Reject the code on grounds of no programming to interfaces.

Broken Windows - Imagine that the JLabel import is gray in the IDE because it is unused. Code should compile with no warnings, and all warnings should be cleaned before the code review begins. Reject the code on grounds of sloppiness.

OK, so this is a little facetious. I don't really do code reviews in 10 seconds. The point is that there's a wealth of information available with little effort on the reader's part. Code reviews are not a big commitment. Hopefully, you'll have more than 10 seconds budgeted for this. Maybe you have as many as 30 seconds! In that case all you'll need to do is look at the type signatures within the class.Easy.

IntelliJ IDEA 8 - The Good Parts

I keep getting asked if the upgrade from IDEA 7 to IDEA 8 is worth the cost.

While all the new features are listed on the IDEA site, these are my favorite 5 features of IDEA 8, listed in the order I like 'em best.

Database Support
The new SQL Console means you now get code completion, syntax highlighting, and error highlighting in your SQL scripts. Plus, no more launching a 2nd application to run queries. Very useful, but does seem to work better in MySQL than MS-SQL.

7 new Java Refactorings
The most useful of the new rafactorings are Extract Method Object, which allows you to extract method on blocks with more than one result type, and "Introduce Parameter Object" to compact long parameter lists. Use with care, you may not end up with a meaningless abstraction in your object model. Also, Introduce Constant got a big upgrade that lets you extract just parts of big static strings. Nice!

UML Diagrams
You can create diagrams right in the IDE now. I think there were some plugins in the past that allowed this, but now a nice version of the feature is available in IDEA. You can generate diagrams, and can also create new entities, refactor, and navigate directly to source code. The diagrams look great; I've used them in some presentation already.

Groovy & Grails Support
Improved Groovy support adds a couple notable improvements: better code completion, more inspections, two new refactorings including "Convert method parameter to map-parameter entry", debugger support for Gant(!), and a whole bunch of Grails stuff.

Debugger for Flex (and Javascript)
We're using FlexBuilder for official Flex development at work, but for me, who does mostly Java, I've found it useful to use the IDEA Flex debugger when I don't feel like launching a 2nd huge application on my workstation. We evaluated IDEA 8 as a replacement for FlexBuilder and decided not to, but we'll take another look at IDEA 9 Flex support and maybe switch then. There's also a Javascript debugger but I haven't touched that language in a year or so.

Honorable Mentions

Dataflow to This - Shows you how a certain variable got the value it did. Think of it as a better call stack window.

Thread Dump Analyzer - The new window is way easier on the eyes than scanning through text thread dumps. Nice.

Spring 2.5 support - Use it every day so that some of the new Spring annotations are recognizable and navigable.

IDE Settings Synchronization - Share all your IDE settings between several workstations.

Those are the things I use the most... there is, of course, way more new than that. If you know me and want a 60 day trial license (normally they are only 30) then drop me an email!

Or check out the IDEA 9 EAP.

GUM, OTUG, 2GX, and Strange Loop, oh my!

I'm going to be out on the road September and October, talking about programming and testing and maybe trying to make people laugh a little. Here's my schedule so far:

September 8th - Minneapolis, MN - Groovy Users of MN - Groovy+OSGi Jumpstart
September 15th - St. Paul, MN - Object Technology User Group - Thinking in Functions
October 19th - 22 - New Orleans, LA - 2GX Groovy/Grails Conference - All 4 talks for 1 low price!
October 23rd - St. Louis, MO - Strange Loop - Groovy Compiler Metaprogramming for Fun and Profit

If you haven't registered for 2GX, get on the stick... early bird pricing ends soon. And if you haven't heard of Strange Loop, then be sure to check out this super affordable unique and esoteric event.

I'm definitely interested in practicing these talks as much as possible, so if you need a speaker for a JUG or work group just let me know. The legacy code talk has turned out to be a really fun event, and it can have as little or as much Groovy as you want. Southwest has super cheap airfare right now... all I need is an invite.

Here are the summaries for the talks:

Groovy Compiler Metaprogramming and AST Transformations (aka Groovy Compiler Metaprogramming for Fun and Profit)
'A language should have access to its own abstract syntax' John McCarthy, Father of Lisp. Well, now Groovy 1.6 does! This talk is about why AST transformations are important, what you can do with them, and where the language world is headed. We'll dive into some of the useful Groovy annotations and libraries being written that harness AST transformations, see how to write our own, and work with the AST tools coming out with the next version. At the end we'll prognosticate about the future of programming languages in general, and hypothesize about where the Groovy features fit into the history of languages. Fun!

Functional Groovy (aka Thinking in Functions)
For many, learning Groovy made you think differently about Java. Now it's time to think differently about Groovy. Although Groovy is not a functional language by many measures, it does support many of the common functional idioms and patterns. Come explore both how far functional programming can be pushed in Groovy, where functional programming can't currently go, and where functional programming is headed in future releases of both the language and the JVM. Learn about morphisms, option types, tail call optimization, pattern matching, and functional composition in the context of solving classic CS problems side-by-side with a more traditional functional language, and decide for yourself how terms like elegance and simplicity should drive your coding.

OSGi and Groovy Jump Start
OSGi, Jigsaw, modularity, service lifecycles, bundles... where do you start? This talk covers the basics of using OSGi and Groovy together. You'll be introduced to the OSGi framework by building a Groovy based application that introduces the core concepts of OSGi such as the module system, service registry, and service life cycles. We'll also cover common pitfalls encountered by mixing Groovy and OSGi, as well the latest OSGi tools available.

Legacy Code, Groovy, and You
Thinking about writing Groovy unit tests for your legacy Java code? This session is an honest discussion about what Groovy will gain youand what it won't. Come learn the engineering practices and tools that you can use to battle tight coupling, monolithic projects, and tangled dependencies, and then decide for yourself whether Groovy is the answer for your project. Plan on returning to work with a vision of what your team can do to write better software.

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.

Wednesday, July 15, 2009

Patterns of Enterprise Cruft: Generic Object Factory

Hmmm, what to do about unit testing a production component that clearly needs to call an object's dependency laden constructor...

My last post detailed the subclass and override approach, which is a simple, non-intrusive mechanism to allow you to mock out constructor calls. An alternative that a lot of people reach for is to create some sort of generic object factory that provides a layer of indirection across all constructor calls. This sounds like a decent enough idea. Let's see how far we can take it before things go wrong.

As context, imagine a system of legacy business objects with persistence baked into the interfaces. This means that persistence and domain objects are not separate and there is no entity manager... a pretty common legacy scenario in my experience.

An example document-style service to work with User objects would just move data from DTO objects into the database:

public class UserService {

private DataSource datasource;

public void create(UserDTO input) {
User user = new User(datasource);
user.setFirstName(input.getFirstName());
user.setLastName(input.getLastName());
user.save();
}

// read, update, and delete methods omitted
}

A naive indirection to provide would be to extract the constructor call to "new User(datasource)" into a separate UserFactory object, which could then be mocked out for testing. The problem is that the 1-to-1 correspondence of domain objects to factory objects doubles the number of classes in your system. This abundance of classes is fine if your entire domain consists of about five objects. But if that's the case you don't really have an enterprise, do you? You should just refactor the objects to not couple the domain and persistence and stop reading these blog posts. But if your domain is 250 objects, creating 250 factories starts to look like a hassle.

No, clearly we need a generic factory that can furnish your services with any type of domain object that is requested. Something like a Registry object from Fowler's PEAA, but just to dole out instances of new objects. If the service were refactored with this factory in mind, then testing is as simple as mocking out factory in the example below:
public class UserService {

private ObjectFactory factory;

public UserService(ObjectFactory factory) {
this.factory = factory;
}

public void create(UserDTO input) {
User user = factory.make(User.class);
user.setFirstName(input.getFirstName());
user.setLastName(input.getLastName());
user.save();
}
}

You can use a mock object framework like Mockito to help you in this endeavor. Mockito is nicer than some other frameworks because it allows you to verify individual methods being invoked rather than all interactions with a particular object. This lets your test methods follow William Wake's arrange-act-assert sequence and makes your tests more understandable:
    import static org.mockito.Mockito.*;

// arrange
User user = mock(User.class);
ObjectFactory factory = mock(ObjectFactory.class);
when(factory.make(User.class)).thenReturn(user);

// act
UserService service = new UserService(factory);
service.create(new UserDTO("fname", "lname"));

// assert
verify(user).setFirstName("fname");
verify(user).setLastName("lname");
verify(user).save();

Easy. And the best part of all this is that ObjectFactory is fun to write. You get to use generics and reflection! Wheee! It's as simple as internally holding a map of interface types to implementation types and reflectively calling a standard constructor when one of the objects is requested:
public class ObjectFactory {

private Map<Class, Class> classToType = new HashMap<Class, Class>() {{
put(User.class, User.class);
}};

private DataSource datasource;

public <T> T make(Class<T> clazz) {
try {
Class type = classToType.get(clazz);
if (type == null) throw new RuntimeException("Type not found: " + clazz);
Constructor constructor = type.getConstructor(DataSource.class);
if (constructor == null) throw new RuntimeException("Constructor not found: " + clazz);
return clazz.cast(constructor.newInstance(datasource));
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

I've officially seen 3 variations of this implementation, but they're all pretty similar. As long as you have a standard constructor then this approach works. If by working you mean you can get test coverage using mock objects and verifying side effects.

What happens when your objects don't share a common constructor and dependencies? Spring to the rescue! You can define a specific Spring factory for your domain objects and then the ObjectFactory can retrieve new prototyped-scoped beans by type whenever one is requested. The implementation is a little simpler in Java but hiding behind it is the complexity of the XML configuration:
public class SpringObjectFactory {

private XmlBeanFactory factory = new XmlBeanFactory(
new ClassPathResource("objectFactory.sping.xml")
);

public <T> T make(Class<T> clazz) {
Map<String,T> beanMap = factory.getBeansOfType(clazz);
if (beanMap.isEmpty()) throw new RuntimeException("No beans found of type: " + clazz);
if (beanMap.size() > 1) throw new RuntimeException("Too many beans found: " + beanMap.keySet());
return beanMap.values().iterator().next();
}
}

This is kinda nice. So why is it a Pattern for Enterprise Cruft?

What was the root problem again? Oh yeah, the persistence layer was baked into the domain layer, they were not separate.

Does a generic object factory solve this problem? Clearly not. It only solves how to test a system written like this.

Does a generic object factory drive us closer to solving this problem? By most accounts, the solution is removing persistence from the domain objects and placing it in some sort of entity manager. An entity manager would handle saving the domain objects but not creating them. In the future, it would be the entity manager that would be mocked out not the domain object constructor itself. So no, a generic object factory is not going in the right direction. All of out unit tests rely on mocking the domain object instantiation logic, not the save logic! In the future, the instantiation of the objects isn't going to change, but the saving will. When it comes time to create a DAO layer we'll have hundreds of fragile mock-sensitive unit tests that are worthless and need to be rewritten. A better solution is to leave the constructors alone and introduce a generic save mechanism, not a generic construction mechanism. That would be a design that is a step close to a DAO layer.

Is a generic object factory a good short term solution to getting higher test coverage? If your problem is low test coverage, then this approach can fix that. But what was the root problem again? Persistence, not testability. So consider the alternatives. Subclass and override is simpler to the production code at the cost of having extra subclasses in the test tree. However, you can get around this by testing with partial mocks, and the technique at least does not move you away from a more appropriate solution.

A bigger risk of introducing a generic object factory is death by a thousand clever ideas. It's not your object factory that is so complex. It's that there is probably another one from the team down the hall. And a third tucked inside another module somewhere. And pretty soon you have a 100 different points of cleverness to deal with, and all those clever spots aren't really solving your problem, they're just getting you to (hopefully) hit a delivery date and be proud of your coverage. As far as I can tell, a whole bunch of "Enterprise Complexity" lies in accumulated clever solutions that solve problems one layer away from the root cause. So, I'll ask one last time: What was the root problem? Beware solutions that don't address the answer to this question.

And welcome to the Enterprise!

Tuesday, July 7, 2009

Groovy+Testability: Maybe not the killer feature

When your only tool is a hammer... and your metaphorical hammer is Groovy... then you'll find yourself losing a lot of arguments about when it's appropriate to use Groovy. Which is where I found myself Friday afternoon, arguing that the best way to solve our testability problem was to change our file extensions from .java to .groovy (I suppose changing the compiler from javac to groovyc would be required too but I hadn't thought that far ahead).

See, we're in a really painful spot. We're rolling out a new web service framework and unit test coverage is hovering in the low teens. Ouch, that's just awful. The problem is that we're hamstrung by a massive set of legacy business objects that have persistence baked into their interfaces. Our new services are mostly just exposing a new set of domain objects that move data back and forth between the old business objects.

How do you write a Java unit test for a document style service whose simplest implementation looks something like this:

public class UserService {

private DataSource datasource;

public void create(UserDTO input) {
User user = new User(datasource);
user.setFirstName(input.getFirstName());
user.setLastName(input.getLastName());
user.save();
}

// read, update, and delete methods omitted
}
The constructor call to the User business object (that importantly requires a datasource) needs to somehow be mocked out. A natural solution in Java would be to introduce a UserFactory that simply wraps the constructor call with a layer of abstraction. But nobody really wants to create factories just to wrap constructors. What a headache. Groovy's mockFor class offers a simple way to mock out constructor calls. Here is what the body of a unit test would look like if the service were written in Groovy instead of Java:
public void testCreate() {
def userMock = new MockFor(User)
userMock.demand.setFirstName { assert it == 'Michael' }
userMock.demand.setLastName { assert it == 'Jackson' }
userMock.demand.save { }

userMock.use {
def service = new UserService()
service.create(new UserDTO('Michael', 'Jackson'))
}
}
mockFor and stubFor have been getting a bad rap lately, but they are very convenient ways to mock out constructor calls. Just create the mock, set up some expectations/demands, and then use it within a 'use' block. The problem is that the constructor can only be mocked out when invoked from a Groovy class and not from a Java class. And hence my arguing for using Groovy in our service layer. Easy testability. Groovy for the win. Just switch the file extension and viola.

There's a fairly obvious and pure-Java alternative: subclass and override. Adding a layer of abstraction in Java doesn't just mean a factory or a new interface. Inheritance works just fine. Instead of wrapping the constructor call in a new class, just wrap it in a protected method, and let a test-specific subclass override and mock out the object:

Here is the production Java service:
public class UserService {

private DataSource datasource;

public void create(UserDTO input) {
User user = makeUser();
user.setFirstName(input.getFirstName());
user.setLastName(input.getLastName());
user.save();
}

protected User makeUser() {
return new User(datasource);
}
}
Now the makeUser() method can be overridden and mocked out in a subclass. Here is the passing Java unit test:
@Test public void testCreate() {

MockUser mockUser = new MockUser();
UserService service = new TestingUserService(mockUser);
service.create(new UserDTO("Michael", "Jackson"));
Assert.assertEquals("Michael", mockUser.getFirstName());
Assert.assertEquals("Jackson", mockUser.getLastName());
Assert.assertTrue(mockUser.saveWasCalled);
}
Not horrible. Not horrible. It's pure Java. No libraries other than JUnit. That's important to a lot of people. I did have to mark the production class as not final, which might bug some folks. I cheated a little in the example by not showing the test specific subclass of UserService. I had to define that as an inner class within the TestCase:
private static class TestingUserService extends UserService {
private User user;

TestingUserService(User user) {
this.user = user;
}

@Override
public User makeUser() {
return user;
}
}
That's an added bit of cruft that the Groovy version didn't have, but any decent IDE will generate this quickly for you. I also cheated by not showing the mock User object, which I handrolled in my example but could easily be replaced with a mock object framework:
private static class MockUser extends User {
private boolean saveWasCalled = false;

MockUser() {
super(null);
}

@Override
public void save() {
saveWasCalled = true;
}
}
So was it all worth it? On the Groovy hand, you get testability within about 8 lines of code by using Groovy. On the Java hand, you get testability in about 40 lines but you get to stay inside the cozy little Java box and not get worried about introducing new languages. The point is that you don't need to settle for low test coverage just because you're using Java. There are a lot of techniques available beyond what Groovy offers. Subclass and Override is described in Working Effectively with Legacy Code, and that's a great place to start if you want to add more tools to your Java testing toolbox. Is Groovy testability really the killer feature that is going to make you switch languages? Not likely in this scenario.