I have updated SpecSalad and also at last pushed it up to the Nuget gallery, when it is installed, it also installs SpecFlow and NUnit, along with adding a reference to the spec salad dll in the step assemblies node of the application config, so it is ready for use.
SpecSalad is a c# implementation of the RiverGlide CukeSalad framework, which is designed to eliminate monolithic step definition class files associated with the standard spec flow style of development. In many projects there comes a point where finding the way around the various step definitions is done more on experience of where the actual method is within the file rather than any specific layout or pattern! Spec Salad uses Roles and Tasks present an easy and descriptive layout, that makes moving between the feature text, test code and implementation easier.
How does the framework look in a solution? Inspired by the great RSpec Book lets make the game code-breaker! to show the framework in action.
I have uploaded the code to GitHub, The important part to aid navigation is the layout of the test project, in this I create folders that will contain features, roles and the tasks.
I start with the features, these define what I am trying to do, and provide me with a simple definition of what done will look like.
They look like fairly standard SpecFlow features, which they are, only the syntax of each of the scenario steps is important to the spec salad framework.
The currently allowable syntax is
Given [I am | you are] a <role>
Given [I | you] [attempt to | was able to | were able to | did] <task>[: | ,] <parameters>
When [I |you] [attempt to | was able to | were able to | did] <task>[: | ,] <parameters>
Then [I | you] should <question> ‘<answer>’
Then [I | you] should <question> that includes: <answer>
Then [I | you] should <question>
Starting with the first feature, which requires that the game displays a title and prompt at start up, running the feature, I get the following error.
The error states I need to create a role or task called ‘codebreaker’, once I have created a class in the roles folder, that inherits from the ApplicationRole base class, and rerun the feature again I get a new error.
the error raised this time requires a role or task called “StartTheGame”, this is the task that the role will carry out.
I created the class in the tasks folder, this class inherits from the ApplicationTask base class, which requires me to implement the PerformAction method, in this method, I tell the role what to do, in this case to start the game.
SpecSalad defines the Role as dynamic, which means that this task will work for any role that implements a StartTheGame method that takes no parameters, so tasks are fully re-useable between different roles.
Because role is stored in the scenario context of SpecFlow any variables set within the role will be preserved throughout the context without any extra work.
The Role now has to implement the StartTheGame method, and do something, in this case create the game class and call its start method
running the test again I get a new failure, stating that I need to create a task ‘SeeTheScreen’
Again this is a task, that is going to tell the role to look at the screen and report what it sees, the task will then send this report to the system, which will compare it against the the expected screen text proposed in the scenario definition.
The system comparer for includes syntax expects an IEnumerable to compare against, which the role method LookAtOutput will return.
The role of cause cannot actually look at the screen, but there are various ways I can mock or stub looking at the standard output, I have chosen what I think is the simplest, an interface that will implement a WriteLine method, and a stub class that implements this interface and stores each message in a collection. This collection can then be returned by our role.
The final code looks like this.
This gives us our first truly failing test
To make this scenario pass I now simply need to write the two expected output lines within the start method.
Running the tests again we now get a pass.
This looks like a good place to break this already very long post, ready to continue next time with the implementation and testing of the submit guess feature.