Port of schuchert.wikispaces.com


Acceptance Testing FitNesse Table Table Example

Acceptance Testing FitNesse Table Table Example

DRAFT

I’m working on an example of developing acceptance tests using a Digital Video Recorder as my problem domain. After several acceptance tests I started working on the idea of season pass priorities. In a nutshell, a season pass says “record all episodes of a given program”. When you add priority, then the highest-priority season pass takes precedence. For example, say you can only record one program at a time and on Monday Evening you want to record House at 7 PM CST as well as Chuck, same time, different channel. If House is the higher priority program, it should be recorded.

So I wanted to create several tests around priority with dimensions like:

First thing I wanted to do was create a schedule to test against. A program has zero to many episodes and I want to be able to create them in different ways. My first thought was to us a script table.

Script Table

I like Script tables because they remind me of Smalltalk. I like to use them when I need to create things that have one to many relationships and I want to create them together.

A program has a normal day and time and is on a channel. An episode can be at any day or time, but is the same day and time of the program by default.

Here is a script table that first creates a program and then adds 4 episodes to it:

|script|Program Scheduler                                                                               |
|$B=   |Create Program Named|BSG|On Channel|247               |Every|Friday   |At      |9:00|Duration|60|
|ensure|Add Episode To      |$B |Named     |He That ...       |On   |2008/4/4 |Duration|45              |
|ensure|Add Episode To      |$B |Named     |Six of One        |On   |2008/4/11|Duration|30              |
|ensure|Add Episode To      |$B |Named     |The Ties That Bind|On   |2008/4/18|Duration|15              |
|ensure|Add Episode To      |$B |Named     |Escape Velocity   |On   |2008/4/25|Duration|10              |

Notes:

This particular example creates one program:

Next, 4 episodes are added to that program with the following names:

Decision Tables

This was fine initially, but for some tests I wanted to make more stuff with less verbage. I needed a lower-fidelity way to create more things. By lower-fidelity, I really mean it was OK for some things to be less flexible (e.g. episode duration always being the same as the default value).

Then I decided to try Decision tables:

|Create Programs|
|Name |Channel|DayOfWeek|TimeOfDay|DurationInMinutes|id? |
|House|4      |Monday   |19:00    |60               |$ID=|

|Create Episodes                                                                |
|Program Id|Name                                                       |Date    |
|$ID       |He figures it out based on something Wilson says.          |2009/4/1|
|$ID       |He's wrong many times but then in the last minute is right.|2009/4/2|
|$ID       |They break into someone's house.                           |2008/3/1|

This accomplishes the same kind of thing in a more succinct manner than the script table.

Noted:

FYI, here’s an example query table to validate these results:

|query:Episodes                                             |$ID                                 |
|name                                                       |date    |startTime|durationInMinutes|
|He figures it out based on something Wilson says.          |2009/4/1|19:00    |60               |
|He's wrong many times but then in the last minute is right.|2009/4/2|19:00    |60               |
|They break into someone's house.                           |2008/3/1|19:00    |60               |

Table Table

As already mentioned, I envisioned my domain with two separate concepts, Programs and Episodes. This might be a mistake but for now I am not considering whether it is or is not. An episode can only exist with a Program. Season passes operate on episodes, not programs. (If anything, removing the Program concept would probably simplify things.) So I needed a way to create a bunch of programs and episodes. I also needed a good way to be able to see what I was doing.

So I came up with the following table:

|Table:Create Schedule                                                          |
|start time|1:00                                                                |
|200       |aaaaBBccccccccDDDDeeeffffffffffgggggggghhhiijklmnopqrstttuvwxyzzzzzz|
|247       |aaaaBBBBccccDDDDeeeeFFFFggggHHHHiiiiJJJJkkkkLLLLmmmmNNNNooooPPPPqqqq|
|302       |aaBBccDDeeFFggHHiiJJkkLLmmNNooPPqqRRssTTuuVV                        |
|501       |____________________aaBBccDDeeFFggHHiiJJkkLLmmNNooPPqqRRssTTuuVV    |
|556       |______aaBBccDDeeFFggHHiiJJkkLLmmNNooPPqqRRssTTuuVV                  |

Notes:

I came up with this right from the domain (and I doubt I’m the first person to do something like list). I was trying to visualize the program schedule to figure out how to create it quickly and it occurred to me that I could do that like I did above.

How is this any better?

Give the above episodes, I can now create the following season passes:

Then, depending on their order, (priority) I can verify that what is scheduled is correct. For example, give the above order and assuming one recording at a time, the “to do” list should include:

If I can instead record two things at the same time, then the “to do” list should include:

And that’s it. If the order is reversed, then the following programs will get recorded:

For me, this makes it much easier to:

This last form was harder to code but easier to write expressive tests. When working with acceptance tests, this seems like the correct trade off.

I used TDD to verify parsing of the table and then connected the table parser to the fixture and got the schedule built quickly.


Update as of March 2009


I was visiting my good friend David Nunn in Dallas and I showed him my “fluent” or DSL-esque table and he said “ugh! that’s ugly!” He looked at it and pointed out that it looked like gibberish and also pointed out that I’d need to use a fixed-point font (I didn’t tell him I put in pre and tags). He was right, of course. So I improved this table to this next version:

|Table:Create Schedule v2                                                 |
|   |1   |2   |3   |4   |5   |6   |7   |8   |9   |10  |11  |12  |13  |14  |
|200|aaaa|BBcc|cccc|ccDD|DDee|efff|ffff|fffg|gggg|gggh|hhii|jklm|nopq|rstt|
|247|aaaa|BBBB|cccc|DDDD|eeee|FFFF|gggg|HHHH|iiii|JJJJ|kkkk|LLLL|mmmm|NNNN|
|302|aaBB|ccDD|eeFF|ggHH|iiJJ|kkLL|mmNN|ooPP|qqRR|ssTT|uuVV|wwww|wwXX|XXXy|
|501|    |    |    |    |    |aaBB|ccDD|eeFF|ggHH|iiJJ|kkLL|mmNN|ooPP|qqRR|
|556|    |__aa|BBcc|DDee|FFgg|HHii|JJkk|LLmm|NNoo|PPqq|RRss|TTuu|VVxx|xxxx|

To get this to work at first, I simply converted the row into a string and parsed it using the original parser. Of course, this only works if each cell is 4 letters long (or the same length). A real parser should handle this correctly. Even so, it greatly improves the match to the metaphor.


Comments

" Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.