Spec Salad

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.

Scenario Outline: Find the sum of two numbers
    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>'

 

  1. public class Add : ApplicationTask
  2. {
  3.     public override object Perform_Task()
  4.     {
  5.         Role.Enter(int.Parse(Details.Value_Of("the_number")));
  6.         Role.Press('+');
  7.         Role.Enter(int.Parse(Details.Value_Of("to_the_number")));
  8.         Role.Press('=');
  9.  
  10.         return null;
  11.     }
  12. }

Roles must inherit from ApplicationRole, the role defines the implementation of the tasks that the role can carry out.

  1. public class CalculatingIndividual : ApplicationRole
  2. {
  3.     TheCalculator _calculator;
  4.  
  5.     public void Enter(int value)
  6.     {
  7.         _calculator.Enter(value);
  8.     }
  9.  
  10.     public void Press(char function)
  11.     {
  12.         if (function == '=')
  13.             _calculator.Equals();
  14.         else
  15.             _calculator.Get_Ready_To(function);
  16.     }
  17. }

 

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.

    <stepAssemblies>
      <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>

  1. Given I am a specified role

And <I | you> <attempt to | was able to | were able to | did> <a task>:<with parameters>

  1. 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>

  1. 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>

  1. And I attempt to do the return task: with parameter '2' and parameter '3'

Then <I | you> should <the question> ‘<expected answer>’

  1. 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>

  1. 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>

  1. 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.

Advertisements

About Duncan Butler

Trying to be a very agile software developer, working in C# with Specflow, Nunit and Machine Specifications, and in the evening having fun with Ruby and Rails
This entry was posted in Code. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s