In Chapter 6, Writing efficient test scripts, we saw how
we can write tests almost in plain English with
DoFixture. However, for some
test steps it is better to use a more compact format, especially
when actions or data have a repetitive structure. Luckily, we
can mix and match with
DoFixture: use story-like rows when this makes sense, and use other
fixtures when we need a more compact structure. Let's see how
DoFixture
can embed other fixtures.
In this chapter, we'll implement the following user story:
Pay out winnings
As an operator, I want the system to find winning tickets, calculate winnings and pay money into ticket holders' accounts when I enter draw results.
Just as with previous stories, our first concern is how to test that the system works as expected. Our business analysts come up with a few ideas:
Let's put four tickets in a draw, each worth 50 dollars, for completely different numbers. Then let's enter draw results that match all six numbers on one of the tickets. Other tickets do not match any drawn numbers. The owner of the winning ticket should take 68% of the payout pool. The total pool value is 200 dollars and the operator takes 50%, which leaves 100 for prizes. The prize for six winning numbers is 68 dollars. So the owner of this ticket should have 18 dollars more than he had before (68 in prize money minus 50 paid for the ticket). The other three players should have 50 dollars less than they started with.
Let's register four tickets as before, but have two tickets with four common numbers, and then draw these numbers along with two others not appearing on any ticket. The owners of two winning tickets should split 10% of the payout pool in proportion to their ticket values. To test the proportional split, let's have one ticket at 80 dollars and the other at 20 dollars, so the prize should be split 4/1.
The first thing that these tests signal is that tickets can
have different values. Luckily, our
ITicket
interface already provides this, so we don't have to
refactor. Also, the test scripts hint that some parts of the tests need a
story-based structure (draw results) and other parts need
a repetitive structure (buy multiple tickets, check
winnings for each ticket). So we have to combine what we
learned in the previous two chapters.
DoFixture
allows us to embed other fixtures into tests.
To embed fixtures, we first need to split one big table
into several smaller ones.
DoFixture
allows this with a feature called
flow:
if the first test class on a page is a subclass of
DoFixture,
it takes over the whole page, and allows us to
split the rows into individual tables.
When the page is in flow mode, the test rows are first
matched to flow fixture methods. If no corresponding
method exists, then a fixture is created normally,
taking the class name from the first row. So, we can
keep using tables for test steps where needed.
If a method of a flow test returns a
Fixture
instance, the rest of the current table is then analysed
as if it was specified for this fixture. So we can use a
DoFixture
method to prepare a
ColumnFixture for execution.
In flow mode we can embed and reuse fixtures
without depending on them to read the context. This is
the FitNesse version of
dependency injection,[21]
which makes writing and combining fixtures much easier.
Flow scripts are much easier to read, as the first row of a table does not have to be devoted to specifying the class name. Also, flow mode allows us to define and store the context of a test script in private variables of a test fixture, rather than static global variables.
We'll use a
DoFixture
in flow mode for the settlement test script. This
fixture provides context to other fixtures. We'll
need to give other fixtures a reference
to a player manager and a draw manager, so that they
can work on the same accounts and tickets. In
addition, we'll need to open a draw in order to
register tickets. Because draw details are not
really important for this test, let's just create a
draw in the background, without requiring anything
to be done explicitly in the test. This is an
example of simplifying tests as explained in
Remove irrelevant information.
Our flow fixture initialises these
“service objects” and other fixtures
use them later:
62 public class SettlementTest:DoFixture
63 {
64 private IDrawManager drawManager;
65 private IPlayerManager playerManager;
66 private DateTime drawDate;
67 public SettlementTest()
68 {
69 playerManager = new PlayerManager();
70 drawManager = new DrawManager(playerManager);
71 drawDate = DateTime.Now;
72 drawManager.CreateDraw(drawDate);
73 }
90 }
To start a test in flow mode, create a table for
the flow fixture class at the top of the page. This table
typically contains just the class name. Because
this must be the first table on the page, the
class name must be fully qualified (with the
namespace). We cannot even use the import directive
before a flow table.
1 !|Tristan.Test.Settlement.SettlementTest|
If this first table, which just holds the test name,
starts confusing your non-technical users or
customers, put a short test description after the
initial setup (use
!3
before it to create a third-level heading). Then tell customers to ignore
everything above the heading and focus on the
part below the title.
![]() | Stuff to remember |
|---|---|
|
[21] A software pattern in which service references and configuration are passed to the object by the framework, without any code in the object to request or locate the services and configuration. This pattern leads to loose coupling and objects that are much easier to test and combine. Objects using this pattern also have less code because they are not responsible for reaching out to services or reading the configuration.

![[Note]](../images/resources/note.png)


