Sunday, May 15, 2011

The French Laundry and Unit Tests

In an article about the legendary Michelin 3-star restaurant - The French Laundry - in September last year, there was an interesting quote:

... in a further twist that differentiates them from most other line cooks, French Laundry cooks don't taste their completed dishes. Keller explained that if the cooks taste each component, and know that the flavor profiles work, the finished product will also work. 

I didn't quite appreciate Thomas Keller's food on my visit last October (read my review here), but this kitchen strategy is smart.

Too many times, test cases in our softwares are end-to-end, which are, first of all, difficult to execute, and not efficient.

In a web-form registration application, we, for every release, test the complete application with combination and permutation of test cases. Every single executed test case exercises all the components of the application, from presentation UI, to form fields validation, to database insertion.

Consider these 2 test caes: 1) phone area code has to match city, and 2) password must at least 8-character long. There is really no need to exercise complete user flow to test them. Both test cases are around validation logic, and should be covered in validation unit tests.

The key is to divide your applications into "units". These units are logically isolated, can be owned and developed independently, and, best of all, can be tested individually.

For example, this registration application can be divided into presentation, validation, and database access layers. Each layer is tested, assuming the other layers work. Presentation testing focuses on the layout, spacing, spelling, usability, etc.; validation tests business logics; and database access layer tests the interaction with underlying data model.

To make it successful, a clearly defined boundary and interface is needed between layers  (analogy: Chef Keller who designs the menu to put individual line cook's contribution together). This is the basis we can make assumptions that the other dependent components work as expected. Validation layer has to take it for granted that UI sends the user input correctly to it; database has to assume validation has already cleansed the data, so what's passed to it to be persisted is kosher. SOA has been used widely to make this boundary clean, but well-defined method signatures or other methodologies work equally well.

Now, does it mean no integration testing is needed? Absolutely not. But integration testing is only required on a very limited scale, in fact, to test the boundaries and interfaces between these layers. For the above 2 test cases, only one integration test case is necessary. In fact, if you have 1,000 validation test cases and 5,000 database access test cases, only a few integration test cases are needed. Do the math, total number of tests will be 1,000 + 5,000 + X, but in the old world, it will be 1,000 * 5,000.

Next time I go to Keller's restaurants, this learning will remind me to be more appreciative. :)

No comments:

Post a Comment