Coding The Automation Steps: Module Overview
Coding The Automation Steps: Module Overview
Module Overview
Hi welcome back to module 3. In this module we'll be learning how the steps in a scenario bind to the
C# methods where we can actually perform our automation. In this module we'll learn about the
relevant NuGet packages that we need to install to utilize NUnits in SpecFlow. We'll look at two different
styles of binding step definitions to scenario steps and we'll see how we can set a default step definition
style when we generate our step definition files. We'll see what happens when we add a new step and
when we delete an existing step. We'll see how we can execute scenarios and debug individual step
definitions. We'll see how we can share step definitions between scenarios and how we can use
learn how when using a data table in a step how the data is passed through to the step definition and
our code. And we'll look at how scenario outline steps map to step definitions. Finally we'll look at how
we share scenario context and data between the individual steps that make up a scenario.
So the first thing we need to do is install the relevant NuGet packages. So we've already got the
SpecFlow extension installed and enabled. And now we have to add in the NuGet packages that we
need. So if we just do a search for SpecFlow we can see that we get a number of results. So if we look
at this SpecFlow NUnit package we can see that this depends on the SpecFlow package and the NUnit
package. So by installing this one SpecFlow. NUnit package we'll get everything we need to start writing
our automation. If we look at our installed packages we can see now that we've got NUnit and this is
the testing framework we'll be using in our automation. We then have the SpecFlow NUnit and the
SpecFlow itself package. So all of these packages combined with the extension that we've already
1
Step Definition Binding
Now we have our NuGet packages installed and we've written our first Feature file with our first
Scenario. We now need to create the automation for each of the steps within the Scenario. So notice
here that each of these steps is highlighted in purple and this indicates that there's currently no
automation set up for these steps. When we're working with SpecFlow and Gherkin we need a way to
there's a concept of binding. Binding is essentially the hooking up of individual steps to individual pieces
of automation code. And we can see in the Test Explorer here that we don't currently have any tests in
our solution. If we take a look at our Solution Explorer we can see we have our. feature file here and if
we expand this down we can see we have this generated C# file. If we have a look at this we can see
that it's designer generated code and ordinarily we wouldn't change any of this. This code
essentially hooks up our natural language sentences to the SpecFlow framework and the
underlying unit testing framework that we're using. So in this case it's NUnit. And we can see NUnit in
use in this generated code through these attributes, but we don't need to worry too much about
this generated code. So now we need to create a class that contains methods that map to each of
these scenario steps. To do this we right-click and we head down to Generate Step Definitions. When
we open this dialog we're given the choice to select which steps we want to generate step definitions
for. So we're just going to leave this as all of them ticked, we get to choose the class name that we
want to generate, and we have a number of options for the style of binding. So by default it's this
Regular expressions in attributes style. And we'll come back to this in just a moment. For now I'm
just going to click Generate and I'm just going to leave the file name the same. If we have a look in our
Solution Explorer now we can see we've got our new class file. If we have a look at this we can see
that it contains methods for each of our steps in our scenario. So the first
open, The mouth is open and notice here that this is mapped to the conceptual Given phase. We don't
have a separate and attribute and the same is true for the but attribute. The braces aren't damaged
2
appears as a Then attribute and also notice now that in our Feature file the steps have changed from
purple to white. And this indicates that there's a binding between the natural language and some code.
notice that this step has reverted back to purple. And that's because no binding is available for this step.
So let's go ahead and remove this step definitions file and everything goes back to purple and we'll
right-click again, choose Generate Step Definitions, but this time we'll choose from the style dropdown
the Method name underscores option. If we click Generate now just OK the file name head back to
Solution Explorer and to our step definitions and this time we can see a different style here. The
attributes are now simply Given, When, or Then and the method name has been generated using
underscores between each word. Let's go back to the original style, (Typing) so this is the default
Regular expressions in attributes style (Typing) and notice here that we've got our text specified in the
attribute itself as well as in the method name and again in the actual original scenario step. So say
we change one of these steps, let's change the When the back teeth are brushed step and we'll change
this to read When all the back teeth are brushed. And immediately this changes to purple to indicate
that there's no matching step definition that can be bound to. So to restore this binding we head back to
our step definitions file and we can just change the attribute value here When all the back teeth are
brushed, Save this. And head back to our Feature file. Notice now that this step has gone from purple
back to white. Because the binding between this scenario step and the step definition has been
restored. And in this case it's because we're using the regular expression style, but notice here the
method name we haven't changed. And that's because it's the text in here that creates the binding. We
could actually name this method anything. So when we're working with the regular expression style it's
possible for the actual method name to quickly become out of sync with the actual binding and original
step text. And of course we could change this manually, but this can create some maintenance
overhead. So let's see what happens in this scenario if we use the underscore style. So I'll just
close this and we'll go and delete it and we'll regenerate these step definitions and this time we'll choose
the underscore style as before and hit Generate. And hit Save. So this time we don't have any text in
3
our attributes and the method names include underscores. And if we go back to our Feature file
everything is white which means we have matching step definitions for each of these steps. So let's
change this back to just when the back teeth are brushed. Again we notice it goes purple and to fix this
we head back but rather than having to change a string into the attribute and also the method name.
We can just change the method name now. So here we can remove the all, we Save this, head back to
our Feature file. And now the mapping has been restored and the step has changed back to white. So
we'll be using the method name underscore style for the rest of this course.
We can specify the default style of binding by changing the app config. So by default when we hit
default we can open the app. config and we can add an additional line in the SpecFlow section. So here
we've added this trace element and we've set the step definition skeleton style to use method name
underscores. And if you want to know more about this configuration head to this link here. And this will
take you to the SpecFlow documentation. So now we've specified our Method name underscore to be
the default format, if we hit Save and we just get a warning here and SpecFlow's offering to regenerate
our feature files if required, so let's just hit Yes for now. And let's head back to our Feature and now
when we choose Generate Step Definitions we can see that the style now defaults to Method
a third option to use Method name Pascal case instead of underscores, but again we're going to stick to
Let's take a look at what happens now when we add a new step to our scenario. So here we've got our
scenario and we've got our step definitions. So let's go and change this and let's just add an extra And
to the Given section. So it goes purple, so it means we need a step definition for this scenario step. So if
4
we go and right-click and choose Generate Step Definitions as before we only get the choice of one
because this is the only one that's not bound to a step definition. If we click Generate and we'll keep this
as BrushingOfTeethSteps. cs we get a warning that we're overriding it and if we click Yes and just hit
Yes because this is open in Visual Studio. If we go and have a look at our steps file now we can see
that we've only got one step definition. And if we look in the Feature all of the other lines have turned
purple. And that's because we've overridden the previous step definitions file and now it only
contains this step. So how do we add a new step definition? Well let's reset this, we'll delete this file,
we'll comment out this extra line for a moment and we'll go and generate everything again. Hit Save.
And now we can see our original step definitions. So let's uncomment this line. So we need to create an
individual step definition for this line. And we'll add it to our existing step definitions. So to do this we
head back to our Scenario, go to Generate Step Definitions, again we only get a single choice, but this
time instead of choosing Generate we'll choose Copy methods to clipboard. Now if we go back to our
step definitions we can paste what we've just copied to the clipboard. So here we can see our x_y_z
line in our step definitions now. And if we head back we can see that once we save this step definitions
file our line goes back to white. So that's how we can add a new step definition when we add a new
Deleting Steps
If we want to completely remove a scenario step we simply delete it from the scenario, so we've just
removed the x_y_z step and we can just hit Save and that's all we really have to do. However,
there's also the matching step definition and if we leave this here it won't cause any problems, but we
have to be careful that we don't create a maintenance problem in the future. So assuming this
step definition isn't shared with multiple scenarios, and we'll have a look at this concept later in the
module, we can simply go ahead and delete the step definition. One small tip is that when we're
deleting or editing a scenario step if we're working with a lot of scenarios and features, we can use a
5
delete And the front teeth are brushed, we could first right-click and choose Go To Step Definition. This
will then open the step definition file in the right place. So we can just delete the step definition, head
So once we've got our scenarios and our step definitions how do we actually execute our scenarios and
kickoff the test automation? The first thing to check is that if you haven't already got it installed in
Extensions and Updates you need to check that you've got the NUnit test adaptor for Visual Studio
installed. Because we're using NUnit as our underlying framework and we're using the Visual Studio
Test Explorer we need to install that extension in order for Visual Studios Test Explorer to understand
NUnit. So to run a scenario we can simply right-click on it and choose either Run SpecFlow Scenarios
or Debug SpecFlow Scenarios. Let's hit Run. If we have a look at our test output for the
successful brushing scenario we can see that we get a message telling us that one or more
step definitions are not implemented yet, but we have actually generated our step definitions here. The
reason we're getting this message is because when we generate the step definitions the generation
adds the ScenarioContext. Current. Pending line. And this instructs SpecFlow that although we've
generated our step definitions we haven't actually implemented any code in them just yet. If we needed
to debug one of these step definitions we simply place a breakpoint in the step definition and we
can right-click and choose Debug SpecFlow Scenarios instead of Run Scenarios. So let's click this and
definition. In addition to right-clicking on the scenario and running it from there we can also use the
Test Explorer to search for specific scenarios to execute. So here we've just got one scenario, but we
could run it by right-clicking and hitting Run or Debug Selected Tests. So that's how we can execute a
scenario by either right-clicking inside the Feature file or by using the Visual Studio Test Explorer to
6
Sharing step Definitions
Our step definitions can be shared between multiple scenarios. So here we've got our successful
brushing scenario and all of the steps have matching step definitions. So let's go and add another
scenario. So notice here that the When x and then z lines are showing as purple because they don't
have any matching step definitions, but this given line There is toothpaste on the brush is showing as
white. Even though for this new scenario we haven't generated any steps. And that's because
there's already a step definition for this Given step. So if we right-click and choose Go To Step
Definition we can see that there is in fact a step definition for this line. If we navigate to the Given in
the first scenario we can see that it goes to the same place. So this Given step definition currently will
execute for both this scenario step and this scenario step. This sharing of matching step
definitions means that we can make use of code reuse in our automation steps, but this does, however,
mean that when we're changing step definitions we just have to be aware that if they're shared they will
say we had this scenario here and we want to modify it to specify the amount of toothpaste on
the brush. So let's say here Given there is 1 gram of toothpaste on the brush, so we need to go and
this and just double-check that it's gone white. And let's say now that we also want another scenario
with 2 grams of toothpaste. So let's take a copy of this and let's just call it Successful brushing 2. And
we'll change this to 2 grams of toothpaste on the brush. So we can go and copy this step definition and
change this to 2 grams. Again we'll Save it and just double-check here that everything's okay, which it
is. So now we've got two scenarios where the only difference is in this Given line. So although all of
these step definitions will be reused, we've got two step definitions for these Givens that only differ in
the data, ie the number of grams of toothpaste that's on the brush. So here in our step definitions we've
7
got two steps that when we come to write the actual automation will be extremely similar. So we can
reduce this code duplication in our step definitions by making use of parameterization in our
step definitions. So let's go and delete these two Given step definitions. Hit Save and head back and
notice now that we've got our two Givens that are not bound. If we right-click and go to Generate
Step Definitions we can get a preview, but notice that in this preview it's only going to generate a single
Given for the two selected Givens that we've specified here. So let's just close this preview and Copy
the methods to the clipboard and head back to our step definitions and let's just paste this in. So we've
only pasted in one Given, if we Save it and head back to the Feature notice now that both of our Givens
have turned white. Also the number in these Givens has changed to an italicized grayed out color. So
why is this? Well if we have a look at the generated step definition we can see now that in place of the
actual number of grams we have this P0, we also have a parameter that's now been added to our step
definition, also called p0. So let's go and put a breakpoint here and let's debug our first successful
brushing scenario. And our breakpoint gets hit and if we have a look at the value of this parameter we
can see that it's a 1 representing the 1 gram from our scenario step. If we stop this and instead
debug successful brushing 2 once our breakpoint gets hit we can have a look at our parameter value
and this time we've got the number 2 to represent 2 grams from the second scenario. So in this way
to we can go and rename this parameter so let's call it grams of toothpaste, or just grams. If we debug
this now we can see that we get our value for grams of toothpaste and we can also improve the
readability of the step by replacing this P0 with something more meaningful. To do this we just
specify something in capital letters. So let's just call it GRAMS. Again if we debug this we can see that
we get our grams of toothpaste. If we go and change the values in the Feature, so let's say 11 and
22, and just choose one of these to debug notice now that we get our new value for grams. So that's
how we can use parameterized step definitions to reduce the code duplication in our step definitions
where we have the same basic step definition but it only varies by data values.
numbers. So let's change this Given and we'll add two parameters. So again we'll add so many grams
of toothpaste and we'll also add another parameter to specify the brand of toothpaste. So let's just make
up a brand called Brand X. So Given there is 2 grams of Brand X toothpaste on the brush. So we can
go and edit our step definition now. So Given_there_is, (Typing) and again we use upper case to
now have to add the method parameters. So the first one is a number, so we'll say int grams to match
the uppercase grams here and also we'll add a string parameter called brand to match the brand
parameter here. And these parameters in the method definition have to be in the same order as they
appear in the method name. Hence we've got GRAMS and grams first and BRAND and brand second.
If we Save this and head back to our Feature we now see that our Given step has gone back to white
and now we've got two parameters signified by the italics and the gray 2 and Brand X. So let's debug
this and we'll see what parameters we get passed. So let's go across here to our parameters and
for grams we can see we've got 2 and for brand we've got Brand X. We can go here and change this to
say 22 and Brand Y, debug the test again check our parameters and we have 22 grams and Brand Y.
We saw in the previous module how we can specify data tables in Gherkin. So here in this Given step
we've specified a data table containing two columns, ToolName and ToolQuality, and we have three
data rows within the table. So how do we access these data items in our step definition? If we look at
our step definition here we can see that we've got this parameter of type table and this is a SpecFlow
table class. And we can use this table object to get at the table data in our step definition here. So to get
the firstToolName here we're using indexes, so we're saying the first row and the first column in the first
row. And here we're saying again the first row, but the second column. As well as using indexes for
the columns we can also specify the name of the column. So here we're saying the secondToolName is
at row 1, these being 0 based indexes. And the column is called ToolName. The secondToolQuality
9
again we're on the second row in the table, and we're looking for the column called ToolQuality. There's
a couple of other methods on this table object to do things such as rename columns and there's
also the useful ContainsColumn method which we can use to test for the existence of a column with a
specified name. So here we're saying does the table contain a column called Color, which it doesn't.
So let's go ahead and debug this test and we'll have a look at this table structure. So we have access to
a collection of Headers, so if we expand this we can see we've got the headers or the columns
of ToolName and ToolQuality. And we also have this Rows property and we can drill down into this, see
each of the table row objects. Each table row object has a collection of keys and values and again
we can just expand this down and we can see we've got ToolName paste and ToolQuality medium. So
let's have a look at our variables here. The first ToolName we've got paste and Quality medium, so this
maps to paste and medium here. And the second ToolName of brush and the second ToolQuality of
high, so again this maps to brush and high. If we look at our IsToolColorColumnSpecified we can see
that we've got false as expected. So that's how we can specify a data table in Gherkin for a Given step
and how we can access the rows and columns by adding a table parameter to our step definition.
So let's take a look at scenario outlines in use. So here we've got our scenario outline from module 2,
we have three parameters, brand, mins, and percent and these map to the columns here. So
notice we've got these quote marks around our string type and these other things are numbers. So let's
go ahead and generate our step definitions, but this time I'm going to start with the Regular
expression style and we'll see why in a just a moment. So let's generate this and let's go and have a
look at our step definitions. So notice that we're using the Regular expression style and for our Given
step for our string it's added our string parameter as expected. So we can put a breakpoint here and we
can debug one of these tests and if we look at our parameter 0 we can see that we get Brand X as
expected. So let's delete these step definitions and let's now generate them using the Method name
underscores style. Let's go and look at our step definitions now so we're not using the
10
Regular expression style this time. And let's do the same as before, add a breakpoint and then debug
the test. And let's have a look at our parameter value again, but notice this time we've got this additional
quote. We can see that we've got Brand X followed by this quote, which is clearly wrong. So we'll Close
this and stop debugging and let's go back to our Features. And we have a hint here that something is
not quite right. The opening quote is white but the closing quote is gray. When we're not choosing the
Regular expression style we need to remove these quotes. If we debug the test again and check our
string parameter now we can see that we've got Brand X without the additional quote. If we look at our
Feature file we can see that we don't have any gray items now, so this is a hint to us that everything is
as expected. And as with parameters before we can go and make this a bit more readable. We change
this to Brand and the corresponding parameter also to Brand and we could do the same things for these
for this first example in the scenario outline we have our Brand X, if we debug the next one we have our
Brand Y, and if we debug the final one we get our Brand Z. So that's how we can map scenario outline
Because in SpecFlow each of the individual steps in a scenario map to a separate method in our step
definitions sometimes we need to be able to pass data between individual step definitions. One way
we can do this is to use the ScenarioContext. Current and we can use this as a dictionary to add keys
and values to the currently executing scenario context. So when each scenario executes we get a
new scenario context and we can add things to it. So here the key is brand name and the value that
we're storing is the brand that's passed through as a parameter. The next step that gets executed is this
When I brush for so many minutes step. And even though this is a separately executing step we can
retrieve the brand name from the scenario context by specifying as an indexer the key that we added
here. So let's see this in action. We'll debug this test and if we check our brandName variable we can
see that we got Brand X that we stored in the previous step. And we can see this for the other tests.
11
This time Brand Y was stored. If all our step definitions exist in the same class instead of using the
scenario context we can create private fields. So here we could simply create a field and rather than
use the scenario context we could simply say that we're setting the internal field to the value of this
parameter passed in in this step. And then we could simply use this underscore brand field in this step
here. So just to illustrate, if we run this now we can see that our brand field in the class is set to Brand
Y. So this private field approach is fine if all our steps are within the same class, but because matching
step definitions don't have to be all in the same class, so a scenario could have two steps. One
step could be bound to a step definition in one class and another to a step definition in a different class
we can't always use this approach. And that's when storing things in ScenarioContext. Current is more
flexible.
Module Summary
So that brings us to the end of module 3. In this module we learned how to install the relevant NuGet
packages to get NUnit and SpecFlow working together. We saw the regular expression style of binding
and the method underscore style of binding. We learned how to change the app config to change the
default step definition style. We saw what happens when we add and delete steps. And we saw how we
can execute scenarios and debug individual steps within those scenarios. We saw how a step definition
can be shared between multiple scenarios and how we can parameterize step definitions so we can
reuse them. We saw how to access the data items in a data table when we pass it to a step definition.
And we also saw how when we're using data driven scenario outlines how the data maps to our step
definition parameters. And finally we learned a couple of methods of sharing data between scenario
steps.
12