Setting up a Visual Studio project for testing with NUnit and SpecFlow

In this article I am going to run through my currently preferred set up for Specflow and NUnit. I have already added a new Class Library project named DemoProject.Tests to an empty solution.


Step 1. Install SpecFlow extension for Visual Studio

Once the SpecFlow extension is installed you will be able to add SpecFlow items to a project from the Installed Templates list of the Add Item dialog box.

  1. In the Tools menu select Extension and Updates…. This will open the Extensions Manager dialog.
  2. In the dialog choose the Online gallery in the left pane.
  3. In the right pane type specflow in the search box.
  4. In the middle pane find Specflow for Visual Studio 2013 in the results list and click the Download button. If you already have it installed a tick will be displayed instead of a download button.

specflow-visualstudio-extension
The extension will be downloaded.
specflow-download
Click Install to complete the installation.
specflow-install

You will be prompted to restart visual studio.


Step 2. Install NUnitTestAdapter

This step is optional.  I like to run NUnit tests from within the Test Explorer in Visual Studio rather than running the tests using the NUnit external application.  At this moment NUnitTestAdapter is not compatible with NUnit 3.0 so in the following steps I will ensure NUnit 2.6.* is installed.

Open Package Manager Console and run the following command.

Install-Package NunitTestAdapter -version 2.0.0 -projectname DemoProject.Tests

Step 3. Install the Specflow

Open Package Manager Console and run the following command.

Install-Package SpecFlow -ProjectName DemoProject.Tests

The relevant SpecFlow assemblies will now installed in the specified project.


Step 4. Install Specflow.NUnit

If you run this command without the specific version parameter this will install Specflow.NUnit 2.0.0 which includes NUnit 3.0.0.  As I intend using NUnitTestAdapter (currently only compatible with NUnit 2.6.4) I do not want NUnit version 3 installed so I have specified the -version 1.1.1 parameter, this will install Specflow.NUnit 1.1.1 which includes NUnit 2.6.0.

Open Package Manager Console and run the following command.

Install-Package SpecFlow.NUnit -version 1.1.1 -ProjectName DemoProject.Tests

Step 5. Update NUnit Version
Open Package Manager Console and run the following command.

Install-Package NUnit -version 2.6.4 -ProjectName DemoProject.Tests

This will have updated the NUnit version from 2.6.0 to 2.6.4.


For additional information see the following links:
http://www.specflow.org/resources/
http://www.specflow.org/getting-started/
http://www.specflow.org/documentation/Install-IDE-Integration/
http://ralucasuditu-softwaretesting.blogspot.co.uk/2015/06/write-your-first-test-with-specflow-and.html

How Disabled and ReadOnly State Affect Postback of Textboxes In ASP.Net

There are certain scenarios where Textbox webcontrols will not post the Text value enter by the user back to the server. To understand these scenarios I created the following form consisting of 4 textboxes. On the first textbox (ReadOnlyTextBox) I set the ReadOnly property to true using the properties window. On the second textbox (DisabledTextBox) I set the enabled property to false using the properties window. On the next two textboxes I did not set the ReadOnly or Eanbled properties, but I did add attributes via C# code in the Form_Load event as will be highlighted later. Here is the complete form.

 
<p>
    <asp:TextBox ID="ReadOnlyTextBox" ClientIDMode="Static" runat="server" ReadOnly="True"></asp:TextBox>
</p>
<p>
    <asp:TextBox ID="DisabledTextBox" ClientIDMode="Static" runat="server" Enabled="False"></asp:TextBox>
</p>
<p>
    <asp:TextBox ID="ReadOnlyByAttributeTextBox" ClientIDMode="Static" runat="server"></asp:TextBox>
</p>
<p>
    <asp:TextBox ID="DisabledByAttributeTextBox" ClientIDMode="Static" runat="server"></asp:TextBox>
</p>
<p>
    <asp:Button ID="SubmitButton" runat="server" OnClick="SubmitButton_Click" Text="Submit" /> 
    <asp:Button ID="ClearButton" runat="server" Text="Clear Fields" OnClick="ClearButton_Click" />
</p>
<p>
    <asp:Button ID="PopulateFieldsButton" runat="server" Text="Populate Fields (ServerSide)" OnClick="PopulateFieldsButton_Click" />
    <input type="button" value="Populate Fields (ClientSide)" onclick="Populate();" />
</p>
<asp:Literal ID="OutputDisplay" runat="server"></asp:Literal>

I also added a basic javascript function to the page to set the Text value of the 4 text boxes for comparing the difference in postback results when the textboxes are populated via server side code or client side code.

<script type="text/javascript">
    function Populate() {
        var readOnly = document.getElementById("ReadOnlyTextBox");
        var disabled = document.getElementById("DisabledTextBox");
        var readOnly2 = document.getElementById("ReadOnlyByAttributeTextBox");
        var disabled2 = document.getElementById("DisabledByAttributeTextBox");

        readOnly.value = "ReadOnly By Property";
        disabled.value = "Disabled By Property";
        readOnly2.value = "ReadOnly By Atribute";
        disabled2.value = "Disabled By Attribute";
    }
</script>

Here is the C# code for the ASP.NET page. In the Page_Load event the readonly and disabled attributes are set for the relevant two textboxes. When the form is submitted the values of the tesxtboxes are read and displayed in a Literal webcontrol. There is also a PopulateFieldsButton_Click event to populate the tesxtboxes from server side.

protected void Page_Load(object sender, EventArgs e)
{
    ReadOnlyByAttributeTextBox.Attributes.Add("readonly", "readonly");
    DisabledByAttributeTextBox.Attributes.Add("disabled", "disabled");

	// uncomment below to compare effect of populating TextBoxes in form load at server side
    //SetTextBoxes();
}
      
protected void SubmitButton_Click(object sender, EventArgs e)
{
    var output = new StringBuilder();
    output.Append("Posted Values<br/>");
    output.AppendFormat("ReadOnly By Property TextBox: {0}<br/>", ReadOnlyTextBox.Text);
    output.AppendFormat("Disabled By Property TextBox: {0}<br/>", DisabledTextBox.Text);
    output.AppendFormat("ReadOnly By Attribute TextBox: {0}<br/>", ReadOnlyByAttributeTextBox.Text);
    output.AppendFormat("Disabled By Attribute TextBox: {0}<br/>", DisabledByAttributeTextBox.Text);
    OutputDisplay.Text = output.ToString();
}

protected void PopulateFieldsButton_Click(object sender, EventArgs e)
{
    SetTextBoxes();
}

protected void ClearButton_Click(object sender, EventArgs e)
{
    DisabledTextBox.Text = String.Empty;
    ReadOnlyTextBox.Text = String.Empty;
    ReadOnlyByAttributeTextBox.Text = String.Empty;
    DisabledByAttributeTextBox.Text = String.Empty;
}

private void SetTextBoxes()
{
    ReadOnlyTextBox.Text = "ReadOnly By Property";
    DisabledTextBox.Text = "Disabled By Property";
    ReadOnlyByAttributeTextBox.Text = "ReadOnly By Attribute";
    DisabledByAttributeTextBox.Text = "Disabled By Attribute";
}

On to the tests.
Test 1 – Populate server side.

  • Ensure the fields are empty by clicking the Clear Fields button
  • Click the Populate Fields (ServerSide)
  • Click the Submit Button

The results show the Text value was posted back to all except the textbox with the disabled attribute set by C# code.

ReadOnly By Property TextBox: ReadOnly By Property
Disabled By Property TextBox: Disabled By Property
ReadOnly By Attribute TextBox: ReadOnly By Attribute
Disabled By Attribute TextBox: 

Test 2 – Populate client side

  • Ensure the fields are empty by clicking the Clear Fields button
  • Click the Populate Fields (ClientSide)
  • Click the Submit Button

The results show the Text value was posted back to the server only on the textbox with the readoly attribute set by C# code.

ReadOnly By Property TextBox: 
Disabled By Property TextBox: 
ReadOnly By Attribute TextBox: ReadOnly By Atribute
Disabled By Attribute TextBox: 

So, if you want the Text value of the textbox to be posted to the server and you do not want the user to modify the contents of the textbox use C# code to set the ReadOnly attribute.