Exploration Through Example

Example-driven development, Agile testing, context-driven testing, Agile programming, Ruby, and other things of interest to Brian Marick
191.8 167.2 186.2 183.6 184.0 183.2 184.6

Tue, 06 Apr 2004

Fit extension: the StepFixture

I've been reviewing a forthcoming book on FIT, so I've been thinking about it a lot. Hence this blog category. I'm going to spew forth both some extensions to FIT and some stylistic quirks I've developed. I hope they'll provoke some blogospheric or wikispheric talk - or at least pointers to place where that talk's already happening.

Since a lot of my examples will involve my StepFixture, I'll talk about that first. (You can get it here. It has both my source and a jar file containing StepFixture plus the standard FIT fixtures.)

StepFixture is my alternative to ActionFixture.

ActionFixture depends on three keywords: enter, press, and check. The first two ask you to model your application as a device with a GUI-ish interface. My first difficulty with ActionFixture is that I'm afraid people will think the FIT tests should test through the actual GUI, though I know this is not Ward's intention. He would prefer the tests to bypass the GUI and test the business logic directly. The pretend device interface is just a convenient way to think about performing a series of steps. Still - to be overbearingly paternalistic about it - I think it's an "attractive nuisance."

I think that the problem could be alleviated by using cause as a synonym for press. Then you "probe the device" by entering data, entering data, ..., entering data, then causing some action. That's easily done by adding this code to ActionFixture.java:

    public void cause() throws Exception {
        press();
    }

But my second difficulty is that the tests are verbose:

enter Betsy
enter Rankin
cause new case

I think long sequences like that are hard to read. I would rather see this kind of terseness:

new case Betsy Rankin

It might be objected that this looks too much like a program's method call; that non-programmers will find the device model more friendly. I have experience showing StepFixture tests to only two Customers, but neither of them has seemed to have problems with the format.

Notice that, whereas press describes a method with no arguments, new case takes several. I've occasionally found it useful to have methods with the same name but different signatures. The following is a bit of a test that describes how sometimes the owner of an animal being treated doesn't pay all the charges. If a clinician does extra work for teaching or research purposes, the veterinary clinic will pick up part of the charge.

diagnosis clinical mastitis  
charge 100  
charge 400 clinic

It might seem that it would be better to always have charge take both the amount and the entity-being-charged. But consider: there were already a bunch of tests that used the one-argument form. It would have been a hassle to change them. Moreover, we'd already established a vocabulary where charge 100 meant "charge the normal payer" - I want to build a vocabulary, not always be revising it.

I've also found arguments to be useful with the check keyword. For example, after the above, I might use these check statements:

check balance 100  
check balance clinic 400

They invoke, respectively, these methods:

    public int balance()...
    public int balance(String payer)...

So the expected value is always the last non-blank cell in the row. (That's a little awkward - I kind of wish they all lined up.)

Sometimes the use of arguments on check isn't necessary, but I find it more pleasing. (I think text that exists to promote conversation - as customer-facing tests do - should be pleasing to the eye.) For example, these check who does what how often:

check
student does
soap
daily
check
student monitors temperature
6 hours
check
caretaker does
milking
never
check
student does
milking
never

There's no particular reason for "student does" and "soap" to be in separate cells, but I find the vertical alignment makes the set of checks easier to scan.

The FIT ActionFixture has the test explicitly start an application. I found myself drawn to a "FIT-first" style of coding, in which I started building the application within the fixture, factoring out pieces as it became convenient. So I did away with start. Nevertheless, an important part of FIT is the ability to have a test that includes more than one kind of table. So state has to persist across tables. As with the ActionFixture, that happens automatically with the StepFixture. If you want to start fresh, you use restart in the table:

fit.StepFixture
restart

That clears out all state and starts you with a new object. I'm not sure I like that, so...

Most of my tests have been a single StepFixture. So what I've found myself doing is having two subclasses of it for an app. The "AppFixture" fixture starts fresh. The "ContinuedAppFixture" signals that the current table is a continuation of a previous one. So a multi-table test looks like this:

AnimalProgressFixture
new case
Susie
Rankin


diagnosis
therapeutic truck ride



... another type of table ...

ContinuedAnimalProgressFixture
payment
30



In the code, the ContinuedAnimalProgressFixture is derived from StepFixture:

  public class ContinuedAnimalProgressFixture extends fit.StepFixture {
      private Case myCase;
      static public Accountant accountant; // Used by other fixtures
      protected Clinic clinic;
      ...

      public void newCase(String animal, String owner) {
        ...
      }

      public void diagnosis(String diagnosis) {
        ...
      }
  }

AnimalProgressFixture extends ContinuedAnimalProgressFixture, but reinitializes things:


  public class AnimalProgressFixture extends ContinuedAnimalProgressFixture {
      public AnimalProgressFixture() {
          super();
          restart();
          accountant = new Accountant();
          clinic = new Clinic(accountant);
      }
  }

I'm not sure I like that either.

If you want to use StepFixture and need more help, let me know.

## Posted at 20:35 in category /fit [permalink] [top]

About Brian Marick
I consult mainly on Agile software development, with a special focus on how testing fits in.

Contact me here: marick@exampler.com.

 

Syndication

 

Agile Testing Directions
Introduction
Tests and examples
Technology-facing programmer support
Business-facing team support
Business-facing product critiques
Technology-facing product critiques
Testers on agile projects
Postscript

Permalink to this list

 

Working your way out of the automated GUI testing tarpit
  1. Three ways of writing the same test
  2. A test should deduce its setup path
  3. Convert the suite one failure at a time
  4. You should be able to get to any page in one step
  5. Extract fast tests about single pages
  6. Link checking without clicking on links
  7. Workflow tests remain GUI tests
Permalink to this list

 

Design-Driven Test-Driven Design
Creating a test
Making it (barely) run
Views and presenters appear
Hooking up the real GUI

 

Popular Articles
A roadmap for testing on an agile project: When consulting on testing in Agile projects, I like to call this plan "what I'm biased toward."

Tacit knowledge: Experts often have no theory of their work. They simply perform skillfully.

Process and personality: Every article on methodology implicitly begins "Let's talk about me."

 

Related Weblogs

Wayne Allen
James Bach
Laurent Bossavit
William Caputo
Mike Clark
Rachel Davies
Esther Derby
Michael Feathers
Developer Testing
Chad Fowler
Martin Fowler
Alan Francis
Elisabeth Hendrickson
Grig Gheorghiu
Andy Hunt
Ben Hyde
Ron Jeffries
Jonathan Kohl
Dave Liebreich
Jeff Patton
Bret Pettichord
Hiring Johanna Rothman
Managing Johanna Rothman
Kevin Rutherford
Christian Sepulveda
James Shore
Jeff Sutherland
Pragmatic Dave Thomas
Glenn Vanderburg
Greg Vaughn
Eugene Wallingford
Jim Weirich

 

Where to Find Me


Software Practice Advancement

 

Archives
All of 2006
All of 2005
All of 2004
All of 2003

 

Join!

Agile Alliance Logo