I while ago I watched a talk by Antoney Marcano at skills matter about a new framework called cukesalad which sits on top of ruby cucumber and allows the test framework to be used without having to write step definitions. The scenarios are defined using a syntax that focuses on the roles and tasks associated with the scenario.
I have been following Antony’s blog and like the way he has been pushing the scenario definitions, as it follows my own thoughts about the position of cucumber within the overall development process, and the writing of the specifications in a generic way that allows the design of the application to follow a more natural course, the scenarios should define the what not the how.
In day to day work I use Specflow, the dot net alternative to Cucumber, so I set about looking at converting the RiverGlide framework into C# to work with Specflow.
There are some changes to the detail. Tasks must inherit from ApplicationTask, which provides access to the current role and the details collection. The role is defined as dynamic, which allows the framework to match any role that has the specified methods to this task, the details collection is made up from the parameters defined in the feature file as a name value collection.
Given I am a Calculating Individual
And I was able to switch on the calculator
When I attempt to add: the number '<first_number>' to the number '<second_number>'
Then I should see the answer '<result>'
- public class Add : ApplicationTask
- {
- public override object Perform_Task()
- {
- Role.Enter(int.Parse(Details.Value_Of("the_number")));
- Role.Press('+');
- Role.Enter(int.Parse(Details.Value_Of("to_the_number")));
- Role.Press('=');
- return null;
- }
- }
Roles must inherit from ApplicationRole, the role defines the implementation of the tasks that the role can carry out.
- public class CalculatingIndividual : ApplicationRole
- {
- TheCalculator _calculator;
- public void Enter(int value)
- {
- _calculator.Enter(value);
- }
- public void Press(char function)
- {
- if (function == '=')
- _calculator.Equals();
- else
- _calculator.Get_Ready_To(function);
- }
- }
Also because the spec salad framework actually contains the step definitions that tie these roles and tasks together, the app config of the test project, must have this additional spec flow child node.
<stepAssembly assembly="SpecSalad" />
</stepAssemblies>
In order to match these predefined step definitions scenarios are written using a subset of the Gherkin language, this subset focuses on the role, and the tasks the role can perform.
Given <I am | you are> a <role>
- Given I am a specified role
And <I | you> <attempt to | was able to | were able to | did> <a task>:<with parameters>
- And I attempt to do the return task: with parameter '2' and parameter '3'
When <I | you> <attempt to | was able to | were able to | did> < a task>:<with parameters>
- When I attempt to do the return task: with parameter '2' and parameter '3'
And <I | you> <attempt to | was able to | were able to | did> < a taks>:<with parameters>
- And I attempt to do the return task: with parameter '2' and parameter '3'
Then <I | you> should <the question> ‘<expected answer>’
- Then I should see the answer '1'
performs an assert are equal between the expected answer and the roles answer to the given question
or
Then <I | you> should <the question> that includes: <expected answer>
- Then I should see the answers that includes: 1
performs an assert contains between the roles answer to the question and the expected content
or
Then <I | you> should <the question>
- Then I should see one
this doesn’t perform any asserts, but simply calls the roles answer method with the given question, it is expected that this method would carry out any required asserts.
You can find the source for this project here, I am hoping to create a Nuget package soon, which will make it easier to include in test projects.