Use SetUpFixture to prepare the stage for tests

Next, let's create four players to buy tickets. Although player details are not relevant for the test, having named players makes it easier to verify test results. Since we want to check the player balances at the end, explicitly specifying the starting balances also makes results easier to verify. Ideally, we would like to use a table with player name and initial balance, and hide all other properties:

SettlementTests.SetUp


3   |Accounts before the draw|
4   |player|balance|
5   |Arthur|100|
6   |Ford|100|
7   |Trisha|100|
8   |Marvin|100|

We could use a column fixture with two fields and a create method to set up the players. However, there is a better solution called SetUpFixture.

SetUpFixture is another one of Rick Mugridge's classes from FitLibrary. It is a good replacement for ColumnFixture when we just want to prepare data, not to test anything. Instead of populating ColumnFixture properties and then calling a method to create a player, SetUpFixture requires us to implement just one method, and does not have the additional utility column on the screen. Join column headers to get the method name (the trick from Don't type method names, copy them also works on SetUpFixture), and declare method parameters to match column values. Here is a quick way to create a player and assign an initial balance:

Tristan/test/Settlement.cs


26    internal class CreatePlayerFixture : SetUpFixture
27    {
28      private IPlayerManager _playerManager;
29      public CreatePlayerFixture(IPlayerManager pm)
30      {
31        _playerManager = pm;
32      }
33      public void PlayerBalance(String player, decimal balance)
34      {
35        PlayerRegistrationInfo p = new PlayerRegistrationInfo();
36        p.Username = player; p.Name = player;
37        p.Password = "XXXXXX";
38        // define other mandatory properties
39        int playerId = _playerManager.RegisterPlayer(p);
40        _playerManager.AdjustBalance(playerId, balance);
41      }
42    }

Method PlayerBalance is used to execute our table rows, because the table has two columns: player and balance. We now need to connect this fixture to prepared service objects. We do this in a new method in our SettlementTest. The method is named AccountsBeforeTheDraw, because our business analysts named the intial table “Accounts before the draw”:

Tristan/test/Settlement.cs


86      public Fixture AccountsBeforeTheDraw()
87      {
88        return new CreatePlayerFixture(playerManager);
89      }

The first row in the test table does not specify a fixture class name, but a method of the DoFixture instance in flow mode. This gives us more freedom over fixture class names. They no longer have to be customer-friendly, because customers never see the class names of utility fixtures directly. All rows after the first are used just as if they were part of a normal SetUpFixture table.

Next, we need to put some tickets into the draw. Again, let's use an embedded SetUpFixture. We are not concerned with exact draw details, so let's hide the draw completely from the test tables and pass it directly from the enclosing DoFixture. This leaves us with player name, selected numbers and the ticket value for the ticket table.

SettlementTests.OneWinnerSixBallsFirstTry


3   |Tickets in the Draw|
4   |player|numbers|value|
5   |Ford|2,11,22,33,39,18|50|
6   |Arthur|1,5,4,7,9,20|50|
7   |Trisha|10,21,30,6,16,26|50|
8   |Marvin|12,13,14,15,16,17|50|

FIT calls the PlayerNumbersValue method for each row of the table:

Tristan/test/Settlement.cs


43    internal class TicketPurchaseFixture: SetUpFixture
44    {
45      private IDrawManager _drawManager;
46      private DateTime _drawDate;
47      private IPlayerManager _playerManager;
48  
49      public TicketPurchaseFixture(IPlayerManager pm, IDrawManager dm, 
50      	DateTime drawDate)
51      {
52        _drawManager = dm;
53        _playerManager = pm;
54        _drawDate = drawDate;
55      }
56      public void PlayerNumbersValue(String player, int[] numbers, decimal value)
57      {
58        _drawManager.PurchaseTicket(_drawDate, 
59          _playerManager.GetPlayer(player).PlayerId, numbers, value);
60      }
61    }

To initialise this fixture, let's add a TicketsInTheDraw method to SettlementTest:

Tristan/test/Settlement.cs


74      public Fixture TicketsInTheDraw()
75      {
76        return new TicketPurchaseFixture(playerManager, drawManager, drawDate);
77      }

The next step is to enter draw results and settle the draw.

SettlementTests.OneWinnerSixBallsFirstTry


10  |Draw results are|1,5,4,20,9,7|

In this case there is no embedded fixture: we process the test step in a single method of SettlementTest. Again, we use the automatic conversion from a comma-separated value list to a .NET array:

Tristan/test/Settlement.cs


78      public void DrawResultsAre(int[] numbers)
79      {
80        drawManager.SettleDraw(drawDate, numbers);
81      }

To complete our test script, we have to verify player account balances. We can use a ColumnFixture for this:

SettlementTests.OneWinnerSixBallsFirstTry


12  |Accounts after the Draw|
13  |Player|Balance?|
14  |Arthur|118|
15  |Ford|50|
16  |Trisha|50|
17  |Marvin|50|

The embedded ColumnFixture is relatively simple:

Tristan/test/Settlement.cs


10    internal class BalanceCheckFixture : ColumnFixture
11    {
12      private IPlayerManager _playerManager;
13      public BalanceCheckFixture(IPlayerManager pm)
14      {
15        _playerManager = pm;
16      }
17      public String player;
18      public decimal Balance
19      {
20        get
21        {
22          return _playerManager.GetPlayer(player).Balance;
23        }
24      }
25    }

[Tip]Can I use flow mode without weird method names?

SequenceFixture from FitLibrary allows you to use most DoFixture features, such as flow control, embedding other fixtures and wrapping business objects (see Wrapping business objects with DoFixture), but uses a different convention for method calls: the first cell of a row is used for the method name, and all other cells define parameters. So using SequenceFixture makes more sense for functional regression tests, where you don't care much about how pages look.

SettlementTest initialises this new class just as it does other embedded fixtures:

Tristan/test/Settlement.cs


82      public Fixture AccountsAfterTheDraw()
83      {
84        return new BalanceCheckFixture(playerManager);
85      }

The end result is shown in Figure 8.1, “DoFixture allows us to embed other fixtures ”. SettlementTest controls the whole page, but individual methods return embedded fixtures enabling us to benefit from the features of DoFixture and other fixtures.

Figure 8.1. DoFixture allows us to embed other fixtures

DoFixture allows us to embed other fixtures