lixo.org

Spreadsheet-Oriented Programming

At my last project, we’ve been writing our acceptance tests as Fit tests, using JWebFit, part of JWebUnit. For those unfamiliar with the concept, it’s basically (and roughly) a test organized as a table. An example would speak for itself, in this case, so let’s get to one: LogicFixtureFitTest.html:
example.LogicFixture
OpLHSRHSExpected
<11false
<12true
<21false
…and so on and so forth. As you can imagine, this test lists all possible outcomes of a less-than operator. This test, when run, will repeatedly call the example.LogicFixture.lt(String, String) method, and assert its results against the ones in the ‘Expected’ column, and you get a green or red cell depending on the result: LogicFixtureFitTest-RESULT.html:
example.LogicFixture
OpLHSRHSExpected
<11false
<12true
<21false
This is pretty much what you would expect from any other explanation of a fit test, despite my poor eloquence. I promise I’ll make this a bit more interesting, though. For example, with test methods that do, well, interesting stuff. We could go to a database, click buttons, fill forms, or whatever else comes to mind. In this particular project, a web app, we were doing all of those, plus a few more, and we ended up creating new fancy methods as we saw things being repeated over and over. For example, when we saw things like: Login.html:
whatever.WebFixture
ActionFieldValue
enterusernamejohn
enterpasswordsecret
clicksubmit 
We were tempted to change it into this: Login.html:
example.OurApplicationFixture
ActionParameters
loginjohnsecret
Which does exactly the same thing (actually, the code in OurApplicationFixture just calls enter(), enter() and click() in sequence), but it has a better representation and communicates what the test is doing a lot better, and in the same language developers and business analysts use, or at least something closer to that, which is always good in terms of total amount of hair pulled over 40 hours per week. Over time, we ended up creating a lot of these methods, and one of the challenges was organizing them so they were still manageable. We had a great idea, then: why not code test sub-routines using fit itself? BuyTwoProducts.html:
example.OurEvenBetterApplicationFixture
ActionParameters
loginjohnsecret
addproduct12345
addproduct54321
checkout 
Login.html:
whatever.WebFixture
ActionFieldValue
enterusername$0
enterpassword$1
clicksubmit 
Roughly, what OurEvenBetterApplicationFixture does when it can’t find a proper method on the fixture class is to look for a directory called subroutines/ under the fit test tree and find a suitable HTML file, substitute the parameters properly, execute it and include the results in the caller fit test. The end result, then, looks like this: BuyTwoProducts-RESULT.html:
example.OurEvenBetterApplicationFixture
ActionParameters
loginjohnsecret
 
enterusernamejohn
enterpasswordsecret
clicksubmit 
addproduct12345
addproduct54321
checkout 
This way, people looking at the test source still see a simple “login” line, but get to look at the results (and any problems that may show up) in much more detail. I don’t really know if this is something new, and I surely don’t believe has never been thought of before, but as I’m quite new to this Fit testing thing the best way for me to be sure is to actually blog about it and see what kind of discussion it generates, if any. I like extrapolating, though, and the obvious next step after Fit subroutines is to implement branching and looping constructs, and then some sort of closure support, just because everyone loves closures these days. I think it’s a bad idea in this particular context for an infinite number of reasons, but it actually has some kind of coolness. In fact, give this a few years, and I’m sure when we look back, we’ll all laugh and try to figure out what happened to using plain text to edit code. We’ll be programming in spreadsheets by then, and life will be lived very happily thereafter. You know, people writing hardcore macros in Excel today will be the next refactoring and code analysis masters. Come to think of it, one of the great things about the user interface of JetBrains’ MetaProgramming System is using little nifty drop-downy table cells instead of plain-text. Maybe I’m reaching here, but who knows if this is not actually a good way to go?