Time Clock Example |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Timeclock> start 'misc' Timeclock> pause Timeclock> start 'stqe' Timeclock> jobs misc, started 02002/08/30 4:32 PM, is paused. stqe, started 02002/08/30 4:33 PM, is recording time.I will, in this space, type up thoughts about how I might test TimeClock using this framework. -- BrianMarick Getting Started What you're looking at above is the Ruby interpreter, with prompts tweaked. Each of the commands is a normal top-level ruby method. They each return strings, which the interpreter has been told to print in a human-friendly way. A test framework can call those commands directly, capture the resulting string, and check it. That's what I do in my own acceptance tests, which use NathanielTalbott's xunit framework for Ruby. Notice the date. I could have handled that in two ways:
Note also that I have several lines of output, which I would like to split into substrings that I could talk about individually. Now, for each of those strings, I'll be reluctant to type in the regexp again - that will be a hassle when I decide to change the output format, as I surely will. Ward's Suggestion Ward gives this a try without knowing anything about the real requirements ... The clock has a display which list a number of things that are being timed. Initially the display is empty.
The clock also has a convenient way to select jobs. It has the effect of entering a job code. A small number of buttons operate on the currently running job or the entered job.
At this point the display has two jobs.
Note: These tests use two fixtures to test one program. The Display fixture is an unordered RowFixture which compares results keyed on the field "job". The Action fixture is the generic ActionFixture. Both use TypeAdapter so that all parameter passing and validation is done with a ValueObject if possible, not a string. Brian's Enlargement I think this will work for the GUI version of the app, except that I'd be inclined to write the last table like this:
The reason is that I trust (and verify, with UnitTests) the code to track dates correctly. Here, I just want to check that the ThinGUI is actually showing the right format date. If I were extra suspicious, I might have ValidDate() check that the date was either today or yesterday, and ValidTime() check that the given time was within the past hour or so. But I don't want to build specific times into this test. Note that Ward's solution - one fixture to issue commands, another to accept results - also works for a command-line version. The "display" is the results returned by the last command. So we'd have something like this to invoke commands:
Now we have a DisplayFixture to check the results of the last command:
(I am supposing that the fixture constructs a regexp from the cell contents. I wouldn't want users to have to know about regexps, so everything outside of the squirrely brackets would be quoted. The things inside brackets would then be substituted in, so the first line would be tested against: %r{misc, started \d\d/\d\d/\d\d \d\d:\d\d [AP]M, is paused\.} (That's Ruby syntax, but you get the idea. Note that the period is quoted.) And I can continue the test with more commands: (Here, the test would have a comment: "Notice that the 'misc' job, being the default, resumes when 'stqe' is paused.")
Ward's Continuation Brian continues his exploration and reports his experience online. I've read the October 25, 2002 installment which was very good. (See http://www.testing.com/cgi-bin/timeclock.pl.) Here I will follow along without doing any of the hard work. Instead I will write the tables that I believe a customer could write, though I wouldn't mind if a customer's helper wrote them either. In the following when I say "I" it will be in the role fo customer addressing "you", the development team. I'll use italics when I want to step out of these roles. -- WardCunningham Here is what I'd like to do based on our conversations and my real need to have more than one background activity. First there is always a background activity, even if I don't specifiy one.
Now I want to show you how I want to enter new background tasks. First let's assume I have a few forground tasks already entered.
Here the customer is using a ColumnFixture to just specify setup data without doing any checks. So here is how I'd like to use the "new task" window to specifiy a second background activity.
You may have better ideas how to do this entry, but you get the idea. I'm thinking today, tomorrow and next monday would be sufficent choices for task starts right now. So here is how this would look once entered. I'll do a little work today and more tomorrow. I'll cancel the new background mid day the next day.
This wold have to be a variation on the ActionFixture because it uses new action words, work and rest. See the Realtime fixture in the MusicExample to see how this might be done. Or there could be "fake" fields for work and rest that advance the clock wth lines like: | enter | work | 4 hours | Ok, so that is the first day. Now the second.
Notice how the clock was already running the conference task when I turned it on. We'll have to discuss when a new day starts. Probably not midnight (I work past midnight all the time.) Probably not 8am (Sometimes I start before then, really.) Let's make the background day start at 4am until we think of something better. (Note to self: add check for 4am here before the iteration is over.) Now I'll quit the conference task in the middle of this next day.
So that's three days of use. Here are the times I will have racked up in the interval.
This is a RowFixture that looks directly at the task objects. My background tasks stack up just like my foreground tasks. Here is a typical month. (Assume days are 8 hours, ha ha.) Focus on foreground is the percentage of a period that I'm working on the foreground. Divide it up however you like. I'll do the first week with some detail and then the next three a week at a time.
This is another ColumnFixture just specifying a scenario. Some columns could be added to provide running checks (and would be by the developers, if needed). I'll put month end totals here when I get to them. If you put something in, please note that they are your totals, because I think there might be some situations I want to think through as I add them up. And so ends our fantasy specification from a wise and confident customer. The key thing to notice is that she moved up and down levels of abstraction as she would in a conversation. She knows that she is making fixturing work as she does but she is happy to pay for that too.
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Last edited October 28, 2002 Return to WelcomeVisitors |