FitNesse Query Tables

This entry is part 5 of 5 in the series FitNesse

Query Tables
In the last post we looked at using Decision Tables with FitNesse. Each row in a decision table can be thought of as a Test Case, with some of the columns representing Inputs and others representing expected Outputs.

Now we move on to something a little more complicated. Query Tables represent a set of results. The Table in its entirety represents a single test (e.g. Get All Employees in IT Department).

The table contains a row for each expected result, and the columns represent the attributes of the objects. Here’s a Query Table in FitNesse that loads a set of Employees.

Query Table

The Markup for this table is about as simple as you’d expect.

|Query:All Employees                             |
|Employee Number|First Name|Last Name|Hire Date  |
|1429           |Bob       |Martin   |10-Oct-1975|
|9924           |Bill      |Mitchell |19-Dec-1966|

The first thing to note is the word Query in the first row. This tells FitNesse that the table should be interpreted as a Query Table.

The name of the table ‘All Employees’ will need to map to a Fixture class called ‘AllEmployees’.

The next row contains the column headers. Our Test Fixture is going to need to mark the returned data with these Column names so that FitNesse knows where it fits in the table.

Query Table Fixtures
Before we look at the specific details of how to pass data to and return data from the Query Table Test Fixture, lets look at the structure of the Test Fixture itself.

At its simplest we need only provide a function called ‘Query’ that returns a list of objects. Since it has no parameters the fixture class doesn’t need any special constructor. The query method will get called and should return the table of data.

We’ll get to the exact details of how the list of objects will represent a table of data. For now you just need to understand that when the Tests are run in FitNesse, the ‘Query’ method will be executed, and it returns a list of something.

public class AllEmployees
{
    public List<Object> query()
    {
        throw new NotImplementedException();
    }
}

We can add a constructor to the class, this will allow our test to feed individual parameters into the Test Fixture. This can be useful if we want to pull back a filtered list of data.

public class SimpleQueryFixture
{
    public SimpleQueryFixture(date HiredBefore)
    {
    }

    public List<Object> query()
    {
        throw new NotImplementedException();
    }
}

Constructor Parameters are specified in the first row of the table.

|Query:All Employees                 |01-Jan-2000|
|Employee Number|First Name|Last Name|Hire Date  |
|1429           |Bob       |Martin   |10-Oct-1975|
|9924           |Bill      |Mitchell |19-Dec-1966|

Of course you can provide multiple parameters to your constructor, just make sure the values in the table match the signature of the Test Fixture constructor.

|Query:Employees By Date City Dept|01-Jan-2000|"IT"|"London" |
|Employee Number             |First Name |Last Name|Hire Date|

We can also optionally implement a ‘Table’ method. If supplied this will be invoked before the ‘Query’ method, and it will receive the existing FitNesse table and it’s contents. This can be useful if we want to provide a table of data, or a partially filled table, and have columns filled in or even overwritten.

public class SimpleQueryFixture
{
    public void table(List<List<String>> table)
    {
        throw new NotImplementedException();
    }

    public List<Object> query()
    {
        throw new NotImplementedException();
    }
}

Table Formats
The eagle eyed among you will notice that the data structure passed to the ‘Table’ method is a List of Lists of Strings, whereas the data structure returned from the ‘Query’ method is a List of Objects.

It’s worth understanding how these tables are represented and the differences between them. We’ll see these data structures used again and again as we look at other types of FitNesse/SLiM tables.

The Output Table – From the ‘Query’ method
We’ll start with the output table since that is by far the most common one you’ll use. It uses a nested List of Lists of Lists type arrangement. Here’s a hard-coded example of how you would return a table of employee details from the query method of your Test Fixture. It illustrates the data structure.

public List<Object> query()
{
    return new
          List<Object>{
            new List<Object>{
              new List<String>{"Employee Number", "1429"},
              new List<String>{"First Name", "Bob"},
              new List<String>{"Last Name", "Martin"},
              new List<String>{"Hire Date", "10-Oct-1974"}
            },
            new List<Object>{
              new List<String>{"Employee Number", "8832"},
              new List<String>{"First Name", "James"},
              new List<String>{"Last Name", "Grenning"},
              new List<String>{"Hire Date", "15-Dec-1979"}
            }
          };
}

From the outside our table looks like a List of Objects. Each item in that list represents a row in the table, and is also represented by a List of Objects. Each cell in the row is represented by a List of Strings. This last bit is where the confusion may lie for the uninitiated.

Instead of representing the Column headers once in a row of their own, the table represents each cell in every row as a Name/Value pair in the form of a List of two strings.

This has it’s advantages, you can pull an individual Row out of the Data structure and have everything you need, the column names and cell values.

It is a little unconventional though, there’s a bit of a mismatch between how you view a table and how it’s actually represented. But, once you know what’s happening it’s fine. This incidentally is where the input and output tables differ. Tables that are sent to the Table method represent the column headers as a row in their own right.

On order to avoid creating boilerplate code from scratch every time we use the Query Table, we can take the tasks of translating from domain objects to this list arrangement and make a generic reusable version. We’ll look at how to do that towards the end of this post.

The Input Table – To the ‘Table’ method
Tables that are sent by FitNesse to the ‘Table’ method are represented by a List>. To put that in english, each row is a list of Strings, and a table is a List of these rows. This is much closer to the way you would imagine a table would be represented.

Using our tables from above as an example, if we have a table that shows Employee Number, First Name, Last Name and Hire Date, we could use code like the following to turn the table into a list of Employee objects.

List<Employee> employees = new List<Employee>();

    foreach(var row in table)
        {
            if(row[0] != "Employee Number")
            {
                employees.Add(
                    new Employee(row[0],
                                 row[1],
                                 row[2],
                                 row[3]));
            }
        }

Pardon the horrible code here, but you get the point. We ignore the first row as it contains the column headers. The four items in each subsequent row represent the cell values from the table, we pass these to the constructor of our domain object.

Translating from Domain Objects To Query Table
It’s unlikely that the data in your application will be represented by a data structure that looks anything like that required by the Query Table.

Assuming we have a list of Employee objects, how are we going to knock it into the shape that will allow our test fixture to pass it pack to FitNesse.

Obviously we could hand code each Test Fixture as the need arises, but that’s a lot of boring repetitive boilerplate code.

Below is an example of using Reflection to convert a list of objects into a list that FitNesse can work with. It makes the assumption that the properties of the object are in CamelCase and by splitting the words in the property name we get the Column name from the table. So, ‘EmployeeNumber’ becomes ‘Employee Number’

class SlimTableAdaptor<T>
{
    public List<Object> FromObjects(List<T> items)
    {
        return CreateTable(items);
    }

    private List<Object> CreateTable(List<T> items)
    {
        return items.Select(CreateRow).Cast<Object>().ToList();
    }

    private List<Object> CreateRow(T item)
    {
        PropertyInfo[] properties = GetProperties();
        return properties.Select(property =>
                         CreateColumn(item, property)).ToList();
    }

    private object CreateColumn(Object item, PropertyInfo property)
    {
        string propertyName = SplitCamelCase(property.Name);
        string value = GetPropertyValue(item, property.Name);
        return new List<string> { propertyName, value };
    }

    private PropertyInfo[] GetProperties()
    {
        return typeof(T).GetProperties();
    }

    private string GetPropertyValue(object source, string property)
    {
        object value = source.GetType()
                             .GetProperty(property)
                             .GetValue(source, null);

        string valueAsString = value.ToString();

        if (value.GetType().Name == "DateTime")
            valueAsString = FixDate(value);

        return valueAsString;
    }

    private string SplitCamelCase(string value)
    {
        return System.Text.RegularExpressions.Regex
            .Replace(value, "([A-Z])", " $1").Trim();
    }

    private string FixDate(Object value)
    {
        DateTime date = (DateTime) value;

        if (date.TimeOfDay.Ticks == 0)
            return date.ToString("dd-MMM-yyyy");

        return value.ToString();
    }
}

With a helper class like this written, it becomes a trivial matter to create a Test Fixture class. Here’s what our Query method might look like.

public List<Object> query()
{
    var employees = EmployeeRepository.GetAll();

    var helper = new SlimTableAdaptor<Employee>();
    return helper.FromObjects(employees);
}

This is a simplified version of the helper class. You might like to add some additional features such as

  • Ability to specifically map property names to column names
  • Ability to return a subset of properties rather than all of them
  • Ability to translate from Input Table to list of Objects
  • Ability to translate other sources of Data (e.g. Data Tables, XML etc.)

Subset Tables
There are two specialised types of Query Table that you can use, Subset Query Tables, and Ordered Query Tables. The names pretty much leave nothing to the imagination here.

When we use a Subset Query Table our tests pass as long as the rows we specify exist in the results returned from the Fixture.

When we use an Ordered Query Table our tests pass as long as the rows we specify match exactly the rows returned from the Fixture, including the ordering of the rows.

Subset and Ordered Query Tables work exactly like regular Query Tables, the data is returned in the same format, we can specify constructor parameters and an input table in exactly the same way.

Here’s a Subset Query Table

|Subset Query:All Employees                      |
|Employee Number|First Name|Last Name|Hire Date  |
|1429           |Bob       |Martin   |10-Oct-1975|

As long as one of the rows returned from the AllEmployees test fixture matches the row in the table, the test will pass.

Here’s an Ordered Query Table

|Ordered Query:All Employees                     |
|Employee Number|First Name|Last Name|Hire Date  |
|1429           |Bob       |Martin   |10-Oct-1975|
|9924           |Bill      |Mitchell |19-Dec-1966|

The rows returned from the AllEmployees test fixture must match those in the table exactly, including matching the order in which the rows are listed.

FitNesse Decision Tables

This entry is part 4 of 5 in the series FitNesse

In the last post, we set up a solution to demonstrate the use of FitNesse. The solution contained a Calculator Project, and a Calculator.Specifications project which contains an instance of FitNesse, and an Acceptance Test fixture for the Calculator project.

To show that everything was up and running we created a simple Decision Table test in FitNesse.
In this post we’ll look more closely and Decision Tables.

Decisions Decisions
A FitNesse Decision Table allows us to supply a number of input parameters and receive back a number of output values. A test passes or fails based on whether the expected outputs match the actual outputs.

In our last post we tested a simple calculation using our Calculator project. Let’s look at the Markup for that Table, line by line.

Line 1 defines the name of the table, and by convention this also tells FitNesse the name of the Class it should try to use when executing the test. In this case FitNesse will search our TestFixtures for a class called DoSimpleMath. Alternatively the Fixture name ‘DoSimpleMatch’ could have been used in the table.

The Exclamation mark at the start of Line one is interesting. If the Table name had been written without spaces as described above, FitNesse would have automatically turned the table header into a link.

The Exclamation mark prevents links being automatically created. Strictly speaking in this instance it’s not needed, since FitNesse does not try to create links where spaces exist. It is however good practice to include the exclamation even when not needed.

Line 2 defines the parameters of the test, but the input values we’ll sent to the test, and the output values we get back. In this case A, B and Op are all input parameters. Result is an output value as indicated by the question mark ‘?’.

Line 3 consists of the values to be used with the Test. We supply 1, 2 and + and we state that we expect the value 3 to be the result of adding 1 and 2.

!|Do Simple Maths  |
|A  |B  |Op|Result?|
|1.0|2.0|+ |3.0    |

Naturally, you can create multiple rows to test various scenarios.

!|Do Simple Maths  |
|A  |B  |Op|Result?|
|1.0|2.0|+ |3.0    |
|5.0|5.0|- |0      |
|2.0|3.0|* |6.0    |
|6.0|3.0|+ |2.0    |

Decision Table Fixtures
As mention above the name of the Table dictates the name of the class that FitNesse will attempt to execute the test.

It may be that a table name and the particular input and output columns are ideal for describing features of the system, but are not good names for objects in our domain model.

This is where Fixtures come in. Generally speaking we don’t want to write FitNesse tests that directly access the domain model. Apart from the fact that good names for tests may not make good interfaces for objects, there is also a brittleness from hooking up directly to a Domain Model that could change.

Test Fixtures provide a level of abstraction between FitNesse and our System Under Test. Fixtures are usually simple pass through objects that invoke the expected behaviour and return apropriate results.

We declare the inputs as public fields. There’s no benefit in declaring properties and private fields in a fixture. We want the simplest possible implementation that allows us to get values in and out.

public class DoSimpleMaths
{
    public decimal A;
    public decimal B;
    public string Op;

    public decimal Result()
    {
        if (Op == "+")
            return Calculator.Add(A, B);

        if (Op == "-")
            return Calculator.Subtract(A, B);

        if (Op == "*")
            return Calculator.Multiply(A, B);

        if (Op == "/")
            return Calculator.Divide(A, B);

        throw new NotImplementedException(string.Format("'{0}' is not an implemented Operator", Op));
    }
}

The following fixture implements the Result output as a function. If your Decision Table includes multiple outputs you can implement each as a separate function for each.

public class DoDivisionWithRemainder
{
    public int A;
    public int B;

    public int Result()
    {
        return A / B;
    }

    public int Remainder()
    {
        return A % B;
    }
}

If the work of the fixture can be implemented in a single method, you could consider the following alternative approach. Use public fields for all inputs and outputs, then use a method called Execute to populate all of the outputs.

FitNesse will run the ‘Execute’ method before evaluating the outputs.

public class DoDivisionWithRemainder
{
    public int A;
    public int B;
    public int Result;
    public int Remainder;

    public void Execute()
    {
        Result = A / B;
        Remainder = A % B;
    }
}

The following FitNesse Decision Table will work with either of the previous two Test Fixtures.

!|Do Division With Remainder|
|A  |B |Result? |Remainder? |
|13 |5 |2       |3          |

Beyond the Basics
We can do some interesting things beyond the basic decision tables shown above. For example if we have inputs that will be the same for each row in the table, we can define it once in the header.

!|AddAFixedPercentage        |10     |
|Principal                   |Result?|
|0                           |0.0    |
|10                          |11.0   |
|100                         |110.0  |

In the above example, the value 10 is passed into the constructor of the fixture. It can then be used for each row, without needing a column for it in the table.

public class AddAFixedPercentage
{
    public decimal principal;
    private decimal _percentage;

    public AddAFixedPercentage(decimal <span class="hiddenGrammarError" pre="">percentage)
    {
        _percentage</span> = percentage;
    }

    public decimal result()
    {
        return Calculator.AddPercentage(principal, _percentage);
    }
}

If you want to pass more than one parameter to the Fixture you can do that. Just add them to the first row in the table. Make sure that the constructor has the correct number of parameters of the correct types to accept the values in the table.

!|FixtureName  |10 |ABC |3.14 |

When testing our expected results against the actual results, we also have options. We don’t need to find an exact match in order to pass a test. Sometimes an approximate match, or a range of values may be sufficient. Let’s remind ourselves of the markup for an exact match.

!|Do Simple Maths  |
|A  |B  |Op|Result?|
|6  |2  |/ |3      |

If we use the ~= operator we can match on approximately equal values.

|22|7|/ |~=3.14      |

22/7 is the famous approximation of PI, but in reality it’s not all that close an approximation. In fact it all goes wrong if you look beyond 2 decimal places. The Test above will pass because at two decimal places, 22/7 matches 3.14.

We can also check that a value is Grater Than another.

|10|1|+ |>10      |

Or that a value falls within a given range.

|5|3|* |14<_<16   |

When Decision Tables Work Best
As mentioned above, Decision Tables are very useful when we have a set of clearly defined Inputs and Outputs. It may seem that most problems can be reduced to this sort of scenario, and that’s probably true, however we’ll see other options in subsequent posts for other types of scenarios.

Aha! Unit Tests – DDDBelfast

Sample Code

On Saturday I spoke at DDDBelfast. My Session was on Unit Testing. After the Test Driven Development session in Bristol, it occured to me that a more fundamental problem was Unit Testing itself. Whether the Tests are Written before or after the code is a non-issue if developers aren’t writing automated Unit Tests at all.

Here are the slides for the session.



The sample Code includes the Wizard project which includes a suite of Unit Tests, you’ll need to install MOQ and NUnit to run all the tests.

Also included are the three examples of injecting mocks, and the example of how traditional NTier code can violate the Single Responsibility Principal, and how to avoid that problem

Any questions about any of this, feel free to get in touch or leave a comment.

Switch to our mobile site