TDD and random numbers in ruby

I’m about to TDD a Ruby class whose behaviour will involve the use of random numbers. I expect the algorithms within the class to evolve as I implement new stories, so I don’t want to design and build a testing mechanism that will be brittle when those changes occur. But before I can write the next example, I need to figure out how to control the random numbers needed by the code under test. Off the top of my head I can think of four options:

  1. One way would be to set a fixed seed just before each test and then simply let the random algorithm do its thing. But for each new behaviour I would need to guess the appropriate seed, which is likely to be time-consuming. Furthermore, the relationship between each magic seed and the specific behaviour tested is likely to be obscure, possibly requiring comments to document it for the future reader. And finally, if the algorithm later evolves in such a way as to consume random numbers in a different order or quantity, the seed may turn out to be inappropriate, leading to broken tests or, worse, tests that pass but which no longer test the planned behaviour.
  2. Alternatively I could redefine Kernel::rand — but that could potentially interfere with stuff I don’t know about elsewhere in the object space.
  3. Within the class under test I could self-encapsulate the call to Kernel::rand, and then override the encapsulating method in a subclass for the tests. But then I’m not testing the class itself.
  4. Finally, I could parameterize the class, passing to it an object that generates random numbers for it. This option appears to give me complete control, without being too brittle or trampling on anyone else in the object space.

So I’ll go with option 4. Right now, though, I’m not sure what interface the randomizer object should provide to the calling class. Looking ahead, I expect I’ll most likely want to select a random item from an array, which means selecting a random integer in the range 0...(array.length). And for this next example all I’ll need is a couple of different randomizers that return 0 or 1 on every request, so I’ll simply pass in a proc:

obj.randomize_using { |ceil| 0 }

And if ever I need to provide a specific sequence of varying random numbers, I can do it like this:

rands = [1, 0, 2]
obj.randomize_using { |ceil| rands.shift || 0 }

Later that same day…

The class I’m developing has evolved quite a lot and split into three. And suddenly, with the most recent change, three of the tests have begun failing. A little investigation reveals that the code is now consuming a random number when it didn’t need to in the past, and so some of my randomizer procs now provide inappropriate values. It turns out that two of the failing examples actually boil down to being a single test of a piece that has now been refactored out into another class; by refactoring the tests to match I can remove the dependency on random numbers altogether. And the last broken test is fixed by providing a randomizer that respects the ceiling passed to it (not an unreasonable request):

obj.randomize_using { |ceil| [2, ceil-1].min }

This works, and I get no more surprises during the session.

Advertisements

dynamic modelling in UML

Over on my personal UML style guide Yanic recently asked “I’m wondering why you prefer collaboration diagrams over sequence diagrams?”. Oops, I never really explained that — so here goes…

The main point about my UML style is to make it clear to the reader that the model is a sketch. What I care about with dynamic models is the division of responsibility among objects; I want to show who does what in carrying out this one system responsibility. But I am rarely interested in describing how those objects do their thing; which means that I don’t care to model:

  1. the exact timing of messages and responses;
  2. the type and content of message parameters;
  3. the type and content of message responses;
  4. what other activities the objects get up to before, during or after the collaboration I’m currently describing.

To my mind, a collaboration diagram is more suited to this style, for at least the following reasons:

  1. A collaboration diagram shows objects, whereas an interaction diagram focuses on timelines. I want to depict objects playing roles in a story; timing and the flow of time is (almost) never relevant for that. When whiteboarding or using CRC cards, I want to be able to point to objects; I want to be able to identify with, and play the part of, objects. Tangible, autonomous, anthropomorphic, responsible actors in the story; not column headings in a flowchart.
  2. Those timelines can be interpreted as implying things about the focus of attention of the objects, particularly when they show “method bodies” as blocks of activity in response to an incoming message. It could then be assumed that the model intentionally says something explicit about such things, which I (almost) never mean to do.
  3. I think of the “messages” on a collaboration diagram as indicating delegation of responsibility; whereas the explicit time axis and the receiver blocks in an interaction diagram can make them seem to be actual messages (or worse, method calls).
  4. The diagram names are indicative: “Collaboration” is about apportioning responsibility; “interaction” is about sending and receiving. The latter seems to me to be at a lower level of abstraction.

I know that one can produce an interaction diagram and a collaboration diagram that are logically equivalent, and so my reason for avoiding the former is, in the end, a matter of personal preference. I like models that say only what I want them to say, without implying anything else. Less is more.

setup and teardown for a ruby TestSuite

My Watir tests for a particular application are grouped into three subclasses of Test::Unit::TestCase. To run them all I have a top-level test suite that looks like this:

require 'test/unit'

server.start

require 'test/first_tester'
require 'test/second_tester'
require 'test/third_tester'

server.stop

But this doesn’t work as intended, because the server.stop line at the end of the script is executed before the test suite is constructed and executed, which is obviously not what I want. The problem is in test/unit: the require causes this script to collect every test method in the ObjectSpace and then invoke the runner on the resulting suite.

What I would like is to have setup and teardown methods on TestSuite; but they aren’t there. I feel sure someone somewhere must have done this already (the closest I could find was this old post on ruby-talk), but I couldn’t find one quickly so I wrote my own:

require 'test/unit/testsuite'
require 'test/unit/ui/console/testrunner'

require 'test/first_tester'
require 'test/second_tester'
require 'test/third_tester'

class TS_MyTestSuite < Test::Unit::TestSuite
  def self.suite
    result = self.new(self.class.name)
    result << FirstTester.suite
    result << SecondTester.suite
    result << ThirdTester.suite
    return result
  end

  def setup
    server.start
  end

  def teardown
    server.stop
  end

  def run(*args)
    setup
    super
    teardown
  end
end

Test::Unit::UI::Console::TestRunner.run(TS_MyTestSuite)

Please let me know if this solution – or anything equivalent – is already published elsewhere, because I hate re-inventing wheels…

UML style – an example

Last autumn I posted a personal UML style guide, followed soon afterwards by a detailed explanation of my reasoning for not including associations. Those articles had quite a positive reception (thanks), but patterns and heuristics can only go so far. So this article presents a (long) worked example to show my UML style in action. I make no claims for the resulting model – except that it works for me, and seems to satisfy those who are able to persuade me to create UML models. I should also point out that I usually – ie. when I have the opportunity – jump right to the last page; what you see here is one conceptual route to that end point…

Fade to an imaginary office somewhere in the north of England. It’s the end of an imaginary project in which we’ve developed an XP planning game tool in Java (this example is based on the Planning Game Simulator exercise in Bill Wake’s excellent Refactoring Workbook). The customer has scheduled a story to document any “interesting” parts of the design, as a roadmap for the code’s future developers and maintainers. We select the tool’s status bar, and we decide to draw a UML model to convey the following information:

The status bar always displays a summary of the plan (number of cards, their total cost, current velocity, and number of iterations required to complete the backlog). Whenever a card is added to or removed from the backlog, or when a card’s cost changes, or when a card is split, the Plan re-calculates everything and the status bar updates itself to show the new information. The status bar does this by listening for change events thrown by the Backlog; when one occurs it requests the latest information from the Plan and displays it.

We begin by drawing a static model showing the classes involved, with their relationships, methods and packages. This is the kind of model created by one of those reverse engineering tools that reads our code and constructs a thorough model of it all:
Continue reading

a personal UML style guide

I use UML a lot in my practice. Not the UML, but a UML – eclectic and variable notation, sketched on whiteboards and cards, and scrubbed out immediately. But recently I’ve actually had to make a UML model to go in a document, so I thought I would share a few lessons I’ve learned about UML over the years…

  1. It’s okay to use UML to document code, as a navigational aid or to give a 30,000-feet summary for folks who can’t read the code.
  2. But only use it to describe stable aspects of the code. Don’t try to hit a moving target, or to describe code that doesn’t exist.
  3. Divide the model into pieces, each of which tells a single story. It can be very tempting to try to get everything onto one huge static model, but when the aim is to communicate smaller focused models work better.
  4. Prefer dynamic models, particularly collaboration diagrams and state transition models. Where multiple threads or processes interact, use activity models (with swim-lanes) to show timing and synchronisation. Static models (particularly class diagrams) often give the (false) impression of “structure” – whereas a running system is all about behaviour. So focus the models on the system’s behaviour.
  5. I use only two kinds of relationship on a class diagram: «implements» and «uses». No containment or aggregation (even when describing C++ code), no bi-directional relationships, no roles or multiplicities, and no navigability.
  6. Follow each static model with a textual traversal of the diagram: Write a single paragraph for each class, consisting of a 1-sentence description of the class’ role in the model (not the system), followed by a 1-sentence description of the job done by each of the dependencies leaving that class. The result will be a simplified narrative that walks through the system’s static structure in a dynamic way.
  7. When deciding what to include on a class diagram, begin with the classes that are essential to telling the story of this particular part of the system. Then add in the “hard” structure, ie. the «inherits» relationships and those «uses» relationships that are really «creates». Then try to remove classes until the model is as simple as possible; only add further dependencies if they carry delegation that’s essential to telling the story.
  8. Don’t be afraid to mix diagram types. I’m particularly prone to putting messages on my class diagrams, for example to show system start-up or incoming asynchronous stimuli.
  9. Lay out each model, whether static or dynamic, so that it reads naturally from left to right and from top to bottom. This will usually mean that «inherits» relationships point up the page (abstract above concrete) and «uses» relationships tend to point to the right. In fact I find that left-pointing dependencies usually only arise to represent the “call-backs” in some variant of the Observer pattern.
  10. Try to arrange for one of the models to describe the entire system using 4-6 classes.

These aren’t “rules” as such, and I don’t consciously use them as a check-list or style guide. But when I’ve made a model I’m happy with, I find it always has all of the above properties. Does a similar style work for you? What, if anything, do you do differently?

Update, 21-jan-07
I’ve now posted a worked example of this style of UML modelling.

how to start organic change

Through bitter experience I’ve come to recognise that change works best when it isn’t imposed, and when it is allowed to occur over a period of time. So when you or I recognise that an organisation’s performance is below par, how are we supposed to get it to change. These days I try to foster change, rather than to impose it. Here are some great ways to start the ball rolling:

Current Reality Tree (CRT)
This is a great way to bring the whole organisation together in recognising and understanding current problems and the links between them. Develop a CRT together as a group to understand the very small number of root causes that lie behind today’s poor performance. Hopefully at the end of the process the whole group will feel they “own” those root causes, and everyone will be motivated to seek and implement solutions.
Simulations
Help everyone gain some experience they wouldn’t otherwise get, by running simulations. These “games” can show some specific aspect of current or future life, but isolated from the other daily crud and also speeded up. Games give the participants rapid feedback on decisions such as they make every day, and insights into their impact on other aspects of their organisation. These insights often “click” some days later (link via Keith Ray), causing folks to spontaneously begin instigating change themselves.
Hansei-kaizen
Run frequent (eg. weekly) retrospectives, and encourage participants to take ownership of the problems they observed in the previous week. Create a culture in which the “way we do things here” gradually evolves, and in which everyone sees this evolution as natural.

I’ve worked almost exclusively with the last of these, usually preceded by some root-cause analysis using CRTs. I’ll definitely be adding more simulations to the mix in future. Do you have more techniques to add to this list? And how do you mix them when asked to initiate an agile transition?