Wednesday, July 11, 2007

Extending Fit with a New Fixture

Fit is a very flexible tool for testing due in large part to the pre-defined fixture types (ActionFixture, ColumnFixture, RowFixture, fitlibrary’s DoFixture, etc.) This flexibility means it’s usually possible to write test tables in a way that is intuitive and easy to read. However, we’ve come across a situation where the test tables we want to write aren’t executable by any of Fit’s built-in fixture types.

The feature we’re working with is a Fit HTML table builder. Our test provides a fixture classname as input and expects a Fit HTML table as output. Here’s an example of what we wanted to test:



Unfortunately, when we ran this test using a ColumnFixture, Fit interpreted the nested table as more parsable cells rather than expected HTML output. And, while there are other ways to structure the test, such as using raw HTML, none of them seem very easy to work with.

What we really need is a new type of fixture, which interprets the table data in the last column as HTML content to be compared with the result of the fixture’s verification method (in the case above, table()).

public class HtmlTableFixture extends ColumnFixture {

@Override
public void check(Parse cell, TypeAdapter adapter) {
String expected = cell.body;
try {
String result = (String) adapter.get();
if (expected.equals(result)) {
right(cell);
} else {
wrong(cell, result);
}
} catch (Exception e) {
exception(cell, e);
}
}

@Override
protected Binding createBinding(int column, Parse heads)
throws Throwable {
Binding binding = super.createBinding(column, heads);
if (column == columnBindings.length - 1) {
binding = new HtmlTableBinding(binding);
}
return binding;
}

private static final class HtmlTableBinding
extends Binding {

private final Binding internalBinding;

private HtmlTableBinding(Binding binding) {
this.internalBinding = binding;
}

@Override
public void doCell(Fixture fixture, Parse cell)
throws Throwable {
Unparse unparse = new Unparse(cell.parts);
String html = unparse.text;
cell.body = html;
internalBinding.doCell(fixture, cell);
}
}
}


Our fixture creates a custom binding, called HtmlTableBinding, which gets bound to the last cell in each row. This binding unparses the cell’s contents and stores them in the body of the cell’s Parse object. When the cell is later evaluated by check(), our fixture gets the expected value from the body of the cell's Parse object and compares it with the result from executing the method (via the TypeAdapter).

Running the test now gives us:



So, Fit is not only a flexible testing tool, it's also easily extensible for those corner cases where you might find that it doesn't give you exactly what you want.


* To understand why we need to unparse it helps to know how Fit reads HTML tables. When Fit is run on a file, the first thing it does is create a model of all of the table information, which it stores in a composite object called Parse. Each part of a table (i.e., <table>, <tr>, or <td>) is a nested Parse object within the composite. Unparsing is achieved by traversing the composite Parse and appending the HTML parts to a buffer.

public class Unparse {

public String text;

public Unparse(Parse parse) {
text = unparse(parse);
}

private String unparse(Parse parse) {
StringBuffer sb = new StringBuffer();
sb.append(parse.tag);
if (parse.body != null) {
sb.append(parse.body);
}
if (parse.parts != null) {
sb.append(unparse(parse.parts));
}
sb.append(parse.end);
if (parse.more != null) {
sb.append(unparse(parse.more));
}
return sb.toString();
}
}

Tuesday, July 10, 2007

Agile 2007 Conference

I recently found out that Stephen, Michael, Askhat and I are attending the Agile 2007 conference in Washington, D.C. August 13-16th. We hope to bring back some fresh ideas about Agile software development and lots of blog post material. Come say hi at the Luxoft booth!

Friday, July 6, 2007

Why We Scrum

I read an article today complaining that scrum was just another useless meeting and that the time would be put to better use speaking to the other developers about design issues one on one. I tend to disagree.
At a previous company, during our waterfall days, product managers tended throw requirements over the wall as they were busy. As a tester, I often found large discrepancies between my interpretation of the requirements and what the developer had coded into the product. On occasion I had to strong-arm developers into the product manager's office so we could come to a common understanding of a feature.
We had product development offices in Boston and Vancouver, so often the product manager, tester and developer were not co-located and had never met.
Scrum helped alot. When daily scrum meetings started up, we met our cross-department distributed team (face-to-face or over phone/video conference) and had a daily opportunity to discuss all the little questions and blockages that come up as you code and test. We came to a common understanding daily, and if we got astray from the feature vision the next day, it was still recoverable.
In conclusion, scrum breaks down the barrier of departments and lack of co-location, and gets a team communicating and collaborating. Cause many brains really are better than one.

Thursday, June 21, 2007

Fit = Acceptance Testing for Anyone

One thing I’ve learned in software: business people and developers speak a different language. My Stanford friends like to lump people under fuzzies or techies (fuzzies being someone who doesn't know a lot about computers) and this generalization has some merit – at times it can feel like you’re speaking to another species (and buzzword spouting executives are from another planet!)

But I’ve been using a solution called Fit, or the Framework for Integrated Testing, that bridges the gap between fuzzies and techies. In Fit, product managers supplement written word requirements with HTML or Excel Fit tables that express concrete examples. These Fit tables can easily be written by fuzzies in a HTML WYSWIG editor or Microsoft Word or Excel. There is something almost mathematical about writing out examples in this way, forming what domain-driven design philosophers might dub a Ubiquitous Language. These examples are both requirements and tests, saving you a step (and an opportunity for business needs to be lost in translation).

How easy is it? Well let’s go through an example (from the Fit bible, “Fit for Developing Software” by Fit pioneers Rick Mugridge and Ward Cunningham.)

Business rule: A 5% discount is provided whenever the total purchase is greater than $1,000.
Fit test table:

Kinda making sense?
Well, row one names the fixture, or the code that hooks the test into the system under test.
Row two has the headers, which label the two columns. The amount column acts as a given column, which specifies the test inputs (amount = purchase price in the business rule). The discount column acts as a calculated value column, which specifies the expected output of the calculation. The calculated value columns are designated by the () brackets after the name. The rest of the rows are effectively our test cases, trying a variety of inputs into the system.

Once a developer has written a fixture to hook this test into the system, the Fit test can be run, producing a report (see my report below). The calculated value column is colour-coded in the report: green=test success, red=test failure. Failed tests list the expected value and actual value calculated by the system, so you can investigate the discrepancy. In this case, the developers seem to have misinterpreted the requirement to provide the discount when the purchase is greater than $1000.


The value of Fit is not only in more precise communication of requirements, but as an automated acceptance testing framework. With Fit, your requirements can be tested regularly to indicate to developers if new development efforts meet expectations, and if refactoring or new development has broken existing functionality.

Well, that’s all for now. To learn more about Fit, check out http://fit.c2.com/