Being a TDD fan, I’m writing tests all the time. And I sometimes ended up having groups of nearly identical tests:
- they use exactly the same objects, send the same messages,
- but they differ only by values.
In a discussion on the Pharo-dev mailing list, Laurent Laffont pointed what is done in PhpUnit and suggested to have something similar in Pharo. After a few hours hacking I’ve my parametrized tests working and integrated with the test runner to ease debugging.
I’ve introduced a ParameterizedTestCase which supports both “plain” tests as well as parametrized tests. This class should be subclassed as in the following example:
ParameterizedTestCase subclass: #ExampleOfParameterizedTestCase
instanceVariableNames: ”
classVariableNames: ”
poolDictionaries: ”
category: ‘ParameterizedTests’
A test method is any method that is marked with the pragma testParametersSelector: as in the following example:
ExampleOfParameterizedTestCase>>#should: value1 plus: value2 equals: expectedSum
<testParametersSelector: #givenValuesAndTheirExpectSum>
self assert: value1 + value2 equals: expectedSum
The argument of the pragma testParametersSelector: is the selector of a method that provides a collection of arrays. Each array gathers parameters for a different test case. In our example the method givenValuesAndTheirExpectSum is defined as following:
ExampleOfParameterizedTestCase>>#givenValuesAndTheirExpectSum
^{{1. 2. 3}.
{10. 20. 30}.
{100. 200. 300}}
Since we have three arrays of parameters, we will have 3 different test cases all three with the same test selector, but each with a different parameters array. This is displayed by the test runner as shown in picture 1.
Picture 1: Passing Parametrized Test
If any of the parameters arrays leads to a test failure, the Test Runner will display the failing test selector as well as the parameters that lead to the defect. For demo purpose, let’s introduce some invalid parameters and change the previous givenValuesAndTheirExpectSum method as following:
ExampleOfParameterizedTestCase>>#givenValuesAndTheirExpectSum
^{{1. 2. 3}.
{10. 2. 30}.
{100. 200. 0}}
I have changed the second and the third parameter arrays. The Test Runner detects indeed 2 failing tests out of 3 runs as shown in picture 2. As you can see the parameters that lead to the defect are displayed so, one can identify the origin of the defect.
Picture 2: Failing Parametrized Test
I have developed and tested parametrized tests under Pharo 2.0. If you want to try it, you can install it by evaluating the following expression in a workspace.
Gofer it
url: ‘http://car.mines-douai.fr/squeaksource/BoTest’;
package: ‘ParameterizedTests’;
load.
It is worth noting that although in the examples I have given above data is hard coded, nothing prevent from adopting an approach as suggested by Frank Shearar in his Squeak Check project. Method that return the array of parameters can rely on any arbitrary complex data generator class, that may produce different data randomly each time tests are run.