Exploration Through ExampleExample-driven development, Agile testing, context-driven testing, Agile programming, Ruby, and other things of interest to Brian Marick
|
Fri, 30 Dec 2005Working your way out of the automated GUI testing tarpit (part 5) part 1, part 2, part 3, part 4 In the last installment, I made an automated GUI test faster—but it still takes three seconds to run. In this installment, I'll increase it to unit-test speeds. In fact, I'll argue that it really is a unit test. The next-to-last step out of the GUI testing tarpit is to convert existing GUI tests into unit tests of rendering and of the business logic behind what's rendered. (The final step is to create workflow tests that really do have something to do with the GUI.)
The existing tests call We can speed up the declarative test by cutting out the network. NullBrowser has the same interface as Browser, but it calls the App directly. The test now runs in around 0.5 seconds. Almost all of that time is spent in XML parsing and XPATH searching. I wish the test were faster, but not enough just now to find a different XML parser.
I next did a little cleanup, removing the fake browser object from the execution path since it really adds no value. I'll skip the details. Suffice it to say that the effort surfaced some duplication hidden behind this surface:
The duplication made me wonder: what's this test really about? Does it have anything at all to do with movement through pages? No, it's about the rendering of pages in the presence of model state that ought to affect what gets rendered. These kind of tests are better described like this: Given an app with particular state, Or, in code:
This is a business-facing test in that it describes a business rule: if you've got one nominal audit, there should be no way to add any more audits. It's also like a unit test in that it gives very specific instructions to a programmer. In my case, the fact that this test fails instructs me to change a particular localized piece of code:
(I'll talk about my rendering peculiarities in some later installment.)
A lot of Fit tests share this property of being about localized
business rules (or business rules that My test here should be one of a file-full of tests that describe what's most important—from a business point of view—about the presentation of a particular place (or interaction context) in the application. Another test of that sort would be this one:
This test describes three facts about the Case Display page's default appearance that must survive any fiddling with how it looks: it must have a title that includes the case's clinic ID, and there must be a way to cause the add-visit and add-audit actions in the App. (This test passes, by the way, though the previous one continues to fail.) Consider this test something like a wireframe diagram in code. Most tarpit GUI tests are addressing, explicitly and implicitly, several issues all jumbled together. If you separate them, you get something that's both faster and much more clear. Here, I've addressed the particular issue of what must be true of a page. Later, I'll address the particular issue of what must be true of navigation among pages. But first, I'll make my test pass and see what that suggests about hooking business rules into rendering. See the code for complete details.
## Posted at 20:30 in category /testing
[permalink]
[top]
Tue, 20 Dec 2005Two Agile Alliance programs you may be interested in
## Posted at 11:11 in category /misc
[permalink]
[top]
Mon, 19 Dec 2005Working your way out of the automated GUI testing tarpit (part 4) The story so far: One of my main goals for tests is that they contain no excess words. That means that a GUI test should not describe the path by which it gets to the page under test. In part 1, I described a declarative format. With it, the test writer specifies all and only the facts that should be true of the app at the point the test begins. Part 2 gives a simple implementation that figures out a path through the app that makes those facts true. Part 3 recommends that you migrate tests to this format only as they fail. The new format tests, though, run as slowly as they did before being migrated. Now it's time to make them faster. I'll do that in two steps. The first doesn't even double their speed. That's hardly sufficient, but the implementation has a side effect that helps the programmer and exploratory tester. Previously, I only pretended the app talked across the network. Since that fakery would make any timings useless, it's now running on a real server (WEBrick), fielding real live HTTP. So localhost:8080 shows this stunningly attractive UI:
In part 1, I wrote three versions of a test. All three of them communicate with the server in exactly the same way: they send eight different HTTP GET commands (just as a browser would if you visited the app and then pressed seven buttons on seven pages). To speed up the test, I've made it remember all eight of the commands the first time it runs. (That all happens behind the scenes; there are no changes to the test.) Now later runs can send the commands in a big glob via a side channel. That avoids seven of the round trips. The results are underwhelming. The original test takes 5.1 seconds. The version that sends the big glob takes 3.2 seconds. The more complicated the test setup path, the greater the speedup would be, but still—is this worth the trouble? Not so far, but it will be after the next speedup. I hope. In the meantime, there's a useful spinoff feature. One of the reasons I hate anything to do with improving a UI is that every time you tweak a page, you have to navigate to it to check whether the change looks right. Having to do that four or five times in a row drives me wild. So I wish this were a universal law: You can get to any page in an app in one step. Now that we can remember application state, that's possible here. Imagine the following: You have to tweak a particular page in the UI. You navigate to that page, then type this:
You go into the code, make a change, reload the app, and return the app to its previous state like this:
The This jump-to-page feature would also be useful for exploratory testing. It's common to go to the same place in the program multiple times during a bout of exploratory testing. Perhaps you're trying to learn more about the circumstances in which a bug occurs (a kind of failure improvement). Or you're trying different paths through the program, each of which starts some distance into it. There's nothing new about using captured commands to accelerate tasks. People have been using GUI capture/replay tools for this kind of thing since the dawn of time. But it's nice that the feature fell out of a different goal. For more about the implementation, refer to part 4b. The code has the complete details.
## Posted at 22:49 in category /testing
[permalink]
[top]
Working your way out of the automated GUI testing tarpit (part 4b) Here are some (decidedly optional) details about the implementation described in part 4. Consider this test:
The next time
Then each command is dispatched to the App object:
That
By doing that, I reduce the suspicion that the restored state is somehow different than the one that app had at the moment the snapshot was taken.
The only difference between the two different routes into the app is
what happens after dispatching.
Notes:
Credit: The idea of replaying server-level commands just popped into my head. It might have been put there by Michael Silverstein's "Logical Capture/Replay".
## Posted at 22:49 in category /testing
[permalink]
[top]
Thu, 15 Dec 2005A working undo command can sure be handy:
Evidence continues to mount that no honorable election official should support voting machines without a paper trail:
## Posted at 07:35 in category /misc
[permalink]
[top]
You know you overuse particular examples on your site when... ... you receive mail like this: I'm impressed with your professional website related to goat and cow milking devices. My website is a NON-COMPETING informational site offering collections of articles, diagrams, and other publications that relate to and may help supplement your website. Since some of your site visitors may be interested in learning more about animal milking devices, feel free to link to my site. By linking to my site, you will be adding value to your own site by providing relevant content for your site visitors. Following is the link I think will be the most helpful for your customers: http://www.braindex.com/products/175+-ANIMAL-(GOAT-&-COW)-MILKING-DEVICE-RELATED-PATENTS-ON-CD-29.htm. Please visit this link yourself and consider inserting it on your website. (I don't think this is phishing or some variant, which would be less interesting than having a search bot—albeit one with wide tolerances and low cleverness—think my site is actually about cows.)
## Posted at 07:35 in category /junk
[permalink]
[top]
Tue, 13 Dec 2005Convention over configuration workbook? Item: I'm fond of Bill Wake's Refactoring Workbook because it shows lots of examples of refactorings in action. Item: Rails is hot, hot, hot these days. Item: One reason it's popular is convention over configuration, which... ... places ease of use for the majority of situations ahead of the need to provide maximum flexibility for the few. The way this is done is through the adoption of coding conventions that automatically embed a certain amount of configuration right into the framework. Convention makes certain assumptions about how things will be put together and by making these assumptions implicit in the code it frees the framework from the burden of having to spell out every intention through explicit configuration. The conventions can be overridden to handle cases where the convention might not be optimal but speed and ease of use are the big benefit that comes from adopting them. Item: Berin Loritsch says: Java applications can be developed using [convention over configuration], but often aren't. The problems come into play when the framework you are using works against you. Other times its just too difficult to do right. You will have to resort to reflection and other black magic tricks. Item: Better Software has had an author drop out. Three times before when that's happened, I've quickly written a replacement article. Two of them have worked out rather well, I think. (You can see them on the sidebar: "Behind the Screens" and "Bypassing the GUI".) Therefore, I'm thinking of writing an article on convention over configuration in Java-style languages. (Despite the chain of thought implied here, the idea was really Mike Cohn's.) The problem is, I don't have any personal experience to draw on. Do you have examples that would let me produce an article with something of the flavor or Wake's book? If so, you know how to reach me.
## Posted at 07:19 in category /misc
[permalink]
[top]
Mon, 12 Dec 2005Working your way out of the automated GUI testing tarpit (part 3) In the real world, you can't leap out of a tarpit in one bound. The same is true of a metaphorical tarpit. Here's a scenario to avoid:
Even if the task is plowed through to the end, it has not changed the habits of the team, so there's no counterforce to whatever forces caused the problem in the first place. I'm with William James on the importance of habit: only when habits of order are formed can we advance to really interesting fields of action [...] consequently accumulate grain on grain of willful choice like a very miser; never forgetting how one link dropped undoes an indefinite number. Therefore, my bias is toward having everyone convert the test suite one failure at a time:
Some fraction — perhaps a large fraction — of the old tests are likely to be worthless. (More precisely, they're worth less than the cost of reviving them.) It's hard to persuade people to throw away tests, but nonetheless I'd try. (There are unknown risks to throwing tests away. My bias would be to do it and let the reality of escaped bugs make the risks better known. Tests can always be un-thrown away by retrieving them from Subversion.) A tempting alternative is simply to delete the old test suite and start over. Spend the 20 minutes writing a new test instead of reviving a failed one. That might well be time better spent. But it's a tough sell because of the sunk cost fallacy.
## Posted at 13:06 in category /testing
[permalink]
[top]
UI design links from Jared M. Spool What makes a design intuitive? is nice and readable short article about the two ways to make an interface that people will call intuitive. Designing embraceable change is a follow-on that talks about how to introduce a new UI to an existing community. This has relevance to Agile projects that are continually tinkering with the UI. The series ends with The quiet death of the major relaunch. Here's a trivial example of the approach:
The key point in this last article is this: Our findings show that consistency in the design plays second fiddle to completing the task. When users are complaining about the consistency of a site, we've found that it is often because they are having trouble completing their tasks.
## Posted at 10:22 in category /links
[permalink]
[top]
In my role as the overcommitted and underskilled Agile Alliance webmaster, I add new corporate members to the site. I realized today that we really have quite an impressive variety there. You can find companies in out-of-the-way places (Topeka, Kansas, USA). It's less easy to find companies that have particular skills, since the blurbs don't generally focus on a company's specific competitive advantage. Nevertheless, I recommend it to you if you're looking for a consultancy. P.S. Not me, though. Exampler Consulting isn't a corporate member because I've never gotten around to getting a logo. P.P.S. Corporate membership was Rebecca Wirf-Brock's idea.
## Posted at 10:22 in category /agile
[permalink]
[top]
Sun, 11 Dec 2005Working your way out of the automated GUI testing tarpit (part 2) In the previous installment, I described a test that looked like this:
The test doesn't tell how to get to the case display page, create an audit record, create the visit record that audit records require, etc. The code behind the scenes has to figure that out. I won't show that code. You can find it here. It's a spike, so don't give me a hard time about the lack of tests. What matters is that it works off a description of what transitions are possible in the program. They look like this:
Given a complete set of definitions, statements like this one:
name "milestones" along the path the program has to take to get ready for the test. A simple breadth-first search constructs a complete path out of the milestones. The path contains appropriate instructions to fill in fields and press buttons. Thus a declarative test is turned into a procedure. P.S. In the declaration, the button's name is given. That's wrong. It should be the HTML id. Like I said: a spike.
## Posted at 09:36 in category /testing
[permalink]
[top]
Thu, 08 Dec 2005Working your way out of the automated GUI testing tarpit (part 1)
Here are three GUI-oriented tests, in increasing order of goodness. The scenario has something to do with a veterinary clinic (of course). In each test, a case record is created, an animal visit is recorded, and an audit record is appended. (All the steps are necessary, because you can't record a visit until there's a case, and you can't create an audit record until there's a visit.) Normally, there can be multiple audits attached to a case. But if the first audit is marked as "nominal", it's the only one that can ever be created. If so, there should be no "Add Audit" button on the Case Management page. That's what the test checks. (It also uses the title of the page to make sure the assertion is checking the right page.) The first test is like one you might get from a straightforward use of Watir or jWebUnit.
What are the problems with this test?
To solve the problem of fragility, some people put a library between the tests and the browser. Here's what such a test would look like:
I believe such a test is still not good enough. It's still procedural - it's still of the form "do this... now this... now this... finally you can check what you care about." Here's a better test:
In the next installment, I'll show what the code behind the scenes looks like. Right now, I want to emphasize that all three tests do the same thing. Here's an execution log for the third test:
## Posted at 08:02 in category /testing
[permalink]
[top]
Mon, 21 Nov 2005I've been corresponding with Rachel Davies about story card style. She said something wise. Here's a slightly edited version of the correspondence (with her permission). It all began when I asked a question about the "As a [role], I want [ability], so that [benefit]" style of writing stories. (See Mike Cohn's User Stories Applied for a description.)
## Posted at 09:38 in category /agile
[permalink]
[top]
Two oblique commentaries on abuse
## Posted at 09:15 in category /misc
[permalink]
[top]
Fri, 18 Nov 2005Two milestones, noticed while paying bills I am now a million-mile member of the American Airlines frequent flier program. This entitles me to two luggage tags. I am also entitled to a Free! "Guide to Planning and Promoting Your Business Anniversary" in honor of fifteen years of business. Yippee. P.S. Hugh Sasse points out that the Ruby extensions library has a method like the one that's mentioned below. After a quick glance, I think it's better than mine. P.P.S. Oh, OK, I also get eight upgrade segments and permanent Gold membership. And a membership card that says "1 Million" on it.
## Posted at 11:38 in category /junk
[permalink]
[top]
Mon, 14 Nov 2005Attractive Ruby tests that use multi-line strings Suppose you're testing some method whose input is a multi-line string. You could write something like this:
That's fine - unless whitespace in the middle of the string is significant. The above method has no whitespace on the string's first line, but a whole lot on the others. What if I needed it all to be flush left? This is ugly:
I could argue that the ugliness makes it too hard to see the structure of the test and too hard to skim a file quickly and see what the tests are. That argument may even be true, but the real reason I don't like it is that it's ugly. So I write such tests like this:
I've fiddled around with
## Posted at 17:00 in category /ruby
[permalink]
[top]
Sun, 13 Nov 2005In part of "When should a test be automated?", I look at tests that have broken because the intended behavior of the code changed. My urge is to fix them, but I stop myself and ask a question: if this test didn't exist in the first place, would I bother to write it? If not, I shouldn't bother to fix it. I should just delete it. Here's an example where that practice would have led me astray.
I've been hacking
away at the code in RubyFit that parses HTML. I'm changing it so
that it will support Rick Mugridge's FitLibrary. To that end, I
created a class, TagSlices, that splits HTML text at tag
boundaries. For example, the TagSclices of I'd looked at the Java implementation before starting. That code operates on a lowercased string for tag-matching, but returns chunks of the original string. In the implementation I started moving toward, maintaining the two strings was inconvenient, so I talked myself into thinking I could downcase the original string at the start and work only with that. Stupid (people sometimes do use capital letters in web pages), but I was backing away from a frustrating implementation closely modeled after the Java one - and thus un-Ruby-like and hard to get right. I was so focused on tags that I thought what was OK for them was OK for everything. I'd generated TagSlices using a set of tests that did not reveal the bug. After I was done, I reran the unit tests for the old version. (I hadn't used them for development because they "chunked" the problem in a way that didn't fit the path I was taking.) Here's one of those tests:
It failed on the line marked with an arrow. I thought about that. Was the failure due to a bug? No, I'd decided it was harmless for tags to change case. Did any other assertion fail? No. Was the test completely redundant with other tests? It seemed so. So I should have thrown the test away. But I hesitated. After all, the changed behavior was a side effect, an implementation convenience. It would be just as harmless for tags to keep their case and pass the test. Maybe that wouldn't be as hard as I'd thought when I'd started. I looked at the code and it suddenly flashed on me that lowercasing the whole string wasn't harmless at all.
And, moments later, I realized that Ruby
is a scripting language, after all; as such, it lives for
regular expressions. Maybe in the Java world, it makes sense to
search a lowercased string for So I created a test that talks specifically about case in tags and non-tag text. I made it pass. The old test passed, too. I could have thrown it away. And yet... what else might it uncover someday? So I kept it. I shouldn't extrapolate too much from a single example, but it makes me wonder. Seven years ago, when I wrote the paper, I was solidly embedded in the testing culture, a culture of scarcity, one in which:
Those assumptions are less true today. Because of that, it makes more sense to change old tests on the off chance you might find bugs or learn something. One of my other testing guidelines is to seek cheap ways to get dumb luck on your side. I'm not smart enough to do without luck. (That's not false modesty: I bet you aren't either.) Fiddling with tests is perhaps now cheap enough to be a luck generator. (P.S. The bug would have certainly been caught by even the simplest realistic use, so it wouldn't have survived long.)
## Posted at 18:02 in category /testing
[permalink]
[top]
Java is a good thing. Rails is a good thing. But just as Java /perpet[ur]ated/ the horrors of StudlyCaps on those of us who like to read quickly, Rails is /perpet[ur]ating/ underscores in filenames on those of us who like to write quickly. There are legions of examples of people not acting according to their rational self-interest. Yet another is the prevalence of filenames like webrick_server.rb over webrick-server.rb. Does an underscore take more energy to type than a dash? Yes. Does avoiding a typo require more coordination? Yes. So why this pathology?
Whatever the reason, we must consider the result. Thousands upon thousands of people already suffer from Emacs Pinky. To add injury to injury, those fragile pinkies must suffer additional unnecessary damage striking the shift key. How many people have been forced to switch to vi because those underscores pushed them over the edge to pinky RSI? That's a tragedy no caring person can ignore. You have a lot to answer for, David HH. I was this close to convincing the world to use dashes, and now there's no hope.
## Posted at 18:02 in category /junk
[permalink]
[top]
Sun, 06 Nov 2005[Austin's procedure] consists in recognizing that [...] failure is an essential risk of the operations under consideration; then, in a move that is almost immediately simultaneous [...] it excludes that risk as accidental, exterior, one which teaches us nothing about the [...] phenomenon being considered. Jacques Derrida, Limited Inc, p. 15. This puts me in mind of a commonplace of UI design: that a popup error dialog should prod you to reexamine the system. Can it be changed to make the error impossible? or a modal dialog unneeded? For the latter, see Ward Cunningham's Checks pattern language, which - if I recall correctly - treats entering bad input as an inherent part of entering input, something to be fixed at the human's convenience, not something to interrupt the flow. It also reminds me of my insistence that Agile projects are learning projects, and that you're probably not learning how to do something right unless unless you try variations and extensions that turn out to be wrong. But there has to be a way of talking about it that doesn't use the words "mistake" or "wrong" because - hard as it may be to believe - a lot of people think those are bad things.
## Posted at 22:01 in category /misc
[permalink]
[top]
Fri, 04 Nov 2005In my first AYE session ("An amateur's guide to communicating requirements"), up to 1/3 of the participants will teach some skill to other members of their group. It might be a card trick, a coin trick, origami, building a house of cards, juggling, situps, headstands, or flipping pancakes over in a skillet. It's best if the skill involves some object. Due to Circumstances Beyond Our Control, attendees weren't sent email asking them to bring objects if they have a skill to demonstrate. So if you're coming to my AYE session, please bring any objects you need to demonstrate your skill. Thanks, and please spread the word to anyone you know is coming.
## Posted at 07:35 in category /misc
[permalink]
[top]
Wed, 02 Nov 2005A thought, inspired by the CSS2 specification Specifications are a tool for resolving disputes. They are not a communication or teaching tool. Sentences in a specification are the tangible and checkable evidence that a dispute among specifiers has been resolved. The specification is also used as strong evidence when two programmers have an implementation dispute, or when a tester and a programmer do. But almost no one, given the option, would choose to learn CSS by reading the specification. That suggests that a specification should not be written to a consistent level of precision. Precision is needed only where disputes have already occurred or are likely. You can be happy when politics and economics allow you to let all precision be driven by actual, rather than anticipated, disputes.
## Posted at 21:46 in category /misc
[permalink]
[top]
Here are three links I plan to point clients at:
## Posted at 21:46 in category /fit
[permalink]
[top]
Tue, 01 Nov 2005Jonathan Kohl and I have been having a little conversation prompted by my comments on the Satir model of communication. He listed three questions he asks himself as he interacts with his team:
He thinks of these in terms of Satir's notion of congruence, which is not an idea that rocks my world. (I'm more interested in external behavior than internal state: what I do in the world rather than my position in relationship to it.) The value of the questions is independent of their background, I think. I've added a fourth:
I think I use that to square Jonathan's sentiments with my suspicion that there's a lot of useful manipulation out there. Consider what I do as a coach. An ideal coach - which I am not - will act mostly by exploiting opportunities to jiggle someone else into discovery. I learn best through discovery, and it seems most people I work with are the same. So I am actively training myself to hold back, keep my mouth shut, and let my pair run with an idea, all the while being ready to say things that will help her realize what's happening. Then we can talk about it. (I've noticed that Ron Jeffries is substantially better at this than I am.) The nice thing about this approach is that it gives me room to be wrong. A lot of the time, what I thought would happen doesn't - her idea was better than mine - and a variant lesson gets learned (by both of us). Nevertheless, it'd be fair to call me manipulative. The saving grace is that I'm happy for people to know what I'm doing; I don't believe writing this note will make people trust me less. The focus on trust also keeps me from overdoing it. I resent it when teachers put me in an artificial scenario where they know precisely the troubles I'll have and what lessons I will not be able to avoid learning. I don't trust such people. From experience, I doubt they'll be tolerant of the perverse conclusions I tend to draw. So when I draw them, things turn into an Authority Game with a dynamic of them proclaiming Trvth at me and me being resistent. (The devolution into such a game is an example of putting process above people. I bet my fourth question is, strictly, subsumed by the remaining three. But "men need more often to be reminded than informed" (*). Given that I do have a regrettable authoritarian streak, redundancy is OK.) I think Jonathan's questions will help me, going forward. (*) Warren Teitelman, I think. He was giving a talk on the Cedar programming language and programming environment.
## Posted at 07:35 in category /agile
[permalink]
[top]
Sun, 30 Oct 2005Welcome, Better Software readers In my editorial for the November Better Software, I use the string of numbers at the top of my blog as an example of a big visible chart. They've helped me lose about 25 pounds. Especially once I started meeting people who told me they tracked them, my impulse to show the world steady progress remained strong for about 20 of those 25 pounds. (I've even met someone who said he was inspired to do the same with his blog.) More recently, progress has been more fitful, as can be seen by the abundance of red. (Green means I've lost at least two pounds in the week, red means I've lost some but not enough, and bolded red means I've gained weight.) My just-ended three-week trip (to PNSQC, RubyConf, OOPSLA, and a client site) did special damage. Naturally, I did that damage just as the November issue is being mailed. But next week will be green.
## Posted at 21:48 in category /misc
[permalink]
[top]
A thought on mocking filesystems (Sorry about the earlier version of this. I wrote some notes locally and then accidentally synchronized with testing.com.) Sometimes people mock (or even just stub) some huge component like a filesystem. By doing that, you can test code that uses the filesystem but (1) have the tests run much much faster, (2) not have to worry about cleaning up because the fake filesystem will disappear when the test exits, (3) not have to worry about conflicting with other tests running at the same time, and (4) have more control over the filesystem's behavior and more visibility into its state. I was listening to someone talk about doing that when I realized that any component like a filesystem has an API that's adequate for a huge number of programs but just right for none of them. So it seems to me that a project ought to write to the interface they wish they had (typically narrower than the real interface). They can use mocks that ape their interface, not the giant one. There will be adapters between their just-right interface and the giant interface. Those can be tested separately from the code that uses the interface. Arguing against that is the idea that giant mocks can be shared among projects, thus saving the time spent creating the custom mocks required by my alternative. But I'm inclined to think it's a good practice to write an adapter layer anyway. Without one, it's painful to swap out components: uses of the old component's API are smeared throughout the system.
## Posted at 21:28 in category /coding
[permalink]
[top]
Thu, 13 Oct 2005At PNSQC, Michael Kelly gave a talk. Among other things, it covered converting functional test scripts into performance test scripts. He gave examples using several tools, one of them Watir. As he described how little of the test script had to change to make it a performance test script, I realized that there was a way to make it require no changes. I didn't quite finish a demo during his talk, but I did shortly after. Here's an example: Load (a fake version of) Watir, get an object representing IE, and ask it to go to a URL. irb(main):001:0> require 'watir' => true irb(main):002:0> ie = IE.new => #<IE:0x329144> irb(main):003:0> ie.goto('url') => "here's a bunch of HTML" (I faked out Watir because I didn't have net access and, anyway,
this machine is a Mac.) What you can't see in the above is
that Now I want to run the same "test", timing all gotos. irb(main):004:0> require 'perf' => true irb(main):005:0> IE.time(:goto) => nil irb(main):006:0> ie.goto('url') 1.000129 => "here's a bunch of HTML" It took just over a second. Here's the code. Mike will be seeing about getting something like it into the Watir distribution. class IE def self.time(method) method = method.to_s original_method = '__orig__' + method new_def = "alias_method :#{original_method}, :#{method} def #{method}(*args, &block) start = Time.now retval = #{original_method}(*args, &block) puts Time.now - start retval end" class_eval(new_def) end end Take that, WinRunner!
## Posted at 15:08 in category /ruby
[permalink]
[top]
Tue, 11 Oct 2005I started my PNSQC talk by asking for three volunteers. I handed each a Snickers bar and told them to eat it. After they did, I asked whether they were confident their body would be successful at converting that food into glucose and replenished fat cells. Then I gave them part of the CSS specification. I asked them whether they thought they could be successful at converting that information into a conformant implementation. Unsurprisingly, they thought digestion would work and programming wouldn't. How odd, I said, that digestion and absorption works so much better than the simpler process of programming. The idea here was to set the stage for an attack on the idea that (1) we can adequately represent the world with words or concepts, and (2) we can transmit understanding by encoding it into words, shooting it over a conduit to another person, and having them decode it into the same understanding. Things did not go exactly as planned. After I gave them the Snickers bars, I was surprised when they balked and asked me all kinds of questions about eating it. I thought they were deliberately giving me a hard time, but one of them (Jonathan Bach) later told me that he was honestly confused. He said something like, "it would have been much clearer if you'd shown us what you wanted by eating one yourself." ... if I hadn't tried to transmit understanding down the conduit... ... if I'd explained ambiguous words with an example. In a talk about the importance of explaining with examples. I'm glad Jonathan was clever enough to catch that, because the irony of it all would have forever escaped me. P.S. It now occurs to me that another problem was that they didn't know why they were to do it. That's something I also covered in the talk: "justify the rules" from the list of tactics. I don't mind not telling them why, since telling them would have spoiled the effect, but not using an example just makes me slap my head.
## Posted at 07:39 in category /agile
[permalink]
[top]
Communication between business and code In a few hours, I'll be giving a presentation at PNSQC. It's on communication between the business experts and the development team. After some audience participation involving Snickers® bars, trapezes, and Silly Putty® (actually, only Snickers bars) and some airy-fairy theorizing, I get down to discussion of 16 tactics. Here they are. When it comes to teaching programmers and testers about a domain, examples matter more than requirements. It's fine to have statements like "always fill stalls up starting with the lowest number, except for the sand stalls and the bull stall". But when it comes time to be precise about what that means, use examples (aka tests). I think of requirements statements as commentaries on, or annotations of, examples. It's best to build examples with talk around a whiteboard. There, a business expert explains an example to a small audience of programmers, testers, technical writers, etc. The conversation includes these elements:
In all of this, attend to pacing. The programmers have to learn about the domain. It's easy to overwhelm them with exceptions and special cases while they're still trying to grapple with the basics. So start with basic examples and consider the elaborations once they've demonstrated (through working code) that they're ready for them. Give the product expert hands-on fast feedback. Anything written down (like examples, tests, or requirements document) puts the reader at one remove from the actual thing. Consider the difference between test-driving a car and reading about a test drive of a car. So quickly implement something for the product owner to look at. That will allow her to correct previous examples and also learn more about how to communicate with the team. It's also important for everyone to work the product. You don't learn woodworking by looking at examples and listening to someone talking about woodworking. You learn by working wood. The programmers, testers, etc. on a team don't need to become experts in the business domain, but they do need to learn about it (again, so they can make unforced choices well). Having people use the product realistically, especially in pairs, especially with the business expert near, will help them. I recommend exploratory testing techniques. James Bach's site is the best place to learn about them. I think of the team as building a trading language. This is a language that two cultural groups use to cooperate on a common goal. (See also boundary objects.) In a trading language, the programmers and business expert will both use words like "bond" or "case" -- indeed, it's best if those words are reified in code -- but they will inevitably mean different things by them. It's important to accept that, but also to attend to cases where the different meanings are causing problems. I happen to also think that the business expert should become conversant in the technology domain, just as programmers become conversant in the business domain. That doesn't mean to become a programmer, but it does mean to come to understand enough of the implementation to understand implementation difficulties and opportunities. Finally, since understanding is built, not simply acquired, it's important to attend to learning through frequent mini-retrospectives. Is the development side of the team learning the domain? Is the business side learning about the implementation? Is the business side learning about the domain? -- I think any project where the business expert doesn't gain new insights into the business is one that's wasted an opportunity. Is everyone on the team learning about communication?
## Posted at 07:39 in category /agile
[permalink]
[top]
Sun, 09 Oct 2005In my Pacific Northwest Software Quality Conference talk, I'm going to throw out a blizzard of references. Here they are.
That's where I end, having given 16 tactics for improving communication, each compatible with this nonstandard view. My ending motto is this: As intermediaries, we do not need to send abstractions down the conduit from the business to the programmer. Anything that provokes the programmer to write the right code is fine by us.
## Posted at 09:49 in category /misc
[permalink]
[top]
Sat, 08 Oct 2005Satir's models of communication, change, and communication stances are influential among those who worry about software team dynamics. I'm uneasy about them on two grounds.
But that's not what I mainly wanted to write about. In the communication stances model, the ignoring of Other leads to Blaming behavior. If I model my own behavior that way, I'd say Blaming is not often the result. What I do more is Unstoppable Framing and Advice-Giving. It's figuring out what the problem and its context are, plus throwing out all kinds of potential solutions. That's different than Satir's Super-reasonable behavior, which is "cool, aloof, reasonable, and intellectual". I'm not cool or aloof; I'm usually passionate and determinedly optimistic - "hey, how about this. It would turn the problem on its head and make it a neat opportunity." That's helpful behavior except when it becomes more about me and less about the Other I'm supposedly helping, when it becomes a way to shift the issue away from what the other person needs to what I'm good at doing: problem-solving, idea generation, and talking. I'm using the Context as a way of making my Self comfortable. The solution (there I go again) is to make sure to let the Other guide the conversation. I bet Dawn (who's witnessed more of this from me than anyone else has) would describe it as stereotypically male behavior. It probably is statistically more common among males. But I'd be willing to bet it's an occupational hazard for consultants. So, by Box's criterion that all models are wrong, but some are useful, Satir's model is useful. I don't use it much, though.
## Posted at 18:31 in category /misc
[permalink]
[top]
Wed, 05 Oct 2005I've become fond of FitLibrary's CalculateFixture. The second table below is an example:
The columns to the left of the blank column are input values. Those to the right are expected results. The blank column is a nice visual separator. Each line of a table should be easy to understand. Sometimes that means annotation. I've hacked my copy of CalculateFixture to allow notes after yet another blank column. Like this:
That's easily done in the 9Feb2005 version. In
And remove an error check in
I'd like to see this change become part of FitLibrary. It cannot break existing tables (because of the error check). The error check would no longer catch mistakes in the table, but I can't see such a mistake lasting past the first time someone tried to make the test pass. It would be easy enough to change the error check to take blank columns into account, but I doubt I'd bother.
## Posted at 15:31 in category /fit
[permalink]
[top]
Sat, 01 Oct 2005For my talk at the Indianapolis Quality Enrichment Conference (October 7), I could sure use some pictures of an Agile project in action. I'd like to show a daily standup and a product owner explaining a story, preferably using a whiteboard. If anyone can mail me some, I'd be much obliged and would give credit. Thanks. I've got other pictures I think I need, but if you can think of events or settings that people really ought to see, send them along. Even if I don't use them this time, this probably won't be my last talk about Agile.
## Posted at 18:01 in category /agile
[permalink]
[top]
Fri, 30 Sep 2005A while back, I stayed at a Marriott hotel. Around US$150 at a reduced conference rate, plus US$10 for wired high-speed internet. Not long before then I'd stayed at a no-name hotel for US$70. It had free wireless. Why the difference? I suppose it's just whatever it is that makes
hoteliers think the more expensive the room, the more expensive
should be the bottle of Aquafina water placed But I also toyed with the thought that it could be a form of first-mover disadvantage. Marriott no doubt put in high-speed internet before wireless was even an option. The other hotel waited. I suspect it's a lot more expensive to string wires all over the hotel than to put up wireless hubs. Having strung those wires, was Marriott now stuck when wireless came along? Were there financial or emotional (sunk cost fallacy) reasons for sticking with a solution that's been superseded? Are early adopters of Agile subject to the same? Are they (we?) prone to getting stuck at local maxima? I suppose that's inevitable. It's sometimes said that the fiercest critics of this generation's avante garde isn't the boring old mainstream; it's last generation's avante garde. Bob Martin said at Agile 2005 that industry seems to be converging on a standard Agile approach: Scrum with a subset of the XP practices. That's good, but what's the next step beyond that? I personally think it's about the Product Owner / Customer. People used to say things like "programmers can't test their own code" or "programmers are asocial" or "requirements must be complete, testable, and unambiguous." Turns out we now know (mostly) how to make those things untrue. There are a lot of statements about product owners that are like that. How many of them have been made untrue? Doesn't seem like many. So I bet there's work to do. One such statement is "To the product owner, the UI is the software." I've heard that as a support for Fit ActionFixture over DoFixture. Not because ActionFixture describes the actual UI, but because product owners can grasp that metaphor, whereas DoFixture would be too abstract. Now, I'm biased, because I think that it's almost always the business logic that delivers the value. The UI is a way to make that value accessible. It's secondary. So I want the product owner to think, um, like me. Or better than me - to come to some product understanding / conceptualization / language that's surprising, that reveals product possibilities in the way that refactoring reveals code possibilities. The question is: what nitty-gritty techniques can be used for that? It makes no sense to go up to someone and say, "Reconceptualize your domain!" I have a low opinion of teaching people how to think, and a high opinion of teaching them how to do.
## Posted at 19:53 in category /agile
[permalink]
[top]
Wed, 28 Sep 2005Upon the occasion of a school meeting Our children go to publicly-funded schools, partly because I buy the argument, from The End of Equality, that it's been important for US society that we've had places where citizens of different incomes and classes mix. My son has some developmental difficulties. Nothing major, nothing romantic - but a need for help with fine motor control, speech, and some social interactions. I've worked with big organizations and small, old ones and young ones, monopolies and competitors. I have a bias - both instinctive and learned - toward the small, the young, and the competitive. (I was once on the technical board of a small company that had a niche market to itself, and I watched how the appearance of a competitor concentrated their mind on bettering the product. It was a wonderful example of how competition is a burden placed on organizations for the benefit of the rest of us.) So I should be - am - naturally suspicious of the public school system, which is large, set in its ways, bureaucratic, and much like a monopoly. But I'm here to tell you that the people - teachers, administrators, school therapists - have, almost without exception, been wonderful. I've been around. I know the difference between people just doing a job and people motivated to do a good job. These people would be a credit to any organization, even the smallest, youngest, and leanest. It's almost as if employees can be motivated by something other than money and status. So the next time you hear a politician speaking scornfully of the teacher's union or the school system, just remember there are a lot of good people in those organizations. Not only are they working hard with resources so limited they make your organization look like the US Congress funding public works in Alaska, they're doing it while enduring constant insults.
## Posted at 07:53 in category /misc
[permalink]
[top]
Hardly anyone thinks the software industries do a satisfactory job of getting the requirements / architecture / design right up front. The reaction to that, for many many years, has been that we should work smarter and harder at being right. Agile flips that around: we should work smarter and harder at being wrong. We should get so good at being wrong that our predictive failings do no harm to us, our project, our employer, or our users. In fact, we should strive to make mistakes---the need to redo---a constructive resource.
## Posted at 07:53 in category /agile
[permalink]
[top]
Fri, 23 Sep 2005Long ago, I learned to fly gliders. Since they don't have engines, they're towed up into the air. So you spend the first minutes of your flight at the end of a long rope that's tethered to a tow plane. As a pilot, your job is to keep your glider in a good position relative to it. As a novice pilot, I had a problem with "porpoising." I might drift up out of the right position, so I'd push the stick forward to descend, but I'd overcorrect so I'd descend too far, so I'd pull the stick back but this time get even higher out of position, so... Eventually, you can oscillate so badly that you become a danger to the towplane. One time, my instructor gave me some advice. "Don't just do something, sit there," he said. Let your status stabilize and become clear before you correct. And, I extrapolate, make small corrections that stabilize faster so that you know more quickly what you've done. I think of that slogan every once in a while.
## Posted at 09:45 in category /misc
[permalink]
[top]
Wed, 21 Sep 2005On the agile-testing list, someone asked this question:
Here's my answer, which goes afield into business-facing test-driven design. My inclination would be to test the business rule directly. Here, I'm using Rick Mugridge's CalculateFixture. With it, the inputs and expected results are separated by a blank column.
(An alternative would be to have a single column
named What are we really testing here? Assuming that the reactor is event-driven-ish, it's that the reactor has the right reaction to a particular event. Were the fixture written in Ruby, it would have two methods like this:
The name of the method indicates that it's the one called to
check
We have to decide what the system under test does and what the
fixture does. (A truly hardcore TDD person would put everything in
the fixture until there was some reason to move it into the
product; I'll skip that.) I'm going to assume the system under test
is in the variable
The two questions in that code raise questions for the team. Consider the second. It's the product expert we go to when we want to know what form operator notification should take. (Hoping all the while that she knows more about human factors than we do.)
What the second choice lets us do is defer the decision about the details of operator notification until later tests. All I need to know now is that it at least makes a log entry. Never decide today what you can put off til tomorrow.
So I could
write
So what this test is forcing me (as the programmer) to do is lay
down the first bits of event-handling code and possibly the first bits
of logging code (which would be a matter of starting to use Log4R or some other
logger). Similarly, writing
So this single high-level test only produces some high-level
structural code. Each of the inexact terms -
## Posted at 12:48 in category /agile
[permalink]
[top]
My son is going to a birthday party this weekend. He wanted to get the birthday boy (Jody) two plush toy giant microbes. He chose Ebola and flesh-eating bacteria. (Yes, this was after I made several attempts to get him to choose something less gruesome, like the common cold or ulcer, because I didn't want his mother to think "what kind of bizarre child does my Jody hang around with?" But Paul insisted that Jody really likes that kind of thing. (What kind of bizarre child does my Paul hang around with?) In any case, he prevailed, and I purchased the two toys at ThinkGeek. Along the way, I took their 46.4 second feedback survey. It asks what your favorite language is. I scanned down to the Rs and was appalled to find that Ruby wasn't listed, though Rebol and Rexx were and Python was just above them. But I later noticed that the list is not entirely alphabetical. Certain languages have been promoted to the front of the list: C, C++, Objective C, Perl, Java, ..., and Ruby. This is the big time, folks. P.S. If you're from ThinkGeek: sorry about the rant in your Suggestions / Comments / Thoughts / Rants text area. That was before I noticed Ruby at the top.
## Posted at 09:25 in category /ruby
[permalink]
[top]
Wed, 14 Sep 2005It seems that while I've been struggling with a single chapter of Scripting for Testers, Esther Derby and Johanna Rothman have written an entire book: Behind Closed Doors: Secrets of Great Management. (I think the fourth complete rewrite will nail this chapter & the hardest part of the book. Smooth sailing from then on, he said with a confident grin, unaware of the iceberg looming behind him.) (Just kidding, by the way: they've been working on this book for quite a while, and I'm sure it will show.)
## Posted at 07:29 in category /misc
[permalink]
[top]
Janet Gregory has provided a sample test plan she's used on agile projects. (In Word and RTF formats.) It's common for the words "test plan" to be used for a list of descriptions of test cases. (Thus, you sometimes hear people on agile projects responding to the question "Where's your test plan?" by pointing to the automated test suite.) That's never made sense to me. When I think of test planning, I think in terms of handoffs. At some point, the code is handed off from one set of people to another. For example, a release is a handoff from the production team to the users. That's the main handoff, but a geographically-distributed, multi-team project might have internal handoffs as well. Everyone should want the receiver of the code to smile. Testing is the activity of predicting whether they actually will smile. Test planning is making sure that everything is in place for that activity to happen smoothly when it's time for it to happen. For example, machines may need to be bought for configuration testing, and the purchasing process may need to start several iterations before the testing starts. I wrote a paper about that once (PDF).
## Posted at 07:12 in category /agile
[permalink]
[top]
Thu, 08 Sep 2005The Pragmatic Press has published Chad Fowler's book My Job Went to India (And All I Got Was This Lousy Book). I haven't read it, but I know Chad and he did write an article for me. The article was about ways to think about career choices, tricks for keeping your skills up to date, and advice on marketing yourself for the marketing-averse. The book appears to be on the same topics. Check it out.
## Posted at 11:49 in category /misc
[permalink]
[top]
Unit tests used to generate documentation Grig Gheorghiu has been poking around with the idea of using tests to generate documentation. Here is what he's been doing. Here is a sample of API documentation that another project generates from this code. (Note: the tests aren't written in xUnit style with explicit asserts, but rather by using a line markup style that I first saw in Updoc.) See also Brian Button's PDF article about tests as documentation (from Better Software). Brian's article isn't about generating documentation, it's (mainly) about how to write tests so that they're useful explanations of how to use an API. Fit uses the "look at the tests themselves" style, since the tests are HTML. I find myself fiddling around, trying to make tests nicely readable, but I find I'm hobbled by the lack of a good HTML editor (much less a good Fit-aware HTML editor). I've been put off using Word because (a) my versions generate horrible-looking web pages, (b) I am morally offended by the garbage it generates as HTML source, (c) I try to avoid using binary files with version control systems because you can't usefully diff them, (d) it sometimes produces incorrect HTML (most memorably when it added extra columns to tables), and (e) I don't know how to script Word so that running the test I'm working on is one button click in IDEA. I haven't tried Open Office (because I think it's lagging on the Mac), though I've heard people prefer it to Word for HTML generation. I like simple layouts, so simple HTML would be fine for me (were it easier to edit). If a colocated team wanted prettier documentation, I'd be suspicious of their focus and priorities. But if the onsite product owner has to bring the Marketing Department into the decision loop, and the Marketing Department is three floors up with important representatives in another city, and they're used to attractive Word documents, weaning them off of requirements documents in favor of annotated customer-facing tests will sometimes require a certain amount of flash. For example, it should be easy to drop in a wire-frame sketch of a GUI.
## Posted at 07:56 in category /agile
[permalink]
[top]
Fri, 02 Sep 2005I don't have a television, but I've been following the Katrina situation a bit obsessively on the net while Sophie's been home sick from school. I'm afraid of a narrative taking hold about New Orleans: that the people trapped there are less deserving of sympathy because (1) they had the chance to get out and didn't take it, and (2) they are lawless looters and shooters. I'd like people to read this first-hand account of eight people behaving nobly, written by a volunteer rescuer. Because his permalink doesn't work (at least for me), I reproduce it in full:
Update: If you follow the original link and read the cries for help, it will break your heart. It will also put the lie to the "they should have known better" narrative. Some should have. Not all: Story: THERE ARE ABOUT 40 ELDERLY & MENTALLY DISABLED CITIZENS TRAPPED IN AN APT COMPLEX AT 1226 S. CARROLLTON AVE . 90+ YEAR OLD FATHER OF A FRIEND HERE IN LAFAYETTE..NAME IS DELERY LANDRY HE IS IN APT 315..NO FOOD OR WATER & THEIR CAREGIVES LEFT THEM PRIOR TO STORM...THEY MAY NOT HAVE ENOUGH INSIGHT TO MAKE THEMSELVES NOTICEABLE TO RESCUERS...MATER DESOTO APTS NEXT TO CHURCH ON 1226 S CARROLLTON AVE. 10 RESIDENTS PER FLOOR..4 STORY BUILDING..PLEASE HELP THEM QUICKLY...DAUGHTERS NAME IS SUSAN LANDRY CHIQUELIN FROM LAFAYETTE SHE HAS LOST CONTACT WITH HIM A COUPLE OF DAYS AGO....ELDERLY & MENTALLY DISABLED RESIDENTS....
## Posted at 17:10 in category /misc
[permalink]
[top]
Wed, 31 Aug 2005Pacific Northwest Software Quality Conference I've long had affection for PNSQC. It's a regional conference, but the only evidence of that is its size. The content is more like what you'd expect from a national conference. It's in Portland, Oregon, which is a little bit of a hotbed of Agile: Ward Cunningham, Jim Shore, Rebecca Wirfs-Brock, Steven Newton - all these people are Portland locals (though I suppose Ward may be completely gone now). Of the six keynote and invited speakers, four are pretty firmly associated with Agile: Mike Cohn, Esther Derby, Linda Rising, and me. They have a PDF brochure. October tenth through the twelfth.
## Posted at 16:39 in category /conferences
[permalink]
[top]
Sometimes when demoing Ruby, I get the reaction that runtime typing is too error-prone. I'm not alone in responding by saying that unit tests will catch the bugs a static typechecker would, plus others. So why use both? That's something of a flip response, and it's not really true. Here's an example I stumbled over while working on a chapter of Scripting for Testers. Here's code that sets a variable:
Here's one of the methods that consume it:
Here's how I called that method in a test:
The test passed. All the methods were tested, and all the tests passed. But the program failed:
The problem is that I unit-tested The root cause of the bug was my cretinous choice of a variable
name. I should not have named a variable expected to contain
a However, it seems to me that such errors will be caught if the whole-system tests exercise every call in the app. Suppose you're doing TDD starting from business-facing tests. Every call in the app would have to be traceable to a test whose failure motivated (perhaps very indirectly) that call, therefore every call in the app would be exercised by the complete suite (modulo some smallish background rate of human coding/design error), therefore there is no need for typechecking. But I'm perhaps being too flip. P.S. Reviewers of Scripting: the example has been slightly tweaked for this posting.
## Posted at 16:17 in category /agile
[permalink]
[top]
Tue, 30 Aug 2005The author of the configuration video I mentioned earlier writes:
It's for Windox and x86 Linux. What do people use on Macs? I was going to use Snapz Pro X and iMovie - but I'm completely ignorant.
## Posted at 06:36 in category /misc
[permalink]
[top]
I'm fond of this article (pdf), by Kevin Lawrence, about growing a test harness. I have worked with many testing common organizations where a common pattern is repeated over and over. It goes something like this - we realize there is more manual testing to do than time available, we decide to automate the testing, and we begin working on a test harness. Several weeks later, we have the start of a harness, but it's barely useful and we still have not written any tests. At this point, we're behind - so we abandon the harness and revert to manual testing.
## Posted at 06:23 in category /testing
[permalink]
[top]
Sun, 28 Aug 2005Via John D. Mitchell, an interesting article about a minimalist reaction to the tunnel vision rules promote:
Update: In response, Randy Mcdonald writes:
Having flown into the old Hong Kong airport, that strikes a chord with me. It occurs to me that I want to take the idea beyond safety. What I want to remember from the article is how physical space can be engineered to cause people to attend to what's easily ignored. What they might not see "in a state of nature" can be made visible. Ditto for those things that rules divert attention from (because following the rules is supposed to eliminate the need for attention). Consider our friend the big visible chart. They are supposed to fall in that middle ground - not rules, but still acting to nudge people. Sometimes they don't work. Why not? Ditto for standup meetings, bullpens, etc. How can they be better engineered?
## Posted at 08:55 in category /misc
[permalink]
[top]
Fri, 26 Aug 2005A program should be able to answer the two questions parents so often ask young children:
Logging is an important tool toward that end. I think it's underused and too often misused. I wrote some patterns for using logging for PLoP 2000 (pdf). Pretty mediocre. Who's written what I should have? The TextTest people advocate using logging to capture the expected results of a business-facing test. I like when idea working on ugly legacy code.
## Posted at 08:57 in category /coding
[permalink]
[top]
Wed, 24 Aug 2005Due to conversations with Jonathan Kohl and John Mitchell, a bit more on counterexamples. I now think that what I'm wondering about is team learning. I want to think more about two questions:
## Posted at 08:02 in category /ideas
[permalink]
[top]
In response to my note on Jim Shore's video, Chris McMahon points to HermesJMS, an open source tool for managing message queues. He says: Configuring any such tool is a chore, but the HermesJMS author has included video on how to configure all of the options of the tool: check out the "Demos" links from the left side of the home page for a really elegant use of video to explain complex activity in a sophisticated tool. I should also mention the video for Ruby on Rails. The speed with which things get done is much more apparent on video than it would be in text.
## Posted at 08:02 in category /misc
[permalink]
[top]
Mon, 22 Aug 2005
Or you may prefer to compete with me.
## Posted at 09:29 in category /conferences
[permalink]
[top]
Andy Schneider responded to my counterexamples post with the following. I think they're neat ideas.
(Reprinted with permission.)
## Posted at 08:47 in category /ideas
[permalink]
[top]
Sun, 21 Aug 2005At Agile2005, Josh Kerievsky gave an invited talk. He advocated using what I guess you could call computer-aided instruction. That was partly inspired by the amount of time his coaches spend re-covering old ground and partly by what he's seen at the North American Simulation and Gaming Conferences. (That conference has been on my list for years - because of Josh - but to my shame I've yet to go.) One of the things he pointed out is that instructional videos are now much much easier to create and distribute. In his talk, I resolved to produce one about using Fit in a test-first style. James Shore apparently also resolved to create one, and he did. It's a slide show explanation, rather than a demo, but I thought the use of animation got ideas across in a much tighter and memorable way than text+pictures could have. It's on NUnitAsp, in which I have absolutely no interest. But now I know something about it, and I'm glad.
## Posted at 10:06 in category /misc
[permalink]
[top]
Flow-style vs. declarative-style Fit fixtures Jim Shore has a note about the dangers of flow-style Fit fixtures (ActionFixture, DoFixture, etc.). One of the dangers has been known for a while in the pure testing world (Fit is not the first tool to use a tabular format for tests): it's that the temptation to add programming language constructs is strong, and the resulting programming languages are usually bad ones. But the more novel point is that flow-style fixtures divert attention from the essence of what is to be programmed (typically a business rule). By doing so, they stop team learning short. There's no question but that business experts like to think in flow style: do this, see that, do this, see that... However, the point of team communication is to build a group understanding of the domain, problem to be solved, and good solution. It is not to draw forth some existing solution buried in the business expert's head and shoot it across to the technical side. Building that group understanding means building a way of talking to each other that lets the group make progress. Just as programmers should not stop with their first design, but continue to work the code in response to stories, the team should not stop with the first way of notating tests. They should shape useful abstractions. To my mind, that's especially important because I believe that the story of a project should partly be a story of how the business expert came to understand more deeply the domain or what people need to do within it. A project in which that doesn't happen is a failure. Sticking with the first and easiest way of describing tests is a way to fail. I'm only a little bit bold in saying that skittishness about flow fixtures is an emerging consensus in the Fit world. Which is not to say that you should never use them. (And, if you do, you ought to be using the DoFixture.)
## Posted at 09:52 in category /fit
[permalink]
[top]
What with this whole test-first thing, some people's attention has drifted away from capture/replay GUI testing tools. I think that's good. But I was reminded today of an oldish article from Mark Silverstein on doing capture below the GUI (pdf). It relies on a clear separation between GUI and guts, with the GUI talking to the guts using the Command pattern. If you're going to do capture, that seems the way to do it, especially since it's yet another way to encourage layering. If - as is extremely likely - the resulting scripts will be read by humans, not just executed, it might also encourage good (business-facing) names for the guts API.
## Posted at 09:52 in category /testing
[permalink]
[top]
Mon, 08 Aug 2005In my thinking about tests as examples, I've been thinking of them as good examples: The right system behaves like this. And like this. And don't forget this. But what about counterexamples? A system that did this would be the wrong system. And so would a system that did this. There's some evidence that differences are important in understanding.
So what about those times when the programmer proudly calls the product owner over to show the newest screen and watches her face fall just before she says, "That's not really what I had in mind"? Or those times when a small group is talking about a story and a programmer pops up with an idea or a supposed consequence that's wrong? That's an opportunity to - briefly! - attend to what's different about the way two people are thinking. Does anyone make explicit use of counterexamples? How? What have you learned?
## Posted at 20:05 in category /ideas
[permalink]
[top]
Link: Crispin on test-first customer tests Lisa crispin has a nice, short article on how her team uses business-facing tests to drive development. A couple of points I particularly like:
## Posted at 11:07 in category /agile
[permalink]
[top]
Sun, 07 Aug 2005As of today, I've lost 20 pounds. (Naturally, I'm now heading off for New Hampshire, Land of the Giant Ice Cream Cone, for a week of vacation.) It seems to me I need to lose around 10 more pounds of fat and gain back at least 5 pounds of muscle to be in non-pathetic shape. Blogging my weight has definitely helped.
## Posted at 20:28 in category /misc
[permalink]
[top]
Somewhere around 1983, I took Ralph Johnson's very first course in object-oriented programming. That led to Ralph becoming my graduate advisor, which led to my being part of his reading group, which led to my reviewing some of Martin Fowler's books in draft, which led to Martin knowing me as a tester guy, which led to him getting me invited to a workshop in Utah, which meant I became an author of the Manifesto for Agile Development, which concentrated my attention on Agile, which is the reason I'm writing this sentence. It's not just me: even the most talented and virtuous of us need luck. The same is true of fields like Agile. Suppose Kent Beck hadn't met Ward Cunningham? Suppose they hadn't become Smalltalk programmers? (I've talked a little to Ward about Smalltalk's influence on Agile, and one of the things he said was, "Smalltalk people were more offended by software engineering than other people." So they did more about it.) What if Alistair Cockburn hadn't early on gotten the job of surveying projects within IBM to see what really worked? I don't know the whole story of refactoring, but would it have made the big time if Ralph Johnson hadn't been immersed in the Smalltalk world at the same time Bill Opdyke was looking for a dissertation topic? One of the things I've long taught testers is that they must work to get dumb luck on their side. When filling a database, it's better to make up new names than to reuse the same ones out of habit - even if what you're testing has nothing to do with name-handling code. The more variety in the names you use, the more likely you are to stumble over a name-handling bug. Moreover, all things being equal, one complicated test that incorporates five test ideas is better at accidentally finding bugs than five simple tests. (This is for after-the-fact testing, note, and all things aren't equal. You have to be aware of the tradeoffs.) There are a whole bunch of talented people out there poised to learn new Agile ideas and techniques. If we get luck on their side - our side - they'll learn and then teach us. If we don't, some of them will take their talents elsewhere. Others will learn, but what they've learned won't spread. The Gordon Pask award, I'm now realizing, was partly motivated by that. It's a way of shining a spotlight on people, of saying "Pay attention to these two." That will cause their ideas to spread faster. And, as a public and tangible acknowledgement of accomplishment, it will motivate them to work harder for us. It has its flaws, though:
I'm still happy about it, but I said we'd be improving it over the next year. What more should be done? (Thanks to Steve Freeman for conversation about this.)
## Posted at 17:55 in category /conferences
[permalink]
[top]
Sat, 06 Aug 2005(After a couple of days trying, off and on, to make a narrative of threats to Agile work, I give up. I also give up on the cybernetics tie-in. It gave me ideas, but I can't use it to express them. So it comes down to three solutions and their justifications. And every time I write about the last of them, I see it in a different way, so I'm going to cut my losses and put up the first two until I can say something coherent about the third.) What we need is...
## Posted at 12:56 in category /conferences
[permalink]
[top]
Wed, 03 Aug 2005Prelude to an explanation of a fear In my Agile2005 co-keynote, I talked about why I think Agile is akin to cybernetics, at least the British cybernetics of the late 40's and on. They share an emphasis on these things:
And then I said that's not what I wanted to talk about. What I wanted to talk about is the fact that cybernetics fizzled. If we share its approaches, might we also share its fatal flaws? More tomorrow.
## Posted at 16:34 in category /conferences
[permalink]
[top]
Sat, 30 Jul 2005One day before the start of Agile2005, the Agile Alliance board voted to create the Gordon Pask Award for Contributions to Agile Practice. Here's its description: The Gordon Pask Award recognizes people whose recent contributions to Agile Practice demonstrate, in the opinion of the Award Committee, their potential to become leaders of the field. The award comes with a check for US$5000 and some physical object inscribed with the recipient's name. We expect two recipients per year. The idea behind the award is that we in the Agile community need to do more to promote and encourage the rising stars of tomorrow. These are people who help other people: both indirectly, by producing tools or ideas other people use, and also through direct support of some Agile community. Rather than planning out the award, thinking through all the gotchas of deciding on recipients, and giving the first award in 2006, we decided to give the Award at the conference's closing banquest just five days later, trusting our membership to be tolerant of mistakes so long as they lead to improvement next year. The two recipients this year are:
The selection committee was Rachel Davies, Big Dave Thomas (a different person than Pragmatic Dave Thomas and Wendy's Dave Thomas), and me. We'll be evolving our notion of the prototypical recipient over the years. Putting nominations from the conference members into affinity clusters got us well started on that. But it was remarkably hard to narrow down to a cluster of two: there were six or seven obvious choices. (Next year, we'll be taking nominations from the entire Agile Alliance membership. And we'll start much sooner.) I'm really happy we did this. Oh - you wonder who Gordon Pask is? As constant readers know, I harp on the similarities between the attitudes and approaches that characterize Agile and those of the British cyberneticians of the last century. Of those people, Gordon Pask is perhaps the closest to us. Also, we needed a logo, some cybernetic device seemed appropriate (given how the idea tied into my keynote), and Pask's ear was the only one I had to hand. (It's the picture above.)
## Posted at 07:52 in category /conferences
[permalink]
[top]
Thu, 14 Jul 2005What I want to accomplish at Agile 2005
## Posted at 09:35 in category /conferences
[permalink]
[top]
Fri, 08 Jul 2005Mugridge and Cunningham's Fit for Developing Software is out now. If you're using or evaluating Fit, you ought to buy it. You can find my reasons here (pdf). There are sample chapters here.
## Posted at 17:25 in category /fit
[permalink]
[top]
Wed, 06 Jul 2005Breaking tests for understanding Roy Osherove has a post about breaking code to check test coverage. That reminded me of a trick I've used to counter a common fear: that changing something here will break something way over there. I started to proudly write up that trick. But the process of putting words down on pixels makes me think I was all wrong and that it's a bad idea. Read on to see how someone who's supposed to know what he's talking about goes astray. (Or maybe it's a good idea after all.) The picture is of a standard layered architecture. The green star at the top level is a desired user-visible change. Let's say that support for that change requires a change at the lower level - updating that cloud down at the bottom. But other code depends on that cloud. If the cloud changes, that other code might break. The thing I sometimes do is deliberately break the cloud, then run the tests for the topmost layer. Some of those tests will fail (as shown by the upper red polygon). That tells me which user-visible behaviors depend on the cloud. Now that I know what the cloud affects, I can think more effectively about how to change it. (This all assumes that the topmost tests are comprehensive enough.) I could run the tests at lower layers. For example, tests at the level of the lower red polygon enumerate for me how the lowest layer's interface depends on the cloud. But to be confident that I won't break something far away from the cloud, I have to know how upper layers depend on the lowest layer's to-be-changed behaviors. I'm hoping that running the upper layer tests is the easiest way to know that. But does this all stem from a sick need to get it right the first time? After all, I could just change the cloud to make the green star work, run all tests, then let any test failures tell me how to adjust the change. What I'm afraid of is that I'll have a lot of work to do and I won't be able to check in for ages because of all the failing tests. Why not just back the code out and start again, armed with knowledge from the real change rather than inference from a pretend one? Is that so bad? Maybe it's not so bad. Maybe it's an active good. It rubs my nose in the fact that the system is too hard to change. Maybe the tests take too long to run. Maybe there aren't enough lower-level tests. Maybe the system's structure obscures dependencies. Maybe I should fix the problems instead of inventing ways to step gingerly around them. I often tell clients something I got from The Machine that Changed the World: the Story of Lean Production. It's that a big original motivation behind Just In Time manufacturing was not to eliminate the undeniable cost of keeping stock on hand: it was to make the process fragile. If one step in the line is mismatched to another step, you either keep stock on hand to buffer the problem or you fix the problem. Before JIT, keeping stock was the easiest reaction. After JIT, you have no choice but to fix the underlying problem. So, by analogy, you should code like you know in your heart you should be able to. Those places you fall through the floor and plummet to your death are the places to improve. I guess not by you, in that case. By your heirs.
## Posted at 10:40 in category /coding
[permalink]
[top]
Test-driven Development and Beyond Dave Astels and I will be hosting a workshop at Agile 2005 titled Test-driven Development and Beyond. Test Driven Development is becoming a mainstream practice. However, it is a step along the way, not a final destination. This workshop will explore what the next steps and side paths are, such as Behavior Driven Development, Example Driven Development, Story-Test Driven Development. The idea is that we'll spend up to an hour having participants give brief pitches for what they think "lies beyond," then split into focus groups to discuss particular topics. The deliverable is a short paper outlining the various approaches discussed, together with people involved in each. You need not submit a position paper to attend. If you'd like to present your idea (briefly! which rules out fumbling with a projector), send us your topic. Thanks.
## Posted at 08:55 in category /misc
[permalink]
[top]
Mon, 04 Jul 2005I'll be leading two half-day hands-on sessions at the Amplifying Your Effectiveness conference (November 6-9, Phoenix Arizona, USA). The titles of my sessions bear witness to my belief that I'm no expert in my topics---but I do expect that collectively we can get somewhere good. An Amateur's Guide to Communicating RequirementsWe're all familiar with traditional requirements gathering: interview and observe a subset of users, then try to write clear, unambiguous, complete, and testable statements of their requirements. Many of us have tried hard to do that and failed. From that, some of us conclude that we should try harder and smarter. I conclude that the whole idea is broken. You not only can't write precise statements in here that represent the world out there, you can't even come close enough. In this session, I hope to convince you that my claim is at least plausible. The next question is: "And then what?" We'll start to explore ways of putting ourselves in situations where we can create better systems without being able to specify requirements. Topics
Since Plato, at least, we've been talking about creating mental models of the world. We usually think of them as like pictures, where everything you can point to in the picture matches something in the world. What if that kind of mental mode is mostly beside the point? Using exercises, we'll ask two questions: What if the power of a mental model isn't inherent in the model itself, but in the way you explain it to someone else? And what if model-building is powerful when it builds on our expertise, as social animals, at predicting what actions will make someone smile? This session is related to An Amateur's Guide to Communicating Requirements. It's not necessary to attend both sessions. Key points:
## Posted at 21:02 in category /misc
[permalink]
[top]
Thu, 30 Jun 2005A month ago, I made a consulting trip. I recommended that the client do the usual Agile thing: have shippable code with new features every few weeks, break each of those releases into stories with user-visible results, make the stories more granular than seems possible, make tasks within a story short with sharp end-points, etc. Yesterday, I asked how it was going. I got this in reply (reprinted with permission): I was actually really fortunate. Shortly after you were here, my wife's pregnancy came to full term. As such, I had to think of life in terms of 2-3 hour slices in case she called to tell me she was in labor. That made it much easier to have the discipline to break a project into smaller chunks. So here's my new Agile training regimen:
It's odd, with innovative ideas like this, that I don't get more business.
## Posted at 09:16 in category /agile
[permalink]
[top]
Wed, 29 Jun 2005As of Monday, Agile2005 had over 500 people registered. The hotel is full, and the conference may be capped at 600. If you're a wait-until-the-last-minute type, this may be the last minute.
## Posted at 09:56 in category /agile
[permalink]
[top]
Thu, 16 Jun 2005On the agile-testing list, we were discussing how reuse could work in an Agile project. How do you find code you can reuse? What prevents you from reinventing it? I rambled for a bit, then finished with this: As I paraphrased at my PhD prelim exam (to unimpressive effect), "Knowledge is of two kinds. You can know a thing, or you can know where to find it." (Samuel Johnson) In a system that's constantly migrating toward a good structure, the problem of knowing where to look it up is simpler than in the typical big ball of mud system. You can look in the place it ought to be. If it's not there, there's a reasonable chance it's not anywhere. To this, Kevin Lawrence gave this wonderful advice about what to do after you don't find the code and start writing it yourself: Put it where you looked. He gives the C2 wiki as the source, but I can't find it there.
## Posted at 17:16 in category /coding
[permalink]
[top]
Wed, 15 Jun 2005User modeling in exploratory testing Jonathan Kohl has an illuminating story about how he used an informal, observation-based user model to repeat a previously unrepeatable bug.
## Posted at 08:59 in category /testing
[permalink]
[top]
Sat, 11 Jun 2005Reviewers needed for Scripting for Testers I have four chapters of Scripting for Testers almost ready for review. Right now, I'm mainly looking for people who don't know any programming language or people who have a passing knowledge of some scripting language (such as the ones GUI testing tools use). I want to see if the tone and level are right. If interested, send me mail.
## Posted at 15:19 in category /testing
[permalink]
[top]
Wed, 08 Jun 2005A certain sense of balance (links)
Some time ago, I wrote a post
about adding an Richard P. Gabriel passed along a piece he wrote on the Y combinator. Like the one I linked to, it uses factorial. Quite interesting to compare and contrast the two explanations.
## Posted at 08:16 in category /misc
[permalink]
[top]
Tue, 07 Jun 2005I'm dialing down my work on Better Software magazine to one article an issue. I'll concentrate on helping early-adopter authors bring now-safe techniques to the early mainstream. Not entirely coincidentally, these are the articles that I pull out of my back pocket for clients. "You need an X, and here's an article about it." Here are some examples:
There are other examples, but those are ones that came to mind both because of recent experience and because I didn't have to search for links. In upcoming issues, I'll have articles on using examples (Fit tests) for specification, what it's like to be an XP customer, and building a strangler application. If you have ideas for an article that matches this theme, send me a proposal. Forgive tardy replies: I'm digging myself out of a pile of urgency.
## Posted at 09:10 in category /misc
[permalink]
[top]
Mon, 06 Jun 2005Eric Jarvi writes a post on threat trees in response to my post on fine-grained guidance in exploratory testing. It reminded me of a short paper by Cem Kaner that I've always liked: Negotiating Testing Resources: a Collaborative Approach. Should be appealing to the big visible charts crowd. I recommend both links to your attention.
## Posted at 11:57 in category /testing
[permalink]
[top]
Form, content, and the structure of relationships From an op-ed piece by Stanley Fish:
(Hat tip to rpg for the link.) One of my pet obsessions these days is learning and teaching two guidelines of well-factored code:
Now, I'm certainly a fan of tacit understanding of what's inadequately captured by rules, so I don't believe that the two guidelines above can be completely captured by some syntax governing relationships, any more than I believe everything that natural language does is a matter of syntax. But if a knowledge of syntactic rules can help English writers, I expect a syntax of relationships (not the BNF of the language) could help Java writers. I'm aware that I'm boldly heading to the 50's and structuralism, at least two intellectual fads ago. What of it?
## Posted at 08:51 in category /misc
[permalink]
[top]
Fri, 03 Jun 2005Anniversary: Next year will be the 30th anniversary of the first time I sent email. As my anniversary gift, I would like a spammer ground up and used to seed 1700 pearl oysters (1700 being the approximate number of messages in my Junk mailbox last time I emptied it). If possible, make it the "Greets! I offer you full base of accounts with passwords..." guy. How Agile will destroy open source: I wanted to talk about Gold Cards in a consulting report, so I went to the original paper: "Innovation and Sustainability with Gold Cards"(Higman, Mackinnon, Moore, and Pierce). There I read: It's good for [a programmer's] skills to be able to practice new techniques [...] Some of us tried to work on this stuff after working hours, however a full day of guilt-free paired programming is extremely tiring. Where does open source software come from? From programmers who are frustrated that their day job doesn't involve very much, you know, programming. So they do it for free at night. And when the evening finds them sated...?
## Posted at 15:46 in category /junk
[permalink]
[top]
Sun, 15 May 2005I've been working on the chapter in Scripting for Testers where readers start defining classes. As the story behind the following text begins, I have to figure out how to make a failing test pass.
Then there's text on how to make that work. I'm teaching an old idea: replace explicit runtime decisions with appropriate setup. Just after writing that, I flashed on something that Gary Klein writes in Sources of Power. His research group was preparing to interview expert firefighters about their decision-making.
What makes someone an expert is the ability to act appropriately without resorting to conventional rational thought, except perhaps for after-the-fact explanations. (And as both Sources of Power and oodles of old work in expert systems show, experts often find it difficult or impossible to explain the reasons behind their actions, even to themselves.) If the parallel isn't completely bogus, expert code will have
few
## Posted at 16:14 in category /coding
[permalink]
[top]
Wed, 11 May 2005Some recent and pending encounters with legacy code have made me think there may be three different broad approaches.
As the last parenthetical remark suggests, these approaches shade into one another. Nevertheless, they seem to me three distinguishable stances toward legacy code. My question is: how do you decide which stance to take? In the 60's, renowned software engineer Rocket J. Squirrel drew on his extensive experience to make the definitive comment on Rewrite and Throw Away: "That trick never works!". Which isn't invariably true, of course, but it's a risky strategy. The other two methods can still deliver a steady stream of features to the business, albeit at a slower rate (in the short term). In this one, the team vanishes from view of the business, doing who knows what, promising great things for the future. That's an unstable situation, because the business is liable to get fed up and start insisting on features ASAP. It's also a dangerous situation for the programmers. Because they have to finish everything before anything works, they might not know they're way off course until far too late. Still, Rewrite and Throw Away is easier than refactoring into submission. When faced by a tangled mass of code, it's hard to know where to start. And, in my (lack of) experience, you're much more likely to have a refactoring that flames out and has to be rolled back, just because of some complex interconnectedness you didn't grasp at first. Until you've learned-through-doing, it's frustrating, and frustration leads to short-cuts (which is how you got the legacy code in the first place, probably). Strangling the application has the advantage that you've consciously decided you shan't fix the old code, so the dangers of touching it are (somewhat) lessened. It also has the advantage that you can quickly create a concrete architecture (a set of layered subsystems, say) to guide your forward movement. (This insight is due to Michael Thomas, who's writing me an article on strangling code.) I don't have the experience to speak to Strangling's disadvantages (except that I can imagine long debates about the concrete architecture preventing people from getting moving). I have this idea that there must be a set of patterns or lore that would help people navigate among those choices. Who will write it down?
## Posted at 09:14 in category /coding
[permalink]
[top]
Tue, 10 May 2005Fine-grained guidance in exploratory testing I'm going to be hosting a couple of sessions at the AYE conference. I was tailoring my standard biographical blurb for it when a phrase leapt out at me: [My] approach is evolving. Today, [I] emphasize [...] exploiting the similarities between exploratory testing and incremental design [...] A lot of what I've been talking about is bringing the tools, attitudes, and biases of exploratory testing to bear on program and product design. But what about the reverse direction? Consider: I make frequent use of a quote from Ron Jeffries:
As I've since learned (and sometimes documented), such heuristics - interpreted with imagination and guided by analogies to past experience - really have a wonderful way of guiding the performance of design. They make it less likely that you'll go off into the weeds. What fine-grained guiding heuristics are there for exploratory testing? I confess that I can't think of any. That alone doesn't mean much, since I don't claim to be a particularly good exploratory tester. But I also can't think of anything written that quite gets at what I'm looking for. Bach&Bach's session-based test management is something like it, since the short sessions force a pause for course correction. Bach, Kaner, and Bolton have written well on using risk to guide testing and on particular heuristics to use when strategizing where to test next. Elisabeth Hendrickson has some techniques particularly good at breaking people out of mental ruts. But somehow, and it might just be me, these things seem on a larger scale than "eliminate duplication." While coding, I can use that heuristic to choose the very next thing I do, the next keyboard gesture I make. After a time, it becomes a perceptual thing as much as a cognitive one. (I think it's no accident that the phrase "code smells" is so popular. It helps toward the useful goal of removing right action from the realm of conscious decision to the realm of instant expert action.) I wonder what the equivalent in exploratory testing is, and has anyone written it down? P.S. I learned about the book Sources of Power (the previous link goes to a review of it) from Rachel Davies. P.P.S. Blogging is light because writing energy is going into Scripting for Testers. Today: Test::Unit.
## Posted at 09:28 in category /testing
[permalink]
[top]
Tue, 19 Apr 2005IRS Form QF
## Posted at 05:00 in category /misc
[permalink]
[top]
Fri, 15 Apr 2005Not exactly, but two species of octopus walk - nay, scurry - on two legs. Video here.
## Posted at 10:53 in category /misc
[permalink]
[top]
Design-Driven Test-Driven Design (Part 4) For background, see the table of contents in the right sidebar. The story so far: I got a Fit test describing a user workflow through a medical records system. I made part of that workflow work using a Model View Presenter style and Mock Views. I'm now ready to start building the real views that will talk to the Macintosh's GUI framework. Here's my normal practice when driving coding with Fit business-facing examples: I constantly want to make the next cell of the Fit table green. When I know that will take too long for comfort, I divide-and-conquer the problem by breaking the interval into shorter ones punctuated by xUnit green bars. There are some disadvantages to treating xUnit tests as secondary to business-facing tests, but that's the way I do it. For this task, I'm doing something similar. In the previous episode, I got to a green Fit cell, creating two Presenter objects, two Mock Views, and two abstract View classes along the way. Now I'm going to flesh out the meaning of statements like "choosing Betsy with owner Rankin". The interaction designer's wireframe sketch shows that done through a list. But when I make that list, a host of questions pop up, like "When you add a new case, is it automatically selected in the list?" Talking about properties of particular UI elements seemed like a job for unit-size tests. It was also painfully obvious that I needed more UI. There's a place in the wireframe to select a case, but no place to add one. For the sake of expediency, I hung that UI off the side of what I was given, well aware that I'll probably change it later. Because I've never programmed to this Macintosh UI framework, I made a simplified UI for my first leap into the unknown. The end result looked like the picture on the right. I now worked through the Fit workflow, adding Macintosh detail to each step. At first, I began each step with a spike so I could find out what kind of messages flow from the UI to my Views. (Yes, I could have read all the documentation - think of the spike as guiding me through the reference manuals.) For my UI's Views to be really thin, there has to be a one-to-one correspondence between messages from the UI and the messages flowing to the Presenter. For example, here's what happens when a user presses TAB or ENTER in a text field: public void animalNameEntered(Object sender) { /* IBAction */ myPresenter().animalNameEntered(animalNameField.stringValue()); } As I learned more, I got bolder about unit-testing behavior into existence with a Mock View and only then making that behavior work with the real View. Sometimes I regretted that, discovering that my assumption about what the UI must do was wrong. It was a little harder than usual to muster enthusiasm for the junit tests. For example, when I wanted to make the Presenter send a "highlight row 0" message to the table, I wrote a test that had the Presenter send that message to the Mock View and then make checks like these: assertTrue(inpatientView().wasARowHighlighted()); assertEquals(0, inpatientView().getHighlightedRowIndex()); ... and then I had to go make the Mock View remember the message was called so that my test could ask about it. Seems like a lot of work to drive one silly message from the View to the UI. (Perhaps a mock-builder would help?) This bothers me because I have a principle that if programmers are finding testing annoying, that's a problem to fix. One way to fix it is to make the work provide value to new people. Consider: I was working on the code that handles entering a patient name, entering an owner name, and clicking the "add case" button. At that point in implementation, it was natural for me to ask an imaginary UI designer about error cases. What should happen if you hit the button before typing in an animal name? What happens if you hit the button twice? Etc. "We" decided not to code up some of the error cases right away. But some we did. Suppose my designer had said that pressing the Add Case button without both fields filled in should produce an error. Here's a table that might record our conversation:
The reason I like this is the reason I like being systematic. When you're constructing unit tests one at a time, it's easy to overlook a situation like both fields being empty. Suppose I'd only thought of the first three tests, in that order. My checking code would almost certainly first check for an empty owner name. So the behavior for that situation would also be the behavior for the situation where neither name was given. That's actually bad. Because the owner entry field follows the animal entry field, there's a fair chance the user would respond to the error by entering the owner name, hitting Enter, then getting annoyed by another error message. It's better for her to be directed to the first field in the tab order. That particular example isn't a big deal, but sometimes the case you overlook is a very big deal indeed. By making a quick table, I not only increase the chance of thinking of all important cases, I also reduce the chance of overlooking a kind of result (like what gets highlighted). Now, as it happens, my imaginary designer chose a different way to solve the problem. The Add Case button should be greyed out until both names are available. That behavior was driven by unit tests like these: public void testCreationRequiresBothNames() { assertEquals(disallowed, inpatientView().getAddCaseCommands()); inpatientView().animalNameEntered("animal data"); assertEquals(disallowed, inpatientView().getAddCaseCommands()); inpatientView().ownerNameEntered("owner data"); assertEquals(nowAllowed, inpatientView().getAddCaseCommands()); } public void testEnteringCaseErasesPreviousNames() { inpatientView().ownerNameEntered("owner"); inpatientView().animalNameEntered("animal"); inpatientView().addCasePressed(); assertEquals(disallowedAgain, inpatientView().getAddCaseCommands()); assertTrue(inpatientPresenter().hasNoAnimalName()); assertTrue(inpatientPresenter().hasNoOwnerName()); assertTrue(inpatientView().wasTheAnimalFieldNameEmptied()); assertTrue(inpatientView().wasTheOwnerNameFieldEmptied()); } So. I didn't think of making that table; I wrote jUnit tests instead. I'm tempted to keep coding. But the point of this exercise is not to produce a program, it's to learn stuff. So what I'll do is back up, write some Fit tests, and ask myself questions like these:
(Note that throughout I'm assuming the hypothetical Good Fit Editor, one that makes creating and modifying tables as easy as creating and modifying a small RTF document with your editor of choice. We need a Good Fit Editor!) As usual, you can find the current code in zip file. There are two separate projects - the core code and the Cocoa interface. I'd rather they were all in one directory structure, but I couldn't get IDEA and Xcode/IB to play nice together.
## Posted at 10:42 in category /fit
[permalink]
[top]
Tue, 12 Apr 2005Usability errors in medical interfaces Jakob Nielsen points to an interesting study on life-threatening errors induced by poor user interfaces. I can well believe it. Unless things have changed in the past ten years, my wife (the veterinarian) has to deal with drugs whose standard doses are given in one of three units of measure. And yes, she's stopped students from giving animals huge overdoses due to conversion errors.
## Posted at 08:06 in category /misc
[permalink]
[top]
Wed, 06 Apr 2005Introducing Agile to a legacy project I was talking with a potential client about what I might do for them. Suddenly I realized I'd had this conversation before. So I decided to write down my talking points. I'm almost always contacted about testing in an Agile project. My biases about that are described in "A Roadmap for Testing on an Agile Project". A problem with that roadmap is that it really assumes either a greenfield project or an Agile project that's well underway. But some people I talk to are just starting with Agile, working on a legacy code base that really needs cleaning up, and don't have much in the way of testing. That makes that roadmap less applicable. My talking points follow. Notice how few of them are about testing. When I first started consulting with Agile projects, I tried - well, some - to stick to my testing knitting. But either it made no sense to wall off testing from other concerns or the existing wall was clearly a problem. So now I stick my nose into all sorts of business.
That's all I can think of now. What else?
## Posted at 21:01 in category /agile
[permalink]
[top]
array[array.size], (car nil), and a certain sense of balance
Last night, I was disappointed by a bug. It was in some Python code
I was writing for the Agile Alliance web site. In Python, indexing
one past the end of the array throws an error. In Ruby, it
returns
To fix the problem, I added an
Perhaps so. But I was at that moment reminded of a wonderful
email. I think it was from George Carrette to some Common Lisp
mailing list, circa 1984. He wrote of a dream in which he was
inspired to eschew all the hackish shortcuts of regular Lisp and
translate a program into Scheme. First he stopped taking advantage
of the way traditional Lisp lets you ask for the first element of an
empty list (that is, As he went on, the code kept getting bigger and not so nice, but he maintained the pretense of being an enthusiastic convert to logical purity. It was a tour de force of sarcasm, I thought, and I'd love to get a copy if anyone saved it. That makes him seem just snarky, but a Google search shows Carrette also involved as a contributor to the Scheme intellectual family tree. The Great Lispers of the Past had that ability to flip rapidly between the ideal and the practical: understanding the power that comes from conceptual simplicity and uniformity, but also realizing that there are non-logical special cases with pragmatic value. Able to be at the most ethereal levels (the Y combinator) at one moment, in amongst PDP-10 assembly code the next. It's a balance I'd like to have.
(See also the Null
Object pattern. How often do null objects actually make sense
when you think about them, and how often are they just ways to
remove
## Posted at 07:20 in category /misc
[permalink]
[top]
Sat, 02 Apr 2005A Big Visible Chart for a big visible belly In my mid twenties, I weighed about 190 pounds. Then I had an early midlife crisis and got into shape, using the novel method of eating less and exercising more. Now, twenty years on, what with kids, age, some chronic injuries, and resurgent gluttony, I'm back at the start. I've resolved that this shall not stand, but the past few months have shown that I need some extra oomph behind the project. What do Agile teams do when they need some constant added pressure to do as they know they need to do? They make the important facts widely visible. So I will do the same. In the header of this blog, I'll post a running record of what the scale shows for me + hiking boots (to ease achilles tendonitis when stair-climbing). This blog gets around 120,000 hits per month. Even though the vast majority don't have an actual human behind them, there are enough that my pride will not let me fail. Twenty years ago, losing two pounds a week was comfortable, so that shall be my progress goal. My lowest weight was 157, but I had absurdly low body fat. This time I'll shoot for 167.
## Posted at 19:30 in category /misc
[permalink]
[top]
Is it possible to get to a place where you can comfortably use Cocoa and Java, or is the path always full of rocks? <boring_tale_of_woe>I am finding plugging a Mac interface on my Jar file no fun. I am distressed that too often building produces mysterious behavior that goes away when I hit 'clean all' first. It's bizarrely cumbersome to include a jar file in the project. The link between the Nib and whatever other magic is involved in launching got so scrozzled that even backing up all the way to the Nib and regenerating all the Java sources yielded an executable that couldn't find the java UI objects. I had to start completely from scratch, redraw the UI, generate the Java sources, and paste in the code from the previous version.</boring_tale_of_woe> Interface Builder is cool, but once past that things go downhill. I'm particularly wondering if the whole system is fragile in the face of lots of renaming of methods and redrawing of interfaces. <boring_tale_of_woe>For example, the runtime once unilaterally ceased being able to find the action method
## Posted at 19:30 in category /mac
[permalink]
[top]
Wed, 30 Mar 2005Design-Driven Test-Driven Design (Part 3) For background, see the table of contents in the right sidebar. The story so far: the way methods have clustered in a Fit DoFixture has persuaded me that I need to make some new classes. Heaven help me, the image that comes to mind is viral particles budding off a cell. (The image on the right shows flu viruses.) I also know that I want to move toward the Model View Presenter pattern, because it should let me get most of the UI code safely under test. And I'm driving my work using scripts / tests of the sort a User Experience (UX) designer might write.
The first time I worked through this script, I created a single
class per method-cluster. For the methods that referred to the
"patient detail interaction context", I created a
PatientDetailContext class. The fixture would send it commands
like The problem was that no test ever drove me to split that one class into the View and Presenter classes. If you think about it, that makes sense. In order to preserve design flexibility and keep detail from obscuring the essence, the test script I'm working from is deliberately vague about the details of the user interface. Since Model-View-Presenter calls for the View to do little more than relay low-level GUI messages over to the Presenter, the programmatic interface between the two (which I think of as like the mitotic spindle in cell division - what's with me today?) has to name a bunch of detail that the script leaves out. Where can that detail come from? I think it has to come from my knowledge of my end goal. So in this do-over, I'll start by assuming such low-level messages. But rather than jump into two classes right away, I'll start by budding out the Presenter and have the DoFixture act as the View (the self-shunt pattern). Let's take two steps in the script to work from:
Here would be the object structure and pattern of communication for the first line:
A portion of the DoFixture acts as a kind of mock View for the Inpatient
Presenter, pretending to respond to user actions. Its implementation
of
Those look rather like UI messages. The Inpatient Presenter knows
that when "Choose Patient" is clicked, it should tell the Patient
Detail Presenter about it. The Patient Detail Presenter in turn has
to update its View. Its View is, again, the DoFixture. So the Presenter calls a
new method on the DoFixture,
Now when the next test line claims that "now the patient detail context names Betsy", Fit calls a query method that returns the right result:
That works (given the right code in the presenters). Having gotten green, I can now refactor. There are two uglinesses in this code.
By an amazing stroke of luck, I can now extract the View-ish methods into full-fledged mock View objects that implement my new interface. They will:
Like this:
I won't show the code itself, but you can find it in a
zip
file. As before, the We've now achieved the View/Presenter separation. The mock Views do conversions. The "from" part of the conversion comes from the Fit tests, but where does the "to" part of the conversion come from? What tests directly drive the the decision about what messages to send from Views to Presenters? Well, what always drives the coding of classes distant from the "top" of the system? - unit tests. That's kind of an interesting inversion. Usually, we think of the code that handles UI widgets as being on the outside of the system, the part closest to the user. But here that code is utility code, not really different from database access code. By burying utility code behind a layer (be it a persistence layer or a DoFixture derived from an interaction design), we let people thinking about larger issues ignore the grotty technology that lies behind the business value of the system. Next: interlacing Views and mock Views. Plus, I finally get around to learning to program Cocoa.
## Posted at 08:21 in category /fit
[permalink]
[top]
Tue, 29 Mar 2005Via the Good Experience newsletter, I got a pointer to pranksters Improv Everywhere. Improv Everywhere causes scenes of chaos and joy in public places [...] Improv Everywhere is, at its core, about having fun. We're big believers in "organized fun". In the process we bring excitement to otherwise unexciting locales and give strangers a story they can tell for the rest of their lives. We're out to prove that a prank doesn't have to involve humiliation or embarrassment; it can simply be about making someone smile. I like this one best so far.
## Posted at 21:11 in category /misc
[permalink]
[top]
Sat, 26 Mar 2005Design-Driven Test-Driven Design (Part 2)
For background,
see
the first installment When working on a Fit test in the "flow" style (step-by-step tests), it's my custom to start by creating empty methods for each of the steps in the test. I do that because I usually find something I don't like about the test, and I'd rather discover that early. Here's the resulting Fit output:
As I was writing the Java code for this most rudimentary DoFixture, I noticed that the methods fell into groups. In what follows, I've separated those groups with rules.
Except for the first one, the different groups talk about different interaction contexts. I could add comments to explain that, like this:
But that would be wrong. To my mind, all the groups but one are crying out to be extracted into classes. Those classes sure look like they'll become the Presenter objects that are going to implement our interaction contexts. I'll extract them next time.
In the meantime, I've packaged up everything in a
zip
file. Feel free to fiddle. There's an ant build file in the
top-level directory. The default target compiles any changed files,
runs junit, then runs Fit. (I like to run junit before Fit, figuring
that there's no point in running Fit if any junit tests are
failing.) All the jar files you need should be in
the
The test results for each HTML file in
the
## Posted at 16:54 in category /fit
[permalink]
[top]
Ever since I read the "lambda the ultimate" papers back in my Lisp days, I've been awed by Guy Steele. So I read this with interest:
I was pleased to read that because one of my habits is to take any state diagram I get and turn it into a state table. The state table contains a square for every event in every state. It forces you to question what really happens in that case. (And you should be careful not to leap to the conclusion that "it's impossible".) State diagrams, in contrast, make it easier not to think about a case - a missing arc is much less visible than an empty cell. Such trudging-through-gruntwork is characteristic of testers, but it needn't be isolated to them. It should be a property of the team. I post the above quote to make it more glamourous. Of interest to those who promote the idea that programmers should practice, as musicians do, is this:
A final note: he has a huge shower, in which he spends about twelve hours a day. I don't absolutely know that, but I deduce it from the time I heard him say he only gets good ideas in the shower.
## Posted at 12:28 in category /testing
[permalink]
[top]
Thu, 17 Mar 2005Design-Driven Test-Driven Design (Part 1) At the Canadian Agile Network workshop earlier this week, Jeff Patton had what we think could be a great idea:
To illustrate, I'm going to walk through a user experience (UX) design from the beginning, through workflow design, into a Fit representation of a workflow, finishing off with test-driven design using Fit and JUnit. This recapitulates and extends what Jeff and I did during an action-packed 26 hours in Calgary. We pretended we were constructing a medical records system for my wife (something close to her heart right now). We went through Jeff's normal UX process. He was the UX designer; I filled in for Dawn and the other users. First, we talked about system goals, together with measurements. There were two goals:
We talked about where the software would be used, its usage context. One place is pretty typical: a reception office where secretaries meet clients. The other isn't: the patient ward. Since this is a ward for large animals, it's rather noisy, messy in spots, and has limited computer access. We developed personae representing four kinds of users. Dawn is a representative clinician (teaching professor), Jamie is a representative caregiver (who can be either a clinician or a medical student), Hazel is a secretary who handles the creation of records and things to do with money, and Bill is a record keeper who tries to respond to data requests in the face of caregivers who are, in his view, insufficiently appreciative of order. These personae would be turned into big pictures on the wall of the project bullpen. Acting as Big Visible Charts, they'd constantly remind the team of who they were building the system for. When the team had underconstrained decisions to make about the user experience (which will always happen), the posters would help them make decisions the users would like. In the absence of a reminder, people tend to make decisions that they themselves would like. Trust me when I say that veterinarians are different from programmers. I then brainstormed a list of tasks that the different kinds of users have. I wrote them on cards. Jeff asked me to arrange the cards so that tasks done by similar people at similar times are close to each other (an affinity diagram). You can see from the picture that we picked only a small subset of the tasks that would be supported by a real medical records system. Each cluster of cards can represent a "place" in the software that people visit to do a set of related tasks. In the jargon, such places are interaction contexts. From the set of places, you can create a navigation map that shows how people get from place to place and a wireframe diagram of a place's visual appearance. Jeff's wireframe is patterned after a typical email client. The top pane contains a list of cases (like a list of email senders & subjects). Click on a case, and the bottom pane fills up with information about it. The bottom pane has tabs because there are three kinds of information caregivers will want to look at. Sometimes they'll be filling in that morning's SOAPs (subjective [observations], objective [observations], assessment, and plan), sometimes making notes throughout the day about observations made or orders given or orders filled, sometimes digging into a case's history. I then wrote an example of how a caregiver would use that interaction context. The tricky thing was to write it so that it supported navigation and key tasks while remaining resistant to changes in the wireframe. The script below will be easier to follow, probably, if you substitute "pane" for "context". I used bolding to highlight changes in contexts and italics to draw attention to what happens after a user action.
That's both an natural-language description that a veterinarian can follow (I just checked) and a DoFixture script that a programmer can implement. The next installment will talk about how.
## Posted at 19:33 in category /fit
[permalink]
[top]
Mon, 07 Mar 2005That pernicious sense of completeness Here's a mistake that seems easy to make.
It's that last step that seems to me a mistake, in two ways.
For more on this way of thinking, see my "When should a test be automated?" (pdf). Some of the assumptions are dated, but I'm still fond of the chain of reasoning. It can be applied to more modern assumptions.
## Posted at 07:22 in category /testing
[permalink]
[top]
Thu, 03 Mar 2005Because of my writing and consulting load, I'm going to scale back on my editing for Better Software magazine. As soon as possible, I'll be working on one article per issue. In the past, I've been more or less guided by an editorial calendar, looking for articles on certain topics. In the future, I'll be looking for articles on any relevant topic (but keeping in mind the need to have balance over an entire year). What I'm looking to help produce is a steady stream of the kind of articles I keep telling clients they should read. Those usually fall into two categories:
So if you have an idea for an article, contact me. Articles can be of two lengths. Feature articles are 2500-3000 words (which is too short to treat anything but the narrowest topic in depth). Front Line articles are 1200-1500 words. They tell a story of something you did that you learned from. They'll typically start with the story, tell the specific lesson, and maybe generalize out from there.
## Posted at 21:13 in category /misc
[permalink]
[top]
Ten most influential computer books of the past ten years I was asked to make a list of the above. My first reaction was "How should I know?" But then I figured I could at least list books that I believe have been influential in my circles. Here they are.
(I distrust lists with ten items. I always suspect the author squeezed something out, or strained to come up with a last item, just to hit that magic number. By coincidence, I really listed ten, first try.)
## Posted at 20:07 in category /misc
[permalink]
[top]
Jim Shore has some thoughts about my earlier posting on Fit style. I'm intrigued by the idea of using, uh, relational verbs like "is" and "has" to make Fit statements look more like they're for understanding than for testing.
## Posted at 20:03 in category /fit
[permalink]
[top]
Fri, 25 Feb 2005Requirements documents or specifications explain how a program is supposed to behave for all possible inputs. Automated tests explain how a program is supposed to behave for certain possible inputs. The understanding gained by reading tests duplicates some of the understanding gained by reading documents. Duplication is (often) bad. One of my goals is to find out how to write and annotate tests so that the redundant parts of those other documents can be eliminated. Fit has potential for that because the test tables can be embedded in whatever HTML you like. Rick Mugridge's Fit Library increases that potential by providing an improved set of default tables. But we still have to realize that potential by using them well. I've been exploring how. Here's an example, patterned after a table I recently wrote for a client. I have some comments about the style after the table. A person reading this page would come to it knowing some context. She would know that things called "nodes" are arranged hierarchically. (In the original table, what I'm calling "nodes" were something less abstract.) She would know that nodes are sometimes visible, sometimes invisible.
## Posted at 15:31 in category /fit
[permalink]
[top]
Tue, 22 Feb 2005A clever story about achieving metrics nirvana from Kevin Lawrence.
## Posted at 12:56 in category /misc
[permalink]
[top]
In exploratory testing, you need a way to kick yourself out of your rut, your habitual way of thinking about the software. One of the ways Elisabeth Hendrickson does that is to use lists of adjectives and adverbs, chosen randomly or no, to prompt new ideas. She's got a short writeup here, together with a phrase generator. My overeducated alter ego can't help pointing out the similarity between what Elisabeth does and the written version of the Surrealist game called "exquisite corpse".
## Posted at 07:17 in category /testing
[permalink]
[top]
Mon, 21 Feb 2005Sometimes you just gotta say people are more attractive in the abstract than in reality. The Constant Reader will have seen my earlier rant about how some spyware producer has chosen to take over machines and direct them to testing.com. Since putting up the note on my front page and resume page, the emails have slowed down to somewhere around four a day, but the remainder are largely of a strikingly aggressive stupidity, such as this gem from "mp3pirate": Get off my Mother-Blankin Machine You Bl Ank Licking Blank........... I can't help but think:
I dutifully reply with a little note reiterating what's on my site and ask if they saw it there (if not, I want to put it where they would see it). Not one has replied. Heirs to the legacy of the Enlightenment. Bah!
## Posted at 13:37 in category /junk
[permalink]
[top]
[Update: two more good links] I'm writing a report for a client, and I mention variant burndown charts. I want to put all my links in one place.
## Posted at 08:58 in category /agile
[permalink]
[top]
Wed, 16 Feb 2005Prodded by Bret Pettichord, I've finally committed to writing Scripting for Testers. The manuscript is due by the end of the year, to be published in Dave Thomas and Andy Hunt's Pragmatic Bookshelf. Here's a version of the plan I sent to Dave, followed by a request for help.
So the request for help: what do you think of that? What kinds of tasks should be covered? What tools should I talk about? Mail me.
## Posted at 07:24 in category /testing
[permalink]
[top]
Tue, 15 Feb 2005I'm writing a report for a client, and I mention variant burndown charts. I want to put all my links in one place.
## Posted at 11:07 in category /agile
[permalink]
[top]
Fri, 11 Feb 2005This week I traveled to a client who was using FitNesse, the Wiki-enabled version of Fit. They were using ActionFicture, which I've never been fond of. Earlier I'd replaced it with my own StepFixture, but I knew Rick Mugridge had a new type of fixture called the DoFixture, so I prevailed upon him to let me take a copy with me. I'm in the first flush of enthusiasm, but I think it's a big step beyond StepFixture and similar fixtures. When I read about it, I thought it was an improvement, but I didn't appreciate how well it suits my goals for acceptance tests. Here's an example:
I strongly prefer Fit tests to be business-facing, written in the language of the business instead of the language of the implementation. Because the rows can be read as sentences, there's less of a translation gap between what a product owner says about the desired product and the way the tests are written. That seems to help keep them business-facing. Moreover, it may be easier to envision a succession of tests as a progressive explanation. If reading the tests is supposed to help you understand a feature, the tests should start with the simple cases and build up progressively to the complicated ones. There's a tendency in test writing to set up an enormously complicated state once, then execute a series of actions and checks. I think that's bad for two reasons. One is that the test becomes hard to understand. The other is that it gives the programmer no obvious place to grab hold and get started. With a series of progressive tests, the programmer, product owner, and tester can devise a few simple cases right away. Then the programmer can launch off into coding while the product owner and tester mull over the more complicated cases. The programmer doesn't face the choice between coding without a concrete goal or waiting around for something to do. Another nice feature of the DoFixture is the way it wraps other fixtures. Before explaining that, here's how a DoFixture would handle the above table. The table translates into calls to these two methods on the DoFixture:
void chargeDollarsAgainstAccount(int dollars, String account)
The DoFixture doesn't care much about table boundaries. It can run any number of tables in succession. But when it encounters the first row of a table, it does a special check. If the row begins with a fixture name, it handles it in the regular Fit style. But if it's a method that returns a fixture instance, the DoFixture recursively uses that instance to process the table, returning to the DoFixture after the table's done. One practical result of that is that a table that once looked like this:
... can now have a first row with the same effect but a different style:
That doesn't seem like such a big deal, but the difference
betweeen a DoFixture style page and a standard Fit page is that
there's only one mysterious technology-facing row that says
something
like The DoFixture isn't in general release yet, I don't think, but it should be soon. Watch for it. Thanks, Rick. P.S. There's one thing that I think Fit still needs to convert it from a tool for the test-infected visionary to a mainstream tool, and that's a Fit-specific editor. For example, if I were in "row-fixture mode", I'd want to type the above table like this: [command to start a row fixture]
The table would grow itself around the words I'm typing instead
of my having to create it first. That would allow me to type the
table quickly, instead of boring the product owner while I fiddle
with table formatting. And the editor would take care of italicizing
the keywords. (Although that's not required, I think it helps.) It
might also touch up the table with the
appropriate
## Posted at 21:36 in category /fit
[permalink]
[top]
Sun, 06 Feb 2005I'd read chunks of Michael Feathers' book, Working Effectively With Legacy Code, before publication, but it's only on the last few plane rides that I've read it straight through. It's really good: gobs of experience distilled, delivered in a consistently readable style and with an encouraging, even gentle, tone. The Pragmatically Publishing Programmers have just come out with Mike Mason's Pragmatic Version Control Using Subversion. Since CVS and I have a stormy relationship, particularly regarding deleting directories, I bought the paper+PDF version post-haste. Rick Mugridge and Ward Cunningham's Getting Fit for Developing Software is in copyedit now. They're at a particularly difficult game: writing for both nontechnical Customers or testers and programmers, weaving themes and a common thread of examples through what is inherently a lot of not-essentially-connected subtopics, tackling both How To and Why Bother. I was pleased and honored to write the foreword. But there's more: the book brings with it Rick's Fit library, with his DoFixture that's along the lines of my StepFixture but seems to be much better (though I haven't used it yet). That and Rick's other fixtures will help Fit a lot, I think.
## Posted at 21:26 in category /misc
[permalink]
[top]
Notes from a business traveller You can get an entire exit row to yourself if you travel to a Superbowl team's home city on the evening of the Superbowl. But once you check in, those same old questions come crowding into your mind:
## Posted at 21:25 in category /junk
[permalink]
[top]
Sat, 05 Feb 2005So I'm a Macintosh user. I get tons of spam, a big chunk of it from zombie PCs. I can live with that. My spam filter works OK. But now I find that some rapidly spreading spyware takes over the screen of the PC it's installed on and displays my site, www.exampler.com/testing-com. I suppose the spyware authors were testing their program and "testing.com" came to mind. Here I am, having to actively fend off outraged PC owners even though I paid extra money to avoid sharing their wretched, spyware-infested, decent-shell-lacking, backslashian lives. Classic market failure. A negative externality. Grr.
## Posted at 14:51 in category /junk
[permalink]
[top]
Mon, 31 Jan 2005I'm a Customer on an Agile project The Agile Alliance is revamping our website. Micah Martin of ObjectMentor wrote the first version and did a fine job, but the site's been around for four years, and technology moves on. I've been keeping it up for a year, tinkering here and there, but I don't have time to do the complete rewrite we need. So we took bids for the revamp. Unsurprisingly, we're running the project in an Agile style. (If the second iteration goes well, we're going to start deploying in two weeks.) And I'm the partly-on-site Customer for the project, since I live about five miles from the company that's doing the work. I'm having a blast so far. It's great fun steering the project against the background of our original story list. But it's serious fun, because all three bids came in at about the same price, and it was about twice what we wanted to pay. So we're paying what we wanted to pay, which means that I'm steering the project knowing that I have to pack the most value into the time we have, since a lot of stories will fall off the end. I hope this will give me a hint of the insider's view of what product owners go through, especially since I hope to concentrate a chunk of my effort this year on supporting them.
## Posted at 20:06 in category /aa-project
[permalink]
[top]
Tue, 25 Jan 2005Mike Clark has a nice little video showing CruiseControl in action. He needs to affix a disclaimer, though, that he writes his books with Emacs. Dave Hoover tells of an interesting pairing technique: Ping-Pong Programming.
## Posted at 09:28 in category /misc
[permalink]
[top]
Sun, 23 Jan 2005The Agile 2005 call for papers is out. Key dates are March 1 and March 15. (But you'll have to follow the link to see key dates for what.) Agile 2005 is July 24-29 in Denver, USA.
## Posted at 16:48 in category /agile
[permalink]
[top]
Jonathan Kohl has an interesting note on team usability testing using personas. It's his position paper for the Third Canadian Agile Network Workshop, where Jeff Patton (Mr. Agile Interaction Design) and I will be leading the group in (we hope) figuring out more about how interaction design, testing, and the customer-facing parts of agile projects hang together. I don't know if workshop is closed yet.
## Posted at 09:11 in category /testing
[permalink]
[top]
Sat, 22 Jan 2005I would like testers on an agile project to be able to code, preferably in some scripting language like Ruby or Python, secondarily in the languages their programmers are using to write products. In a note on the software testing list, Cem Kaner challenged that assumption. Here's my interpretation of his point. It may not be a correct interpretation, but it's the one I want to address. As Bret Pettichord has pointed out (PDF), testers tend to be generalists. They know testing, but they also need to know the product's business domain. They might have a wide though uneven understanding of technology issues (like differences between Windows NT and Windows 2000, or between IE and Firefox). They need to have the "soft skill" of interpreting the desires of multiple interest groups because part of what they're doing is looking for the Customer's mistakes. As I've been learning from Jeff Patton, they ought to have some background in user-centered design. They're likely to switch projects more often than programmers, so they also need to be quick studies (which Bret also notes). So why then do people like me make such a big deal out of programming?
On balance, it seems to me that programming is underemphasized as a part of a balanced tester's skill set. So I am justified in emphasizing it. I suspect programming is singled out because of historical accident, though my hunch may be skewed by the circles in which I've moved. This is what I saw:
History needn't be destiny.
## Posted at 19:50 in category /agile
[permalink]
[top]
Tue, 11 Jan 2005From Elisabeth Hendrickson, testing consultant and my occasional partner in training: I'd been resisting Ruby for such a long time, thinking that I already knew enough scripting languages. I figured I'd be better off spending my time learning Java and C#. After seeing what WATIR could do and how neat Ruby is, I became a convert. I dug in and learned the basics of Ruby over the weekend (though there is still much I need to learn).
## Posted at 20:42 in category /ruby
[permalink]
[top]
Mon, 10 Jan 2005The OOPSLA Call for Papers is out. I'm chair of the Essays track. Here's its blurb:
I've assembled a wide-ranging committee: a business school professor, head of the MIT AI lab, head of the Illinois sociology department, professors of philosophy, sociology (again), and statistics, a Forrester researcher, a Pragmatic Programmer, the director of the Warren-Wilson Master of Fine Arts program, another software consultant, and me. As that list implies, we're looking for submissions from both those within the software fold and those outside it. Spread the word, please. See also this:
Submissions are due March 18.
## Posted at 14:25 in category /oopsla
[permalink]
[top]
Sun, 09 Jan 2005A story, following up on my post about the virtues of knowing languages close to the machine. One of the things that always impressed me about the great Lisp hackers was the way they moved effortlessly between levels of abstraction. At one moment, they could be thinking extremely abstract ideas like call-with-current-continuation (often abbreviated call/cc). The next, they could be hacking PDP-10 assembler. But are the two levels so unconnected? There was an OOPSLA workshop organized around reading PDP-1 assembler. An interesting machine, the PDP-1. It had one general-purpose register, one IO register that could be used for scratch space, and no stack pointer. In the workshop, we read parts of Peter Deutsch's first Lisp for the PDP-1, struggling through the unfamiliar idioms. Even for people who know assembly, there's a big difference between idioms that assume at least six available registers + a stack pointer (the PDP-11) and those that assume two. One idiom looked something like this (eliding any complications due to having such a small peephole to memory): 104: store 106 in 100 105: goto 203 106: next instruction in the computation ... 203: do something 204: goto 303 ... 303: do something 304: goto 404 ... 404: do something 405: goto the instruction stored in 100 The main program invokes a subcomputation by storing the eventual return address and jumping to the first subroutine. All the components of the subroutine know they're part of a chain of computation, so they just jump to the next link. The final one looks in a known place to find where the main program's next instruction is and jumps there. No stack. When we figured out what was going on (I think Dick Gabriel had to explain it), the thought that flashed through my brain was "call/cc!" It's not - it's closer to setjmp/longjmp - but I wondered whether experience at that low level primed the Lisp hackers to be receptive to ideas like call/cc. The idea of a function call is sort of a closed conceptual universe. It encourages you think about what you can do with function calls, not necessarily what you can do that's like function calling. But if you know assembler, especially from before there were modern-day function calls, you're perhaps more likely to think of a function call as a bricolage: something made up of pieces, pieces that can be assembled in different ways or used independently in combination with new pieces. Maybe call and return don't have to go together. I suspect that's all bogus. Call/cc probably has more to do with Lisper's tendencies to try to make everything a function. (Witness Steele and Sussman's Lambda the Ultimate papers.) And there's all that denotational semantics / lambda calculus stuff. Perhaps experience using assembly to code something vaguely similar didn't till the soil for call/cc. But isn't it pretty to think so?
## Posted at 12:51 in category /misc
[permalink]
[top]
Thu, 06 Jan 2005For old fogies who think there's no progress in software, this advice from Joel Spolsky to college students:
I agree wholeheartedly with that advice. However, I can't help but be amused that in 1981 (when I got my BS), that advice could be - and was - expressed in these terms:
It sounds hard to believe people said that of C, which has been called "portable assembly language", but people did argue (rightly, I think) that people who only knew C did not really understand the costs of things like function calls and passing structures as arguments (as opposed to pointers to structures). Thus, they wrote inefficient C code. I remember serious and heated arguments on USENET about whether C compilers could possibly get good enough to allow C to be used for serious applications like operating systems. (Though I do think the assembly defenders were definitely losing by then.) Nowadays, I wouldn't recommend just learning C, I'd recommend learning the C-coded virtual machine of some higher-level language (Ruby, Python, Lisp, Smalltalk). Learning how closures/blocks/lambdas really work is the modern equivalent of understanding function calls. Ditto garbage collection and passing structs. Not only will you learn about efficiency, you'll learn what these features really do - so you'll more readily recognize situations where they apply, and you'll make fewer puzzling mistakes. Then the next important thing to master is when not to pay attention to what you know about efficiency.
## Posted at 08:52 in category /misc
[permalink]
[top]
Wed, 05 Jan 2005Something for fans of CRC cards, Big Visible Charts, and the like
## Posted at 07:08 in category /agile
[permalink]
[top]
Mon, 03 Jan 2005Are companies more like wheat farmers or rice farmers? Twice a year, Dawn and I drive from the Grandparents' house to the White Mountains to hike. On the way, we always read a nonfiction book to each other. This vacation, it was James Surowiecki's The Wisdom of Crowds. I may have more to say about it later, but for now, this extended quote:
Seems fairly straightforward, but it made me think a bit about the effort to make Agile methods more mainstream. Let's assume that Agile development works for the visionary crowd. Now we want to get early mainstream project managers and executives to adopt it. Geoffrey Moore calls these people pragmatists. He has a rule: pragmatists almost always adopt only after their peers do. Those peers are other pragmatists in the same industry. A visionary entrepreneur or someone in another industry is like a neighboring rice farmer: so different that their experience doesn't predict much. It's only the fellow pragmatists who can be treated as fellow wheat farmers. This produces a first-mover problem: how do you persuade the first pragmatist to try something? I'm not going to talk about that here, but see Moore's Crossing the Chasm. Instead, I'm going to assume that we've succeeded at that. For whatever reason, MegaCorp has one Agile project going and producing good results. Are we over the hump? I think experience tells us not, and Surowiecki gives us a way to talk about why. Let's consider the other project managers and executives in MegaCorp. When they look around themselves within the company, they see a huge variation in project results. (That's why they've probably already flirted with CMM: they crave predictability.) I think of every project as being like its own little rice patch. Why should the manager of the next-door rice patch believe that another project's success with XP means anything? Especially if that project was a pilot project: it was probably staffed with enthusiasts, it was probably small, it was quite likely a greenfield project, the Hawthorne Effect was surely in play, etc. etc. All these are reasons to avoid the risk of change. (In Moore's terminology, software encourages managers to be either visionaries or conservatives, leaving a bigger-than-usual chasm.) To me, this suggests that those who want to encourage the spread of Agility should perhaps concentrate more on the second Agile project in a company than the first. One of the two goals of the Agile Alliance is to help more Agile projects be created. During the next year, we want to reach out more toward project sponsors and other executives. (I should have been doing a better job of that over the last year.) Perhaps the best way to do that is to provide specific support for moving beyond the pilot project. That'd at least be novel, and I think it demonstrates a reassuring long-term commitment. |
|