Archive for the ‘Testing’ Category

ReSpect RSpec

{Monday, May 21st, 2007}

What is Behavior Driven Development (BDD)?

According to behaviour-driven.org BDD was born from NLP experiments (astonishingly, nlp.com mention NLP and hypnosis in the one sentence!).
It is a combination of TDD and DDD. Here are some of my attempts at describing BDD:

A process for describing the behavior of a system that is understood by both technologists and non-technologists.

DDD applied to the domain of TDD.

The concept of a ‘vocabulary for describing behavior’ is at its core, but interestingly the behavior-driven site falls short of defining the vocabulary (note the incomplete links at the base of this page).
BDD is strongly linked to TDD as tests are often used to describe the features, or behaviors, of a system. Consequently, part of BDD involves writing tests using the vocabulary.

Enter RSpec

That’s the driving principle behind RSpec. Test::Unit is perfectly fine for defining tests, but it doesn’t employ a BDD vocabulary.
RSpec does, and it throws in a side order of Mock and Stub support often needed for TDD. As it happens this support is virtually identical to that provided by Mocha.
Take your pick, the support both provide is particularly cool as you can Mock and Stub methods of any object, sure you can create Mock and Stub objects (in a fashion that I’ve been used to with EasyMock and JMock) but the object doesn’t have to be a Mock or Stub in order to Mock or Stub a method invocation.
To highlight this here’s an RSpec demonstration applied to a banking model;

  describe Account do

    before(:all) do
     @@amount = 100
    end    

    before(:each) do
      @account = Account.new
    end

    it 'should withdraw cash via a Transaction' do
      Transaction.should_receive(:deduct).with(@account, @@amount)

      @account.withdraw @@amount
    end

    it 'should log unsuccessful operation when withdraw is unsuccessful' do
      Transaction.should_receive(:deduct).with(@account, @@amount).and_raise(InsufficientFundsException)

      @account.should_receive(:log_outcome).with(:unsuccessful)      

      @account.withdraw(@@amount).should_raise(InsufficientFundsException)
    end

  end

Pretty cool huh?! This mocks two methods in a manner that can’t be easily repeated with Java:

  • A class method, Transaction.deduct
  • An instance method of a real object, @account.log_outcome

Take a look at the recently tweaked documentation on the RSpec site for info on it’s other features (like partial argument matches), and more generally its implementation of a BDD vocabulary.

Why use RSpec?

One of my initial encounters with RSpec was via a blog critising BDD that goes so far as to suggest RSpec is pronounced ‘arse peck’, so I’ve been skeptical from early on. I have been particularly cosy with XUnit tests, a mock framework and consistent test method naming conventions as a way of specifying behaviors, so I didn’t feel the urge to change. Test::Unit and Mocha can pretty much yield the same result - what did I have to gain?

Still, this ol’ school approach requires some discipline and custromizations to read like a BDD vocabulary. RSpec, on the other hand, encourages codification of tests in a consistent BDD vocabulary. But hey, if you don’t intend on using the vocabulary for communications between roles (and that’s a substantial change) your missing the major benefits of BDD - so why bother?

Nonetheless, it’s worthy of consideration.

With its subtle shift in the XUnit language I believe it produces more readable tests. That coupled with its nice mock and stub support and the potential benefits of a shared language for describing behavior - the pro’s start outweighing the con’s.

Parting Thoughts

I’ve read some BDD proponents claim they sought out BDD as a solution to tests that are tightly coupled to source, hindering refactoring and causing a maintenance burden.
I fail to see how BDD helps here; this is a natural consequence of writing unit tests. For tests to do their thing, an API under test must be invoked - you can’t avoid that. If you change that API; surprise, you’ve got to change your unit tests! If you’re suffering this affliction maybe you should test against an API few layers up, like HTTP. Personally though I’d be blind without my unit tests, at a minimum they aid design and verify correctness.

Torn tearDown

{Tuesday, November 8th, 2005}

I frequently encounter two problems with JUnit’s tearDown:
1. tearDown is not executed if setUp fails, leading to resource leaks.
2. Mock verification calls in tearDown can obfuscate original causes of test failures.

Many developers work around the mock verification problem by commenting out the verification to expose the original problem. The problem with this is that it’s very easy to forget to uncomment the verification calls, hiding future test failures. Another alternative is to blatently violate the DRY principle.

My solution to these problems is to introduce a custom TestCase that overrides runBare, the skeleton directing the steps performed in a test:

public void runBare() throws Throwable {
    try {
        setup();
        runTest();
        tearDownExpectations();
    } finally {
        tearDown();
    }
}

tearDown can now do its thing if setUp fails and tearDownExpectations (a Template Method containing Mock object expectation verification calls) will only be performed if the test method is successful.

From Fit To Fitter

{Thursday, May 26th, 2005}

For about the past year I’ve been occasionally looking at Fit. When I first heard about it I perceived it as the shiny new tool that would radically modify the way user acceptance scripts are traditionally created, specifically for web applications. I was under the impression both analysts and testers could use Fit to the run scripts against a web application. No more laborious amounts of tests scripts coded by developers – that was the analysts and testers job now.

Well, after trying to read the site numerous times, downloading it and playing with it, I plain gave up. The doco was terrible and the code certainly wasn’t self-documenting. I encountered some sites that mentioned jWebFit, an extension to Fit for jWebUnit, but I couldn’t uncover any useful information on that either. I walked away from it all under the impression Fit was immature and generally unusable. But I was still intrigued as I heard rumors of it being put to good use.

Thankfully Fit is now Fitter! The Fit site has now been updated and it contains plenty of doco and examples to guide you through the process of understanding Fit. There’s even a new book on the way explaining Fit and the business processes supporting its full use. The doco on the site is fairly concise - within around 15 minutes I had Fit up and running with some experiments of my own. Here’s my take on Fit:

  • Depending on how you use it, developers may still be required to produce a fair amount of code – Fit fixtures that exercise code being tested.
  • Fit is a testing framework that it is completely agnostic of the thing being tested. You could perform any test (unit, integration or acceptance) using Fit.

Looking at it simply, Fit is a way of expressing what code to run, what values to use and what results to expect, all via a HTML table. View it as a layer above code that returns results – importantly that code should not be asserting the expected result. That’s Fits job, Fit asserts the result and displays the assertion result in a table. What that code does it entirely up-to the developer, hence there can still be plenty of grunt-work to do. While it’s a cool tool that can be used to express tests simply, a fair amount of development effort could be expended ensuring Fit fixtures do the job required of your test scripts. But this could be said of any code that has the “difficult to test” odor.

Enter jWebFit. After digging around I’ve discovered it’s a Fit fixture or two built on jWebUnit facilitating jWebUnit tests being expressed via Fit tables/scripts. If Web Apps is your thing, jWebFit promises to cut-down the development effort required to get acceptance tests running through Fit. So my original belief in Fit is realized - less developer grunt-work for web application testing. But beware. It’s documentation is non-existent and it’s not official, it can only be downloaded from jWebUnit’s CVS repository. Robert Watkins has played the tune I’m leading to before - use it at your own risk. But hey, as always if it’s free you can’t complain.

From what I’ve discovered, teams pursuing a collaborative team structure with analysts, developers, and testers working closer together (in true XP fashion) should consider using Fit and/or jWebFit but be wary that they are immature. It’s definitely a “try before you buy-in” deal, they will not work in every team, especially teams lacking the skill to support and expand fixtures.

P.S. Interestingly, the Fit site recommends the use of Word for analysts/testers to produce tables. For a cheap kick I tried Open Office 2 but unfortunately it produces HTML tables with <th> tags not liked by Fit.