Add Test Project

Prerequisites:

Background:

Up to this point, we have really just been getting setup and creating a boiler plate web project for the automated tests we will create.  This tutorial is the first where we begin writing and testing code (woot!).  I’ve broken things out step-by-step, so the material is easily digestible.  By the end, you will have completed your first “Hello World!” test project.

Agenda:

  1. Project setup
  2. NuGet Packages
  3. Features and steps
  4. Base classes
  5. Test code

Project Setup:

First we need to create the library project that will host all of our automated tests.  The following steps walk-through the project creation process.

1) Open the MVC web application project we created during an earlier part of this tutorial.  Open the file menu, and select New, and then Project as depicted below.

test_project_add_project

2) The new project dialog will display.  Select Windows Desktop in the tree view on the left.  Select Class Library from the list view on the right.  Name the project RegistrationDemo.Tests as depicted below.

test_project_library_project

3) Visual Studio will automatically create a class named Class1.  We will not be using it, so it can be deleted.  Right-click the file and select delete.  Click OK when prompted to confirm the delete.

test_project_class1_delete

NuGet Packages:

There are several useful libraries that we will leveraging.  We will use Visual Studio’s NuGet Package Manager Console to include them in our project.  The following steps walk through using the package manager console and including the appropriate libraries.

1) To open the package manager console, open the tools menu.  Select NuGet Package Manager, and then Package Manager Console as depicted below.

test_project_pm_console

2) In the console window select RegistrationDemo.Tests as the target project and type Install-Package Baseclass.contrib.SpecFlow.Selenium.NUnit.

test_project_pm_baseclass

3) When the install completes, type Install-Package SpecFlow.Assist.Dynamic.

test_project_pm_specflow

4) The last NuGet package we will need is the Selenium web driver.  Type Install-Package Selenium.WebDriver.

test_project_pm_selenium

Features and Steps:

Now we are ready to begin including our feature and step files, which are at the heart of our ATDD development process.

1) To keep things clean, let’s first create a few folders to hold our various test files and source.  Right-click the test project.  Select Add, and then New Folder.

test_project_new_folder

 2) Type Base for the folder name.  Create three more folders and call them Features, Pages, and Steps – respectively.

test_project_all_folders

3) Now we are ready to add our first SpecFlow feature file.  Right-click the features folder and click Add, and then New Item.

test_project_add_item

4) The dialog below will display.  Select SpecFlow Feature File and name it UserRegistration.feature.

test_project_new_feature

6) Add another item – this time to the Steps folder.  This time select SpecFlow Step Definition and name it UserRegistration.cs.

test_project_new_step

7) Adding the feature file and step definition will auto-generate some code for you.  For now, leave them as-is.  We will come back to them later.  At this point, your test project should build – but its not really doing anything.  Pause a moment, and press CTRL + SHIFT + B to build the project.  If you have any build errors (don’t try to run the test yet) stop now and review your steps.  As a validation, if you open test explorer (on the left) you should see a single test that says “AddTwoNumbers” – this is a default test created within your feature file by SpecFlow.

test_project_build_validation

Base Classes:

We will be coming back to the feature file and step definition shortly.  We are taking a slight detour at this point to put together some boiler-plate base classes.  We will be using the page object and navigation object design patterns.  These are the underlying classes that will do the heavy-lifting of loading an navigating pages for us.

1) Right-click the base folder, and add a new item.  This time we want to add a class.  Name the class CommonBase.

test_project_new_class

2) CommonBase, as the name implies, contains code that will be common among our base classes.  The following lists the source for CommonBase:

2) Add another class and call it PageBase.  The class inherits from the common base class, and contains methods useful for interacting with the web page. The following lists the source for PageBase:

3) Add another class and call it TestFixtureBase.  The class interacts with NUnit to create and dispose the web driver. The following lists the source for TestFixtureBase:

4) Add another class and call it StepsBase.  The class will use be used to keep track of the page we are on and navigating to. The following lists the source for StepsBase:

Test Code:

Boiler-plate code out of the way, we are ready to begin writing our test code.  We will first revisit the feature file we created earlier.  Then we will implement the underlying test methods.

1) For our purposes, we will create two simple tests.  One will test the normal flow of user registration, and the other an error condition (password mismatch).  Open UserRegistration.feature, and replace the default Gherkin with the following:

Notice that I have explicitly specified for the test to be run on Firefox.  You will have install Firefox for the test to work.  Adding additional browser support is really easy, but requires browser drivers.  For clarity and singularity of purpose, I decided to side-stepp additional browser support at this stage.  Not to worry – additional browser support will be covered in a follow-on tutorial.

2) In your feature file, right-click the line that says “Given I am on the Home Page” and then select “Go To Definition.”  A dialog will display as demonstrated below.  Click the yes button.

test_project_binding_source

3) Open your step definition, and replace the class body with the copied text.  Once pasted, your step definition should look like this:

4) Create a new class in the Pages folder and call it IndexPage.  This class contains the requisite source for our test implementation.  For now, the class really only needs to identify itself.  Add two properties for the URL and title of the page.

You may be asking yourself, where did the title text come from?  Is it arbitrary?  Does it really mean anything?  I’m glad you asked.  It’s not arbitrary, and the answer comes in two parts.  First, there is the _Layout.cshtml, which is shared among the pages in the application.  You can search the code base for the following text to find it: “<title>@ViewBag.Title – My ASP.NET Application</title>”.  Second, there is the page .cshtml itself, which defines the following: ViewBag.Title = “Home Page”.  The two join to become the default title for our index page.

Press CTRL + SHIFT + B to build your project.  Take a moment to go back and look at the UserRegistration.feature file.  Notice the line where we started a moment ago, “Given I am on the home page.”  Do you see that the line is now black (versus the purple lines just below)?  The development environment has recognized that the step has been implemented.

We still have a way to go before our tests are ready to run, but I like to pause and celebrate our successes along the way.  Good job!

5) We previously created PageBase as a partial class.  We are now going to fill in some additional details that we need as part of that base class.  Specifically, we need some navigation methods.  In the base folder, create another class and call it PageBase.Navigation.

Note the BaseUrl property is calling the application configuration manager to obtain settings.  Is that going to auto-magically work?  Nope!  Let’s set things up so they work.  Right-click the RegistrationDemo project and select “Properties.”  Select the “Web” option on the left, and note the address and port of the web application (http://localhost:56126/ in my case).  Copy the Project Url to the clipboard by pressing CTRL + C.

test_project_app_settings

Open app.config in the RegistrationDemo.Tests project.  Search for the “seleniumBaseUrl property and paste the url by pressing CTRL + V.

test_project_app_config

6) We are now ready to complete our step definition.  Open UserRegistration.cs and implement the call that will navigate the browser to the index page.  Once complete, your step definition should look like this:

Press CTRL + SHIFT + B to build your project, and ensure there are no errors.  Go back and review your steps before proceeding if your build does not complete successfully.

7) Having taken time walking through our first implementation, let’s speed things up a bit.  Go back to the UserRegistration.feature file.  Implement stub methods for each of the statements, by right clicking it, selecting Go To Definition, clicking yes to copy the source, and then pasting it into the step definition source module.  Review steps one, two and three within this section if you need a refresher.  When you’ve completed your task, you step definition file – with all of the stub methods – should appear as follows:

 8) Our feature has been defined, the steps have been stubbed out, and our next step is to implement the underlying test source.  In the upcoming steps we will go through each of the stubs and implement them in turn.  First up … let’s develop the implementation for the “Given I am not logged in” test step.  Within the IndexPage class we need a method for determining if we are logged in or not.  Since the application under test will toggle the login link to logout when logged in, we can use that link as our identifier.  Add the following methods to the IndexPage class:

Now all we have to do is call our check for login from the our step definition class.  Update the following method within UserRegistration.cs:

So that it makes a call to the new method within the  IndexPage class as follows:

9) We can now identify the index page, and whether or not we are logged in.  Our next step (in this scenario) is to register a new user.  For this step we simply click the register link.  Add the following to the IndexPage class:

Then add the corresponding call to the step definition:

If you press CTRL + SHIFT + B at this point, you will notice the build is broken.  Now why is that?  If you look closely, you will see the ClickRegisterLink() returns a type we have yet to define.  As with our IndexPage calls, RegistrationPage contains the requisite source for implementing registration page tests.  Let’s create that class now.  From the solution explorer, right click the pages folder and select add class.  RegistrationPage should inherit from PageBase.  Will will be making changes to the class definition shortly, but in it’s initial form your source should look something like the following:

10) For the purposes of our test scenario, we should now be on the application’s registration page.  We can now populate the page with the data specified from our test scenario.  Add the following methods to the the RegistrationPage class:

To the step definition, we can now add calls to the underlying implementation methods:

11) With the form data populated, the next step is to simply click the submit button.  To RegistrationPage.cs we add the following:

And to UserRegistration.cs we add:

12) We now validate we are on the home page by adding the following to our step definition class:

13) Finishing out the final step for our first test scenario, we call the check for Logout that we had previously created within the RegistrationPage class.  Update UserRegistration.cs with the following:

14) Our final step is to fill in the details for our error case test scenario.  In this case, we have already done the hard work in our page base class.  All that remains is to add the following to our step definition:

Notice none of the prior steps had to be re-written for the second test scenario.  SpecFlow has done the heavy lifting by calling the appropriate methods!

This section is complete now !