Pathfinder Blog
Topic Archive: Test Driven Development

TAE Boston 2008: The Unsexy Presentations

Lets face it, most people come to Ajax conference for the eye candy. TAE Boston 2008 is no different, and the jQuery, Dojo and other sessions are packed. That's great. I love good eyecandy. But the shame is that many folks skip the less sexy presentations, such as today's presentation by Ted Husted entitle Ajax Testing Tool Review. Talks like these and the tools and methods they discuss is what is leading to the "professionalisation" of front end development, as my colleague Brian Dillard likes to say.

Some of the highlights from Ted's talk:

  • If you like CruiseControl, but it's too fiddly for you, you'll love Hudson, a much more user friendly continuous integration engine.
  • The Selenium IDE is great for getting started or smoke testing, but use the API's (in Java, C#, Ruby, etc.) to get real, supportable unit tests done.
  • YUI Test is intrusive, but it overcomes some of the shortcomings for testing asynchronous events that are present in JsUnit and Selenium. See Ted's post on YUI Test.

OK, not sexy, but if you want to develop quality software, you have to keep an eye on the non-sexy bits.

Web 2.0 Expo: Behavior-Driven Development with Rails and RSpec

Web_20_expo
At today's Web 2.0 Expo, Greg Pollack of Rails Envy introduced me and a few hundred of my latest acquaintances to Behavior-Driven Development. Basically a mash-up of Test-Driven Development and Domain-Specific Langauges, BDD empowers developers to turn English-language spec documents into working test suites with a minimum of fuss.

Pollack's talk was titled The Art of Testing Web Applications, but his copious code examples skewed, unsurprisingly, toward Rails. Easily mixing high-level concepts with nitty-gritty code, Pollack showed how to turn existing Rails unit and integration tests into BDD tests using the RSpec framework. Although the translation from one testing framework to the other seemed almost 1:1, the difference in readability was striking. I can actually see clients and product managers/business owners using these test suites in the real world.

Continue reading »

Lesser Known Test Processes

Testtube
While Test-Driven Development (TDD) and Behavior-Driven Development (BDD) get all the headlines, thousands if not millions of developers have worked out their own ad-hoc variations on these processes. This is a list of alternate testing processes, some of which are useful, some of which less so. It's a different way of thinking about the benefits of doing testing -- at the very least, it's a way to think about the costs of backsliding on TDD.

Data Driven Testing (DDT)

Also Known As: Begging The Question, Blank Box Testing

Process Description: Write your tests first as in normal TDD, however instead of actually asserting an expected value, assert against a blank value (as in assert_equal(nil, user.batting_average)). The test, of course, fails. You then fill in the expected value based on the result of the failing test. Bingo! The test passes.

Pitfalls: If you aren't careful, this turns in to Tautology Based Testing. Specifically, you need to verify that the returned value really is what you expect. If you are doing this too often, it may mean you don't really understand what your code is doing.

Actual Uses: There are a couple of benefits to this testing process. First off, it guarantees a failed test the first time around, which is proof that the basic test setup is correct, and that you are testing the item that you think. This is also useful in cases where the correct answer is easier to verify than to generate by hand (a long string, for example). It's preferable to use the literal result of the actual program then a separate non-literal calculation of the answer, even if you paste in the literal result.

Continue reading »

New Year’s Resolutions 2008

As I've posted before, I'm pretty leery of prognostication. My colleageus Noel and Dietrich have already made their predictions for 2008, anyway (here and here) so who am I to join the fray? Instead, let me dust off another hoary device and share my programming resolutions for 2008.

Continue reading »

RSpec and Rails Custom Form Builders

I'm working on a small project and trying to use RSpec as the complete testing solution. First thing I did was copy over an existing custom FormBuilder which puts everything in a nice tabular layout. Then I tried to convert the existing Test::Unit tests to RSpec specifications.

I banged my head against this for a few hours, at least partly because the normally-infallable Google-based tech support failed to expose a clear example. So I figure I should at least get a blog post out of it.

The form builder is technically a helper, so it goes in app/helpers, and the test goes in spec/helpers. One problem -- the custom form builder expects to have access to template object and calls content_tag on that object to format the output. Normally, the template object is automatically placed in @template during evaluation. But since RSpec is testing just the helper, and not an associated controller or view, there is no template object.

At first I created a mock template object that just imported the relevant Rails helpers, but then I actually read the documentation in more detail and learned that the RSpec HelperExampleGroup class, which manages helper tests, already imports all those helper modules. So, I can set up my specs like this.

before(:each) do
@object = mock_model(Project)
@object.stub!(:longname).and_return("Long Name")
@builder = TabularFormBuilder.new(:project, @object, self, {}, nil)
end

The first two lines of this just set up a mock object. The key line here is the last one, where the form builder is created with arguments representing the model, the instance, the template, and then options. The template is represented by self, meaning the RSpec HelperExampleGroup, which will respond to content_tag.

Now I was able to write all my specs against the template and use the have_tag and with_tag predicates to validate the output, like so:

it "should build input fields" do
@builder.text_field(:longname).should have_tag("tr") do
with_tag "td.tdheader"
with_tag "label[for *= project_longname]", "Longname"
with_tag "td" do
with_tag "input.text_field#project_longname[name *= longname][size = '30'][value = 'Long Name']"
end
end
end

One other nice feature of the helper specs in RSpec is the ability to directly evaluate ERB. This is designed to be used for validating helpers that take ERB blocks as arguments. Use as follows:

eval_erb("<% table_form_for (@object) { |f| f.text_field(:shortname) } %>")

The method being tested looks like this -- it wraps a form inside an HTML table so that the custom form builder's table layout will render properly:

def table_form_for(name, *args, &proc)
concat("<table>", proc.binding)
form_for(name, *convert_args(TabularFormBuilder, args), &proc)
concat("</table>", proc.binding)
end

The eval_erb method returns a string, which you can then validate. Note that if you are using it to test a form_for derivative like this, you also need to place the following stub method in your spec file's describe block:

def polymorphic_path(args)
"http://a.fake.url"
end

The polymorphic_path method is used within Rails to convert something like form_for(@object) to the RESTful URL that the form should be submitted to. Normally it's an method of the controller, but in the RSpec helper environment, there is no controller.

There's another issue when validating this form builder. Unlike a typical ERB block, the custom form builder implementation of f.text_field explicitly uses the template object to write output. The eval_erb method does not seem to work as I expected in this case -- the output from inside the block does not appear to be saved.

In other words, when running the eval_erb call above, the resulting string contains the table tag created by the table_form_for method, and the form tag created by form_for. The table rows that are built by the custom form builder itself, however, do not show up in the output. I was able to verify that the output is being generated, so either it's not being stored by the RSpec object, or I still haven't completely figure out how to tie these things together yet.


If you found this example helpful, you might also enjoy my upcoming book Professional Ruby on Rails, scheduled to be published in February, 2008.

assertNotNull(”the long road to recovery”)

The use of 'assertNotNull' should be discouraged.  Those of you who have been testing for a while will not be as surprised by this statement, but I think it's worth repeating since I still see many developers who rely too heavily on this-- the weakest kind of assertion you can make about your code.

So what's wrong with 'assertNotNull'?  Put simply, it's a crutch.  If I could vote it off the island, I would.  It is used as a way of testing code in a way that adds only a modicum of value.  In fact, I'd go so far as to say that if you rely solely on 'assertNotNull' in your test methods, you're probably writing buggy code, and seeing it used in existing test cases should make one question the implementation.

Continue reading »

GWT+ IntelliJ Productivity Tip

If you are an IntelliJ user doing GWT development and you haven't already done so, make use of the boring yet incredibly useful Alt n 8 plug in.  It's either available via the link, or just look for it in the plug-ins panel within IntelliJ.

I can't say enough about this particular plug in, and I'm surprised (based on the paltry number of downloads) more people don't make use of it.  It's a very underrated plug-in for IntelliJ for a couple reasons, but first let's go through an example of how I find it useful for GWT development.  Combined with other keyboard shortcuts, it turns out to save quite a bit of time when performing the following code traversal (starting at a test case for a service implementation class):

  1. (alt-8) -> Jump from Test to Service Implementation
  2. (ctrl-u) -> Jump from Service Implementation to Service Interface
  3. (alt-8) -> Jump from Service Interface to Async Interface
  4. (alt-7) -> find usages of...

That's four keystrokes to move from server-side test case to finding usages of the service on the client-side.  Alt n 8 allows you to use regular expressions to switch between any two files based on naming conventions.  There are only four such rules I need to make this happen (rules below are applied in order so that the first match wins):

Altn8

I suppose if you were so inclined, you could even shorten the example above into two keystrokes (moving from (.*?)ServiceImplTest.java -> $1ServiceAsync.java.. but I find the shortcuts above useful enough as is.

Maybe these shortcuts only save me seconds or a minute of typing per day, but I find the difference to be substantial when it comes to following a train of thought from looking at a test case for server side implementation classes to finding client code that exercises the same code.  No need to type in class names, navigate menus etc.

The usefulness here to test-driven development should be obvious as well.  Quickly switch between writing a test & implementing the functionality. Good stuff all around.

Live Ruby: Testbed, part two

In Part 1 of this post, I started a to demonstrate using Ruby Metaprogramming to implement a potentially useful testing API:

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)

Last time we covered the testbed call, now, let's move on to verify_that and returns.

The verify_that method is a class method of TestCase, just like testbed. In order for the method chain to work, it needs to return some object that can accept a returns call. There are three options:

  • verify_that can return the TestCase class, and returns could be another class method. I rejected this out of hand, on the grounds that it's kind of ugly, and also feels like it could lead to some tangles if the code gets more complicated.

  • verify_that can return a the testbed instance, and returns can be an instance method of Testbed. I actually walked down this road for a block or two, but it implies that Testbed needs to have a current state for the most recent input and output values. I didn't like the code that produced, and I think it might have some problems later on.

  • verify_that could return a brand-new class, Verifier, which stores a specific state to be verified. This is the design I chose -- I never met a design with extra objects that I didn't like...

The next test covers the creation of the Verifier object:

def test_creating_a_verification
FakeTestA.testbed("this is a fake testbed"){ |a| a * 2 }
verifier = FakeTestA.verify_that(1)
assert_equal(FakeTestA, verifier.test_class)
assert_equal([1], verifier.arguments)
assert_equal(:test_this_is_a_fake_testbed_1, verifier.testbed.method_name(1))
end

The test creates a testbed as before, then simulates another class call, this one to verify_that, then validates that the verifier object knows about the test class, the arguments, and also can work with the testbed to generate the method name for the eventual test.

To make this work, we need to define verify_that, the Verifier class, and Testbed#method_name. Individually, all of these methods are straightforward.

First, define verify_that inside the TestCase class singleton block where testbed is already defined:

def verify_that(*arguments)
Verifier.new(current_testbed, self, *arguments)
end

Right now, the Verifier class is just the initializer -- this needs to be defined inside the Test::Unit module along with the existing Testbed class.

class Verifier

attr_accessor :testbed, :arguments, :test_class, :value

def initialize(testbed, test_class, *arguments)
@testbed = testbed
@test_class = test_class
@arguments = arguments
end
end

Finally, the method name, an instance method of testbed. I'm building the method name up from the name of the testbed and the arguments being verified.

def method_name(*arguments)
"test_#{name.gsub(" ", "_")}_#{arguments.join('_')}".to_sym
end

Okay, the next step is to implement the returns method, which generates an actual test method and verify that the test actually runs. This leads to the philosophical question of how you test a test case. After some banging around with the Test::Unit docs, this is what I came up with:

def assert_test_run(method, error_count, failure_count, run_count, assertion_count)
test = FakeTestA.new(method)
runner = Test::Unit::UI::Console::TestRunner.new(test, 0)
result = runner.start
assert_equal(error_count, result.error_count)
assert_equal(failure_count, result.failure_count)
assert_equal(run_count, result.run_count)
assert_equal(assertion_count, result.assertion_count)
passed = error_count == 0 && failure_count == 0
assert_equal(passed, result.passed?)
end

I'm not prepared to defend this as the best way to test a test case, but it does seem to work. It's creating a TestRunner with quiet output (the 0 argument -- otherwise, you get spurious test running output, which is confusing). It runs the test runner, and validates the various result counts against the passed in values.

The first test is to prove that a returns call creates the method and then allows the method to run correctly.

def test_makes_return_successful
FakeTestA.testbed("this is a fake testbed"){ |a| a * 2 }
verifier = FakeTestA.verify_that(1)
verifier.returns(2)
assert FakeTestA.public_method_defined?(:test_this_is_a_fake_testbed_1)
assert_test_run(:test_this_is_a_fake_testbed_1, 0, 0, 1, 1)
end

The first step in implementing this is Verifier#returns, which simply stores the value, then defers to the test class to create the actual method.

def returns(value)
@value = value
test_class.define_test(self, testbed)
end

This gets a tiny bit hairy. The method is getting created within the test class, but all the data is in the verifier and testbed objects. Ideally, I'd like to actually define the method within returns, but define_method is private, and so has to be called in the test class singleton block, right below verify_that:

def define_test(verifier, testbed)
define_method(testbed.method_name(*verifier.arguments)) do
assert_equal(verifier.value, testbed.actual(self, *verifier.arguments))
end
end

Using define_method makes metaprogramming so pretty... The method being defined takes it's name from the method_name method we just wrote. Then it asserts the equality of the value passed to returns, comparing it to the actual value of the testbed with the verifier arguments, which is a simple block call -- the method is an instance method of Testbed:

def actual(inst, *arguments)
block.bind(inst).call(*arguments)
end

The tricky thing here is that the actual test case instance -- self in the testbed.actual call above, and inst in the arguments to the actual method -- has to be bound to the block. The statement block.bind(inst) sets the value of self within the block being called to the instance. This enables any instance variables created in the test class (in a setup method, for example) to be accessible in the block. Without the bind call, then self inside the original testbed block is the test class, and not the test instance, because when the testbed block is defined, it's defined within a class method.

And that's it -- I'm always amazed at how much you can do in Ruby with just a few lines of code. Some follow up tests prove this works in the case where there's a failing method, and in the case where we want to have multiple verifications against the same testbed:

def test_makes_return_unsuccessful
FakeTestA.testbed("this is a fake testbed"){ |a| a * 2 }
verifier = FakeTestA.verify_that(1)
verifier.returns(3)
assert FakeTestA.public_method_defined?(:test_this_is_a_fake_testbed_1)
assert_test_run(:test_this_is_a_fake_testbed_1, 0, 1, 1, 1)
end

def test_two_methods
FakeTestA.testbed("this is a fake testbed"){ |a| a * 2 }
verifier = FakeTestA.verify_that(1)
verifier.returns(2)
verifier = FakeTestA.verify_that(2)
verifier.returns(2)
assert_test_run(:test_this_is_a_fake_testbed_1, 0, 0, 1, 1)
assert_test_run(:test_this_is_a_fake_testbed_2, 0, 1, 1, 1)
end

And I thought it was worth it to have a separate file test that should work given the syntax as it would actually be used in the wild. In a separate file, try:

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

testbed "this should work" do |input|
input * 2
end
verify_that(1).returns(2)
verify_that(0).returns(0)

end

It should all work.

Next time: adding raises and any other functionality that strikes my eye, plus packaging as a Rails plugin.

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.

Rails, Ajax, RJS, and Testing

As promised, today’s entry is Agile and Ajax. Also, it’s a dessert topping.

Ajax in Rails

The initial support for Ajax calls in Rails was centered on two framework methods called link_to_remote and remote_form_tag. The basic functionality of these methods is to allow a remote call to be triggered by a link or form submit and have the result of that call be used to update a DOM element somewhere on the page.

Moving outside that simple behavior, however, quickly got messy. Both methods specify a series of callbacks where arbitrary JavaScript can get implemented at various points in the call life-cycle. However, writing dynamic JavaScript in an ERB template is awkward, and the resulting method calls could get ugly.

Enter Ruby JavaScript (RJS), sometimes described as “training wheels for JavaScript”. RJS allows a very simple subset of JavaScript to be written in Ruby and translated to JavaScript as the result of a Rails Ajax Request.

Here’s what a sample RJS template looks like:

page.visual_effect(:fade, 'recipes_to_show',  :duration => 0.5)
page.visual_effect(:fade, 'category_being_shown', :duration => 0.5)
page.delay 0.5 do
page.replace_html("category_being_shown",
"Recipies For: #{@category.capitalize}")
page.replace_html("recipes_to_show", :partial => "recipes")
page.visual_effect(:appear, 'recipes_to_show', :duration => 0.5)
page.visual_effect(:appear, 'category_being_shown', :duration => 0.5)
end

The page variable is automatically provided by Rails and represents the page that is going to receive the JavaScript. There are about a dozen or so instance methods that page can receive, mostly having to do with the basic Ajax-y features of replacing HTML in a DOM element and calling Scriptaculous visual effects. This particular snippet fades out two elements, changes their text, and fades them back in for a crossfade effect.

(There’s a certain similarity of concept with Google Web Toolkit, but RJS is going after a much smaller and more focused piece of functionality, optimized towards what you would do in a single Ajax call in an otherwise standard interface. GWT, on the other hand, is trying to be the entire application on both the client and server side.)

How useful this is depends on your relative level of comfort with Ruby and JavaScript. I’m personally much more comfortable in Ruby, so I think this is just great. It’s especially nice since I can use Ruby blocks to abstract this crossfade function into something I can use generically.

def crossfade(page, *dom_ids)
dom_ids.each do |dom_id|
page.visual_effect(:fade, dom_id, :duration => 0.5)
end
page.delay 0.5 do
yield
dom_ids.each do |dom_id|
page.visual_effect(:appear, dom_id, :duration => 0.5)
end
end
end

The generic function takes a list of DOM ids and a block — the assumption is that all the content changing will be managed in the block. So the original snippet would now be changed to:

crossfade(page, 'recipes_to_show', 'category_being_shown') do
page.replace_html("category_being_shown",
"Recipies For: #{@category.capitalize}")
page.replace_html("recipes_to_show", :partial => "recipes")
end

If you’re feeling more adventurous, you can patch the crossfade method directly into the JavaScriptHelper class and change the call to page.crossfade, making it more consistent with the other calls performed in an RJS template.

Testing RJS

Now for the Agile portion — how do you test this thing? RJS templates can be tested pretty thoroughly based on the content of the JavaScript code being generated. It’s much harder at the moment to test based on the actual results of the JavaScript — for example, it’s hard to test that the DOM elements being referenced actually exist in the client page.

There are two mechanisms for testing RJS that I’ve found useful. The first is mock object testing. Using the flexmock package to set up the page as a mock object, a sample test for the crossfade method looks like this:

def test_crossfade
page = flexmock("page")
page.should_receive(:visual_effect).with(:fade, "dom_1", :duration => 0.5).once.ordered(:first)
page.should_receive(:visual_effect).with(:fade, "dom_2", :duration => 0.5).once.ordered(:first)
page.should_receive(:delay).and_yield.once.ordered
page.should_receive(:replace_html).once.ordered
page.should_receive(:visual_effect).with(:appear, "dom_1", :duration => 0.5).once.ordered(:last)
page.should_receive(:visual_effect).with(:appear, "dom_2", :duration => 0.5).once.ordered(:last)
crossfade(page, "dom_1", "dom_2") do
page.replace_html()
end
end

Without going into the details of flexmock because, hey, future blog post, the idea is that the mocked page object keeps track of the method calls it receives and checks them against an expected set of method calls. In this case, I’m telling the mock object that it should get two calls to the visual_effect method with various arguments, and that those calls should come before the other calls.

The interesting thing about this method is that on the face of it, it contains no assertions. Implicitly, though, each should_receive call sets up an assertion about the messages coming to the object that is validated at the end of the test.

The other mechanism uses a plugin called ARTS (Another RJS Testing System), which defines a method called assert_rjs, which checks the outgoing JavaScript for a method call matching a set of parameters.

Using ARTS, the following method tests whether an individual DOM element is in the crossfade:

def assert_crossfade(dom_id, replacement)
assert_rjs :visual_effect, :fade, dom_id, :duration => 0.5
assert_rjs :visual_effect, :appear, dom_id, :duration => 0.5
assert_rjs :replace_html, dom_id, replacement
end

And a full test of the example would look like this:

def test_one_crossfade
assert_crossfade 'recipes_to_show', /Recipe/
assert_crossfade 'category_being_shown', /Category/
end

The replacement argument can be either a string, in which case the output needs to match exactly, or a regular expression, in which case a Regex match is performed. In general, assert_rjs works by recreating what the JavaScript looks like from the assert call, and checking the actual output for the existence of that call. Again, this is most helpful when you can bundle calls together in a single assertion.

ARTS is a nice little plugin, and it does let you do some syntactic testing of your RJS templates, but semantic testing along the lines of, is the recipes_to_show element visible at the end of the RJS and what text is actually in the element is still elusive. I think that’s doable, but it would require a much more complex mock object representing the page, one that keeps track of a pseduo-DOM tree and can manage at least some of the effects of RJS calls. Another project for another day…

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.

Agile, The Control Paradox, and the Boring Software Manifesto

I'm probably not getting the quote quite right, but supposedly at one point during the C3 payroll project where XP was created, a developer said that it was so easy to make changes to C3 that they could turn it from a payroll system to an airline scheduling system without any strain.

Okay, it's not much of a story, but the idea resonates with the core of what Agile development means: driving the cost of incremental change so low that you can handle whatever the client or customer throws at you at any point in the process.

Gaining Control

There's two parts to that statement, of course. The first is that it's great to be able to easily fix bugs and make changes to the software over time. The second is that it's even better to be on a project that you feel is under control.

This is the paradox of being Agile. Agile dispenses with many of the artifacts that traditionally symbolize control in a development process -- big requirements documents, detailed UML diagrams, long-term Gantt charts, that kind of thing. At the same time, I've never felt more in-control of the actual day-to-day work then I do when in the midst of an Agile process. By accepting the inevitability of change in a software project, Agile allows the development team a structure by which the effect of changes can be mitigated.

The Boring Software Manifesto

Several years ago, I coined the phrase The Boring Software Development Process, in response to a former employer where project management really didn't think anything was happening unless we were trying to solve seven crises simultaneously.

The manifesto goes like this:

  • Boring software projects favor tacking exciting problems, and focusing our energy on the most interesting and valuable parts by avoiding wasting time on avoidable problems.

  • Boring software projects favor automated test suites over the excitement doing all your testing at the last minute and finding bugs after the project is "done".

  • Boring software projects favor frequently integrating work from the whole team as opposed to the excitement of finding out whether you changes work well with the rest of the team after you have been working on them for six weeks.

  • Boring software projects favor always having a working, if incomplete, system over crossing our fingers and guessing whether the newest build would compile.

  • Boring software projects favor incremental design rather than spending six months crafting a UML document that is thrown out after one week of development. (I'm not exaggerating on this one, I reviewed a project that happened on)

  • Boring software projects favor understanding that requirements change over being "surprised" when late change requests come.

  • Boring software projects favor putting working, if incomplete, systems in customer hands early to get feedback as early in the cycle as possible rather than finding misunderstandings after the project is done.

I hope that wasn't too boring... Next time, something a bit more nuts and bolts.

GWTTestCase and Server Side Mocking

While I like the fact that GWT supplies a mechanism for unit testing your applications, there is room for improvement on testing the interactions between the UI and server-side components.  Based on everything I have read so far, testing GWT applications is an area which many people tend to gloss over or merely pay lip service to, leaving developers to fend for themselves on issues such as how to incorporate the use of mocks, or how to test GWT applications while keeping the test code clean and maintainable.

For the moment, let's consider a simple application where a client requests data from the server, and updates some content on the UI.  We would like to assert that some content on the client can be updated with data returned by the server.  For purposes of testing, the client code contains a package-level method which executes a remote call and updates the content area (asynchronously, of course).  Here is a test case as we would like to write it:

      public void testRemoteCallPopulatesContentArea() {         // Mock out server call         server.willReturn("Foo data");         // Client invocation         client.executeCall();          // Assert client is updated         assertContentArea("Foo data", client.getContentArea());     } 

You can imagine additional testcases that assert behavior when the server throws an exception, returns an empty string, etc.  Looks like a great test case so far (short & sweet), but as you have probably guessed, there are hoops to jump through in order to get this code to actually do what we intend it to do, each hoop deserving of a much longer, in-depth discussion of its own.

This test case should look pretty familiar to anyone who has used mocks before.  In this test, we want to (1) mock out the behavior of the server component, (2) execute the call from the client's side, and (3) assert that the "content area" of the client contains the data we defined when we mocked out the behavior of the server component.

The work we will need to do breaks down as follows:

  • Define a service that will support 'willReturn(String data)'
  • Implement a mechanism for mocking out the actual implementation of the service method.
  • Implement our assertion logic, taking into consideration the asynchronous nature of the client code, the use of GWT's Timer mechanism, etc.

The third item is the easiest to envision-- the method 'assertContentArea' wraps all of the Timer logic, defering execution of the actual 'assertEquals' invocation until the client has had a chance to execute the remote call and update the content area under test.

I have a few solutions in mind for the first two items, one of which involves using Spring to intercept calls to GWTShellServlet during execution of each test case.  Can you guess how that one would work?

I'll delve into that side of things in following posts, but I hope this gets you thinking a bit more about readability of your test cases, and what test cases that extend GWTTestCase should really look like when they involve interactions with a back end component.

The awesome state of JavaScript development tools

Dietrich's post on the depressing state of IE develpment tools got me to thinking about the generally wonderful state of JavaScript tooling. Compared to just a few short years ago, we've got a wealth of productivity-enhancing browser add-ons, TDD frameworks and static-analysis tools at our disposal - most of them open-source. For those who want to get their hands dirty writing POJ, this is a golden era.

Like most developers, my code circa 1998 was filled with commented-out alert() statements. I spent way too many hours cursing IE4's inability to report accurate line numbers in its error dialogs. I relied heavily on Netscape's built-in debugger. Within a couple of years I had graduated to a primitive logging utility that spawned a separate browser window and output messages into it using simple DHTML. At the time, it seemed like a huge advance.

Then came the Firefox era, with its host of disparate add-ons. You could edit your CSS in the sidebar, selectively disable JavaScript and CSS, inspect the DOM .... Once again, the possibilities seemed endless. Now, thanks to Firebug, most of my grab-bag of browser add-ons are gone. Firebug is so powerful and wide-ranging that the only other add-on I use regularly is the venerable Web Developer Toolbar. Yahoo's new Firebug extension YSlow adds some really useful optimization benchmarks to the suite. When a plug-in begins to spawn its own plug-ins, you know you've got a winner.

I'd be interested to know, though, what kind of process UI developers use to debug their JavaScript. Most of us are using similar tools, but how are we using them? (That's an invitation to jump in on the comments, folks.) Every UI person I know develops prototypes in Firefox and Firebug, crossing his or her fingers that there won't be too many implementation-specific issues to tackle in the other browsers. Many rely on a logging utility - heir to that long-ago popup window - to grind away at any such browser bugs.

But beyond that kind of hunt-and-peck debugging, have we arrived at an industry-standard practice for client-side code maintenance? Who's doing true TDD with one of the flavors of JsUnit? Who's using Selenium to test their entire webapp in the browser? Who's picking apart the details of their syntax with Douglas Crockford's JsLint? Who's busting out Fangs or another accessibility test tool on a regular basis? The tools are out there. It would be interesting to know who's using them, and how.

When you're banging your head against a wall trying to figure out why a certain DOM element won't return the same node type from one browser to the next, it's easy to see why there are a hundred competing Ajax frameworks promising to solve all your cross-browser issues for you. Let's just remember how far we've come - and how important it is for real-deal UI developers to maintain the skills that they've honed for over a decade. The more trust we put in frameworks, the more helpless we'll feel when our code fails and we've lost the ability to figure out why.

Agile Practices and Ajax Toolkits

I've been practicing agile development in one form or another through my involvement with open source projects since the early 90's. Of course at the time, we didn't know we were practicing Agile development. We were distributed, we had real jobs, we were pressed for time. Often we compensated by eyeballing requirements, having rapid releases, and evolving the SW over time as new needs and requirements were discovered. Now many of those shortcuts that grew out of necessity are at the core of Agile.

In all that time, I've developed my own philosophy (when you turn 40, your "opinions" turn into a "philosophy") on how Agile development should be done. There are a number of core principles I adhere to:

  1. Short iterations. Thirty days is a nice number.
  2. Pair programming (not necessarily the one keyboard, one mouse variety). Yes, two developers working on the same tasks do get more done than the same developers working on separate tasks. The practice also really boosts quality and learning.
  3. Test Driven Development. If you've ever worked on projects that don't have extensive unit and integration tests, then you've experienced the waves of bugs that appear with every new feature or enhancement. TDD -- rather than after the fact unit test development -- is also the only way to guarantee that the practice doesn't slip during stressful times.
  4. Continuous integration. Hourly is good enough. If you've worked on projects without CI, then you've felt the pain of week long "build and deployment" sessions, driven by the poor sods condemned to being the "build masters."
  5. Self organizing teams practicing continuous improvement through process reviews.

Everything else is negotiable, as far as I'm concerned. Through #5, each team will find the right agile methods and practices for themselves and the client. No single method (note, "methodology" is the study of methods) is appropriate for all situations and teams. I myself favor Scrum as a wrapper around the development process, as it incorporates #5 as a core principle.

Turning now with these Agile principles to the world of Ajax frameworks, which of them explicitly incorporate unit testing into their development? This is an important consideration, since if a framework doesn't provide unit testing facilities or hooks, you will have to develop and maintain them in step with the framework. As an example, with full unit test coverage (branch and line) in place, you can weather the release of new browser version (think IE7 and Safari for Windows) much more easily. Not only will you know that your sophisticated Ajax interface doesn't work, but you will know exactly why it doesn't work (probably).

So, which frameworks do incorporate unit tests, and how easy do they make it to hook those into your own development machinery?

  1. GWT, of course, lets you use JUnit directly.
  2. Prototype  and Scriptaculous both use the same unit test harness, which already comes integrated with Rake (Ruby make), but would take a little work to integrate with other build environments.
  3. JQuery does have unit tests that can be run with make or ant, but they aren't extensively documented, so extending them to your own development environment will require a bit of work.
  4. Of the straight Javascript frameworks, Dojo has the best documented unit testing approach, as well as a build process that can be integrated into your build environment.

(BTW, has anyone else noticed that YUI doesn't have a publicly available SVN?)

The one tricky bit with testing Javascript is that object definition and creation can be pretty complex code itself. Ideally it should be tested as well, though that doesn't always happen in the above frameworks. Whatever framework you choose, make sure that it provides unit testing facilities that your developers can and will use, otherwise your user interface will be the redheaded stepchild of your web 2.0 webapp.

Technorati Tags: , , ,

About Pathfinder

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

Topics