Pathfinder Blog
Topic Archive: Unit Tests

GWT Testing With Groovy? (Heck yeah!)

Speaking of GroovyTestCase, I experimented a bit with using both it and JMockit as an alternative to GWTTestCase.  This may sound strange at first-- after all, the point of GWTTestCase is to exercise your code in the way it will eventually execute as JS at runtime.  What I've effectively done is to run my tests from within Groovy against GWT classes compiled-as-Java.  First I will go through an example of what I'm talking about, then I will summarize some of the thoughts I had as a result of going through this exercise.

Below I have an implementation of KeyboardListener which modifies the contents of a TextArea based on keypress.  I want to test the behavior of this listener.  Here's what I did:

1) Write a test.  I did this using Groovy, but you could just as easily write it in Java using JUnitTestCase if you prefer.  This particular test verifies that my listener will append an equal amount of whitespace to the next line when the <enter> key is pressed, and position the cursor at the end of that new line.  Very simple stuff, but worth testing even outside of GWTTestCase.  I find that the Groovy style keeps this test case a lot shorter than it would otherwise be in Java.

class SampleTest extends GroovyTestCase {
    private static final char KEY_ENTER = (char) KeyboardListener.KEY_ENTER
    private static final int NO_MODIFIERS = 0;

    protected void setUp() throws Exception {
        Mockit.redefineMethods(GWT, MockGWT)
    }

    public void testEnterKey() {
        def keyListener = new MyKeyListener()
        def textArea = new TextAreaFixture(text: "    abcd", cursorPos: 8 )

        keyListener.onKeyPress(textArea, KEY_ENTER, NO_MODIFIERS)

        assertEquals "Content is incorrect", "    abcd\r    ", textArea.text
        assertEquals "Cursor position is incorrect", 13, textArea.cursorPos
    }
}

class TextAreaFixture extends TextArea {
    String text;
    int cursorPos;
}

2) Mock out com.google.gwt.core.client.GWT.  This ultimately comes down to mocking out the 'create' method.  Notice below that we make a special case for 'DOMImpl.class'.  The reason for this is that the actual DOMImpl is decided at runtime.  It is also referenced in the constructors of the widget we are testing (i.e. 'TextArea()').  Note that this class needs to be a Java class (i.e. non-Groovy) due to the way in which JMockit redefines methods on existing Java classes.  As for why I return 'null' for everything else, I do this to fail fast in any cases I'm not testing.  As it turns out, this is all I need for the testcase above.

public class MockGWT {
    public static Object create(Class classLiteral) {
        try {
            if (classLiteral.equals(DOMImpl.class)) {
                return new MockDOMImpl();
            }
            return null;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

3) Subclass com.google.gwt.user.client.impl.DOMImplAh-hah!  Here's the catch... This step provides us just enough code to satisfy construction of our Widgets.  For my purposes, I let my IDE generate this subclass for me, and stuck with the default implementations it generated.  I return an instance of it above.

public class MockDOMImpl extends DOMImpl {
    public Element createElement(String tag) {
        return null;
    }
    [...]
}

The approach to this style of testing intercepts any calls on the Widgets themselves before anything is allowed to hit the underlying DOM implementation.  What I provide above is just an example of how this could be done, specifically when testing behavior of custom classes that happen to inherit or reference GWT classes.  Testing things like layout or UI concerns is another matter, but one which I would not consider 'interesting' enough for unit testing, since most of the behavior on the UI can be easily inspected by viewing Widgets as simple beans.

So why would you want to attempt this anyway?  First, I happen to like working in Groovy, so I crave more reasons to do exactly that.  Second (and more pertinent), much of behavior I find interesting in GWT apps revolves around simple message passing.  I trust GWT enough to do its job once I leave the Java space.  Beyond this are some philosophical differences I have with GWTTestCase, particularly since GWTTestCase makes it hard to maintain a larger body of unit tests, requires additional configuration in your module file (or as I've done before, constructed a different "test-only" module file that inherited from two module files), did not let me set up tests the way I would like to, etc.  I could go on.  When unit testing, very little of the logic I write is made less interesting or less relevant outside of a JS runtime environment, so where possible I would like to gain some benefits from treating everything as Java.

There are other benefits.  There's the noticeable speedup in execution time when running entirely within the JVM.  There's also less restrictions on the test class itself with regards to instance variables, language (i.e. Groovy), dependencies in outside packages, etc.  Why wouldn't I want such flexibility in my test code?  I really want my test code to be as concise and expressive as possible, particularly as my apps get larger and more complex.  I think having alternative ways of approaching this kind of testing brings a lot of these types of benefits.

Live Ruby: Testbed, part 1

In this series of posts, I’m going to walk through the implementation of an interesting Ruby problem, namely, using metaprogramming to create a small DSL-like syntax for specifying tests.

Here’s the problem as I notice it in my own unit testing: I tend not to go back and ensure that multiple input values for a method work — worse, I don’t often check for error conditions or possible corner cases.

The main reason for this, I think, is a) wanting to move on to the next thing, and b) not wanting to take the time to refactor the test to make adding another test call simple. What I really want is something where the test is essentially pre-factored, so that adding a new call is easy. The newest test frameworks on Java use function decorators to specify multiple sets of data over the same test.

In Ruby, we can achieve the same effect via metaprogramming, which allows a clean enough API to make specifying new tests easy.

I think I want the syntax to look like this:

testbed "call my test function" do |input|
subject = MyObject.new(input)
subject.method_to_test
end
verify_that(1).returns("fred")
verify_that(2).returns(3)
verify_that(0).raises(Exception)

In other words, using something similar to the way Rake matches descriptions to tasks. Define a testbed to perform some assertions on a given set of data, then assert any number of different instances of the test using verify_that. Each verify_that is automatically associated with the most recent testbed, and gets converted to an actual test method called when the test class is run.

So, how do you implement this, and how do you test it? Here’s the first test I wrote:

require 'test/unit'
require '../lib/testbed'
class TestbedTest < Test::Unit::TestCase

class FakeTestA < Test::Unit::TestCase
def test_something; true end
end

class FakeTestB < Test::Unit::TestCase
def test_something; true end
end

def test_creating_a_testbed
FakeTestA.testbed("this is a fake testbed"){ |a| a * 2 }
assert_equal("this is a fake testbed", FakeTestA.current_testbed.name)
assert_equal(4, FakeTestA.current_testbed.block.call(2))
FakeTestB.testbed("a different fake testbed") { |a| a * 3 }
assert_equal("a different fake testbed", FakeTestB.current_testbed.name)
assert_equal(6, FakeTestB.current_testbed.block.call(2))
assert_equal("this is a fake testbed", FakeTestA.current_testbed.name)
assert_equal(4, FakeTestA.current_testbed.block.call(2))
end

end

First off, I created a pair of fake test classes to use later on (I gave them a single test to prevent Test::Unit from complaining when I run the tests). The actual test method explicitly calls the testbed method on the fake classes, mimicking the actual usage shown earlier. What I’m testing here is that the testbed call places an object in a current_testbed slot so that it can be referenced by later calls to verify_that.

(I test it on both fake classes to verify that multiple classes can hold separate values in the class variable at the same time).

The first round of implementation looks like this:

module Test
module Unit
class TestCase

class << self
attr_accessor :current_testbed

def testbed(string, &block)
self.current_testbed = Testbed.new(string, block)
end
end
end

class Testbed

attr_accessor :name, :block
def initialize(name, block)
@name = name
@block = block
end

end

end
end

So far, this is pretty simple. I’ve created a Testbed class to hold a name and a block. I’ve also opened up the TestCase class to add the class method testbed. Right now, that method does nothing more than store the string and the block in a Testbed instance, and stores that instance in a class-level attribute called current_testbed.

The way in which the class method and class attribute are set up is very Ruby specific. Each object in Ruby has a special attribute called a singleton class. If filled, the singleton class can have it’s own methods and data, and that class is checked for method names before the object’s own class or any of it’s superclasses. This allows an individual Ruby instance have unique behavior — different from other instances of the same class — just by placing different methods in it’s singleton class.

To define a singleton class, you use the form:

class << obj
end

Where obj is the instance whose singleton class you are defining. (An instance only has one singleton class. If you define multiple blocks for the same object, they are all added to the same singleton class.)

In this case the object in question is self, which when referenced outside a method definition refers to the class being defined. In Ruby, classes are objects just like anything else, and they can have singleton classes. This gets a little strange when dealing with instances of the class Class, but the basic idea is that adding methods to the singleton class is equivalent to adding instance methods to the class itself.

The testbed method, which is defined in the singleton block, becomes an instance method of the class TestCase, which means it can be invoked as a Class method as in:

FakeTestA.testbed("this is a fake testbed"){ |a| a * 2 }

The nice thing about using the singleton format, rather than using regularly defined class methods and attributes, is that each subclass of TestCase will get it’s own singleton class, and therefore each can have its own current_testbed attribute, which is the functionality we want.

That’s going to be it for Part 1. Next time, I’ll implement the verify_that method chain.

Lessons Learned From Domain Modeling

There are many lessons I've learned as a result of working in a more domain-driven way.  My recent work on the UI front has highlighted a few ideas that are just as applicable to other areas of application development (outside the sphere of, say, modeling a complex domain).  Here are three things I believe developers should always keep in mind when designing or implementing code.

  1. Hierarchies require coordination between their roots.
  2. Uniqueness adds complexity.
  3. Null holds meaning, but it's meaning will never be consistent.

Like learning how to write a good unit test, these are simple concepts to explain, but each requires patience and experience to understand really well. (a good pairing partner never hurts either!)

Hierarchies Require Coordination Between Their Roots
A graph of objects often needs to interact with another graph of objects, and while it is initially faster to build direct dependencies between members of each group in an ad hoc fashion, in the long run you benefit from controlling access to those members through the root of each group/hierarchy.  I see this as an extension to the principle of encapsulation applied to hierarchies of objects (ala: Law of Demeter). 

Consider the general case of one object acting as an observer of another.  If there are notable side effects in the handling of an event up or down the graph, it makes sense to put the root in control of the event.  Refactoring across the hierarchy become easier, adding additional behavior introduces fewer edge cases (thus reducing the need for more complicated testing), behavior more predictable etc-- the only exception (as I see it) would occur when the type of messages being passed around do not affect state at all.  Which brings us to our next point:

Uniqueness adds complexity
Stateless systems are invariably easier to grasp and comprehend than stateful ones.  While stateful systems have a temporal dimension to them which is largely absent in stateless ones, this is not the only source of such complexity.  It is the interaction between two or more stateful systems where we begin to see the huge cost in terms of managing complexity (recall your first experience debugging issues in badly written multi-threaded code to remind yourself of this).

This is why value objects are so important as a concept, and why their use is so prevalent in domain-driven design.  While the identity of a value object is determined by it's state, it's state is invariant, so it does not have to be managed the way an object with variable state needs to be managed.  But the use of VO's in domain-driven design is just one manifestation of the broader concept: always strive to reduce the number of parts in an application which rely on uniqueness (even if this requires a few more parts added to the whole), whether you are writing domain logic, UI behavior, etc.

The Meaning Of Null Is Never Consistent
It is easy to miss this point, as witnessed by how often I see code which uses null as a substitute for "I Don't Know...", "Shouldn't Really Happen...", "Just Satisfy The Compiler..." or "This Is A Placeholder".  In reality, null (or nil) is often employed as a mechanism for passing the buck to someone else.  Try as you might to ascribe a single meaning to it for all cases in your API, client code will feel free to redefine this meaning on a case-by-case basis, and its meaning will evolve (or devolve, as the case may be) into code which looks defensive, but behaves unpredictably.  Avoid returning null when possible-- strive for clarity instead.  While in other languages (such as Ruby) it is possible to add behavior to the concept of null, thereby making it's contract with the rest of the code a bit clearer, I'd still choose the alternative, and use something else.

That's it-- three little things that come in handy just about anywhere. My initial intent was to write a line or two for each section, but as you can tell, there is so much to say on each topic, and all of this just scratches the surface.

About Pathfinder

  • We design and build extraordinary applications for companies looking to make the next great idea a reality.
  • learn more

Topics

WordPress

Comments about this site: info@pathf.com