Testing your web application with Selenium and MTM (part 1)

*Moved to: http://fluentbytes.com/testing-your-web-application-with-selenium-and-mtm-part-1/

For a project I currently work for, we have the requirement to test the user interface on multiple browsers. In the past we have used Microsoft CodedUI many times to setup automated testing, but the fact that we must test multiple browsers (Chrome, Firefox and IE) made us switch to use Selenium instead of CodedUI.

In a series of posts I will guide you through some of the steps I took to make Selenium and MTM work together so we now have automated reports on our tests using Selenium in stead of CodedUI.

In this first part, I will help you get started with Selenium and writing a automated UI Test using the Microsoft Test framework unit test that we later relate to a MTM test case in one of the follow-up posts. the final end result will be a series of fully automated tests that can be run from MTM and providing us with all the data and reports that we use in our projects to track progress on our test effort.

Getting Started

First of all you need to get started with selenium. selenium is a plug-in in the Firefox browser, so you need to install Firefox to get anything done in the first place 🙂

Next you need to get selenium Firefox plug-in, found here:http://release.seleniumhq.org/selenium-ide/1.9.0/selenium-ide-1.9.0.xpi 

Next you can start the selenium IDE using the Firefox main menu->web developer

imageThe Selenium IDE can be used to record your tests and generate boilerplate code that you can use to build your test object model from. (more on that later)

imageThe IDE keeps track of which pages you surf and which elements you interact with, so it can simulate this later in playback mode.  For the purpose of this blog post I use the default ASP.NET MVC website so you can replay the scenario yourself in your environment.

Scenario to automate

The scenario I will automate contains the following steps:

  1. Register as a new user on the default ASP.NET generated website
  2. Logoff using the logoff link
  3. Login again as the user that just registered

First we start with recording these steps. To record these steps you need to load your website in the Firefox browser with the selenium IDE active. (the IDE is in record mode by default) Now you will see the IDE is recording your steps and you can use this recording as basis for your tests. the tests show up in the IDE and you can see the commands you execute in the browser and the target elements you use navigating the site. These steps are the basis to create a unit test later. My goal here is to transform the recorded steps to a Microsoft Unit test and add some attributes to it, so it can be driven from MTM in terms of the values used for the test case.

image

To convert these steps to a unit test, we can use the clipboard. For this we need to set the clipboard format in the Selenium IDE to “C# / NUNit / WebDriver”, so we can copy the recorded steps and past them in a C# format into a MSTest. See screenshot:

 image

MSTest C# implementation of the recording

Next we create a new Test Project in Visual Studio (2010 or 2012) and in the Test class we add the TestContext Property, which we will use later, to get data back from MTM.

Next we create a test method and there we past our code we got from the clipboard in the Selenium IDE, this will result in the following code fragment:

 public void RegisterAndLoginOnDefaultASPMVCSite()
 {
    driver.Navigate().GoToUrl(baseURL + "/");
    driver.FindElement(By.Id("registerLink")).Click();
    driver.FindElement(By.Id("UserName")).Clear();
    driver.FindElement(By.Id("UserName")).SendKeys("marcelv02");
    driver.FindElement(By.Id("Password")).Clear();
    driver.FindElement(By.Id("Password")).SendKeys("Test123");
    driver.FindElement(By.Id("ConfirmPassword")).Clear();
    driver.FindElement(By.Id("ConfirmPassword")).SendKeys("Test123");
    driver.FindElement(By.CssSelector("input[type="submit"]")).Click();
    driver.FindElement(By.LinkText("Log off")).Click();
    driver.FindElement(By.Id("loginLink")).Click();
    driver.FindElement(By.Id("UserName")).Clear();
    driver.FindElement(By.Id("UserName")).SendKeys("marcelv02");
    driver.FindElement(By.Id("Password")).Clear();
    driver.FindElement(By.Id("Password")).SendKeys("Test123");
    driver.FindElement(By.CssSelector("input[type="submit"]")).Click();
 }

If you look at the pasted code, then you see we need to define a variable of type IWebDriver and call it driver in order to make the code work. One other thing you see is that this code will soon be a mess to maintain. You also see hard coded text strings that will be used to enter the user name and password. We will replace these string later when we feed the data from the MTM test case into the test, we just keep it for now, so that we have a starting point test. In one of the next posts I will address maintainability of this code. Let’s first try to make the test run, by adding the object called driver. Here for you need two things. One a driver that get’s called during the test that drives the web browser and second a language binding to that driver, in our case the C# binding.

You can download the web drivers from the selenium site.
The IE driver can be found here: IEDriverServer_Win32_2.25.3.zip (or any newer version found here: https://code.google.com/p/selenium/downloads/list)
and the Chrome driver can be found here:chromedriver_win_23.0.1240.0.zip  (or any newer version found here: http://code.google.com/p/chromedriver/downloads/list)

I have placed the Executables for the time being on my local drive at lcoation c:tmp, more on that as well in one of the later posts.

Now that we have the driver, we also need the C# assemblies that use the driver, those can be found here: http://www.nuget.org/packages/Selenium.WebDriver

Best is to just import them using the NuGet Package manager and there search for Selenium.Webdriver

After you imported this package using the package manager, you can now add the following Setup and TearDown methods to your test that instantiate the driver. (You must choose which driver you want to use, I use the chrome driver since it is the fastest especial if you look at generating input data)

Setup Method:

IWebDriver driver;
private string baseURL;
[TestInitialize]
public void Setup()
{
    driver = new ChromeDriver(@"c:tmp");
    //use the local host adress for your project here->
    baseURL = "http://localhost:48540";
}

TearDown method:

[TestCleanup]
public void TearDown()
{
    driver.Quit();
}

Now your total test looks as follows:

using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;

namespace SeleniumDemo
{
    [TestClass]
    public class UnitTest1
    {
        public TestContext TestContext
        {
            get { return testContextInstance;}
            set { testContextInstance = value;}
        }
        private TestContext testContextInstance;
        IWebDriver driver;
        private string baseURL;
        [TestInitialize]
        public void Setup()
        {
            driver = new ChromeDriver(@"c:tmp");
            //use the local host adress for your project here->
            baseURL = "http://localhost:48540";
        }
        
        [TestCleanup]
        public void TearDown()
        {
            driver.Quit();
        }

        [TestMethod]
        public void RegisterAndLoginOnDefaultASPMVCSite()
        {
            driver.Navigate().GoToUrl(baseURL + "/");
            driver.FindElement(By.Id("registerLink")).Click();
            driver.FindElement(By.Id("UserName")).Clear();
            driver.FindElement(By.Id("UserName")).SendKeys("marcelv03");
            driver.FindElement(By.Id("Password")).Clear();
            driver.FindElement(By.Id("Password")).SendKeys("Test123");
            driver.FindElement(By.Id("ConfirmPassword")).Clear();
            driver.FindElement(By.Id("ConfirmPassword")).SendKeys("Test123");
            driver.FindElement(By.CssSelector("input[type="submit"]")).Click();
            driver.FindElement(By.LinkText("Log off")).Click();
            driver.FindElement(By.Id("loginLink")).Click();
            driver.FindElement(By.Id("UserName")).Clear();
            driver.FindElement(By.Id("UserName")).SendKeys("marcelv02");
            driver.FindElement(By.Id("Password")).Clear();
            driver.FindElement(By.Id("Password")).SendKeys("Test123");
            driver.FindElement(By.CssSelector("input[type="submit"]")).Click();
        }
    }
}

In order to make this test run successful we need to change the user name text that we send when we create a new user. If we forget to do so, the test will fail on it’s attempt to logout, since it will not be able to add a user twice to the same site.

Now when you run this Unit test, you will see the chrome browser spin up and replay the steps you recorded in the selenium IDE.

In the next few posts I will address, driving the test from MTM using data that comes from the test case specification, Setting up a test environment, so you can run your tests as automated in MTM and last, how to build your tests in such a way that they become maintainable. Here I will use a pattern of specifying the test cases in a BDD style of testing using Given, when, Then and I will break up the classes I build into Pages, Flows and Test cases.

Follow my new blog on http://fluentbytes.com