PragProWriMo: Day 1
If you’ve followed my tweets, you already know that I’m participating in the November PragProWriMo, or the Pragmatic Programmers Writing Month. It’s not a contest or anything, but it is an opportunity to start writing what might become a book, or just a series of blog posts.
Note that these are not really blog posts, or even self-contained tidbits, but just what I’ve happened to write on that day. So, while you can feel free to comment, I’ll not really be paying attention to the comments and certainly expect things to not be well-written, let alone make sense without additional context. This is simply a way to allow people to see my writings as soon as they’re written and nag me if I miss a day of writing.
Day 1
Fluent Testing
ATDD, or Acceptance Test-Driven Development is one of the more recent techniques in developing software. The idea is to use code-based acceptance tests instead of English-based specifications or requirements. While it seems that English accetpance tests would be easier to write, in fact, they are more difficult to write well. It’s quite hard to be precise in a natural language where words are often ambiguous. For example, in this English-based acceptance "test"
* Filter searches on the Account number and the Policy number
The context here is a text field for a "filter" that limits the records that are shown. This simple statement can be interpreted in different ways. Before reading my interpretations, think about how many ways you could interpret it.
1. Text entered in the filter text field is used to search in the account number field, the policy number field or both.
2. The text is searched for in both the account number and policy number fields and must be found in both in order for the record to appear.
3. The filter text is used to search in the account number field, and if no records are found, then search in the policy number field.
You might be thinking that this is obvious and should have been stated more precisely when this requirement was discussed. However, it’s very difficult to always express the intent of requirements with enough precision on a consistent basis without missing something, or contradicting some other requirement. Even if you do end up with sufficient precision, you’ll likely end up with a 300 page requirements document that, I guarantee you, will end up being interpreted differently than from how it was intended. Since the whole point of agile development using story cards is to discuss these details (as in a "token for conversation") on an as-needed basis, how do you make sure that the developers don’t forget the details as they’re developing the code? The answer is executable acceptance tests.
The problem I’ve seen in coming up with a good form for executable acceptance tests (no, I won’t call them EATs) is that in trying to formalize the English, you end up with something that is close enough to English that people understand the intent, but not quite enough like English so that people find it hard to write. The solution here is a fluent testing API. Something that is not only precise, but can be executed against production code once the code has been written and, going with the ATDD technique, use by developers while they’re writing the code. For example (using JUnit in Java):
public void sortByInvoiceDatesIsVisibleOnlyWhenGroupingByInvoiceAndByItem() {
openCreateDirectBillPaymentPage(account)
.groupByInvoice()
.aggregateByItem()
.assertSortByInvoiceDatesIsVisible("Sorting by invoice should be visible for Group By Invoice Aggregate By Item");
}
It’s true, this test only checks that the "Sort By" selection element is visible, depending on various combinations of other selections ("Group By" and "Aggregation"), but it’s also very explicit under what conditions it should be visible and, most importantly, is not that much less readable than if it were written in English. It’s hopefully clear that after opening the "Create Direct Bill Payment Page", we "group by invoice", then "aggregate by [invoice] item", and finally, the check (assert) that the "Sort By" element is indeed visible. The string passed to the assert is the failure message, and helps describe why the assertion should be true.
There’s an additional feature that puts this over the top, and that’s an IDE’s ability to provide a list of choices of methods that are available on each object, aka, code completion. This allows the executable acceptance test author to be guided by the code completion of methods that are available at each point. This turns out to make test writing much easier than if it were an /external DSL/, because the choices are constrained by the objects that you’re working with, i.e., on the DirectBillPaymentPage, the IDE will "tell you" that you can do "groupByInvoice" and "aggregateByItem" by showing those methods as auto-complete options.

