Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / security

Continuous Delivery with TFS: Creating Automated Web Tests with Selenium

5.00/5 (1 vote)
3 Mar 2015CPOL5 min read 15.3K  
In this blog post (which is part of my series on on implementing continuous delivery with TFS) we look at creating automated web tests with Selenium.

In this blog post (which is part of my series on on implementing continuous delivery with TFS) we look at creating automated web tests with Selenium. Although the need for manual testing will probably never go away any organisation that wants to deploy software on a frequent basis is going to have to automate some if not most of the application testing effort if quality has any hope of being maintained. Clearly, if you want to release your application once a week but it takes two weeks to properly manually test your application you have a big problem, and automation is probably the only sensible answer.

Let’s be clear that test automation is a mammoth subject and not only involves automating the driving of the application but also data setup and teardown and service virtualisation ie stubbing interfaces to external systems. Then there is managing your tests between sprints or projects – when you have 500 or so this is a non-trivial task. I can’t possibly cover the subject properly in a couple of posts and instead my aim is to show you how to begin to create a framework for writing automated tests and crucially how to make them run in the TFS ecosystem. I’ll be using Selenium since it’s used by John Sonmez in his superb Pluralsight course Creating an Automated Testing Framework With Selenium. I thoroughly recommend this course to anyone who is embarking on an automated testing project, and some of the code I use comes directly from John’s course (with his kind permission). If you are using a different automation technology such as CodedUI similar principles will apply. As with many other things in software development there is a quick and dirty way to write automated tests (by recording them which makes them very brittle – think recorded Excel macros) and there is the professional approach where you put the time and effort in to make a much more robust solution. I’ll be using the latter technique although I will only scratch the surface of what’s possible.

Create the Framework

Our simple automation solution will be in two parts, the first of which is a fluent API framework that models the web application’s web pages. To get the ball rolling create a new class library project in the ContosoUniversity solution called ContosoUniversity.Web.SeFramework and complete these steps:

  1. Via NuGet install Selenium WebDriver and Selenium WebDriver Support Classes.
  2. Remove Class1.cs and add a class called Driver.cs. Ensure Driver.cs contains the following code:
    using OpenQA.Selenium;
    using OpenQA.Selenium.Firefox;
    using System;
    using System.Threading;
    
    namespace ContosoUniversity.Web.SeFramework
    {
        public class Driver
        {
            public static IWebDriver Instance { get; set; }
    
            public static string BaseAddress
            {
                get
                {
                    var url = "ALMWEB01/CU-DAT";
    #if DEBUG
                    url = "localhost:0000";
    #endif       
                    return url; }
            }
    
            public static void Initialize()
            {
                Instance = new FirefoxDriver();
                TurnOnWait();
            }
    
            public static void Close()
            {
                Instance.Close();
            }
    
            public static void Wait(TimeSpan timeSpan)
            {
                Thread.Sleep((int)(timeSpan.TotalSeconds * 1000));
            }
    
            public static void NoWait(Action action)
            {
                TurnOffWait();
                action();
                TurnOnWait();
            }
    
            private static void TurnOnWait()
            {
                Instance.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(5));
            }
    
            private static void TurnOffWait()
            {
                Instance.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(0));
            }
        }
    }
  3. Open the properties of ContosoUniversity.Web and from the Web tab find the IIS Express port number. Replace the four zeros in the above code with the port number.
  4. Add a new class called DepartmentsPage.cs and ensure it contains the following code:
    using OpenQA.Selenium;
    using System;
    
    namespace ContosoUniversity.Web.SeFramework
    {
        public class DepartmentsPage
        {
            public static void GoTo()
            {
                Driver.Instance.Navigate().GoToUrl("http://" + Driver.BaseAddress + "/Department");
            }
    
            public static string Name
            {
                get
                {
                    var title = Driver.Instance.FindElement(By.TagName("h2"));
                    if (title != null)
                        return title.Text;
                    return String.Empty;
                }
            }
    
            public static bool DoesDepartmentExistWithName(string name)
            {
                var bodyTag = Driver.Instance.FindElement(By.TagName("body"));
    
                return bodyTag.Text.Contains(name);
            }
        }
    }
  5. Add a new class called NewDepartmentPage.cs and ensure it contains the following code:
    using OpenQA.Selenium;
    using System;
    
    namespace ContosoUniversity.Web.SeFramework
    {
        public class NewDepartmentPage
        {
            public static void GoTo()
            {
                DepartmentsPage.GoTo();
    
                var newDepartment = Driver.Instance.FindElement(By.LinkText("Create New"));
                newDepartment.Click();
            }
    
            public static CreateDepartmentCommand CreateDepartment(string name)
            {
                return new CreateDepartmentCommand(name);
            }
    
            public class CreateDepartmentCommand
            {
                private readonly string _name;
                private decimal _budget;
                private DateTime _startDate;
                private string _administrator;
    
                public CreateDepartmentCommand(string name)
                {
                    _name = name;
                }
    
                public CreateDepartmentCommand WithBudget(decimal budget)
                {
                    _budget = budget;
                    return this;
                }
    
                public CreateDepartmentCommand WithStartDate(DateTime startDate)
                {
                    _startDate = startDate;
                    return this;
                }
    
                public CreateDepartmentCommand WithAdministrator(string administrator)
                {
                    _administrator = administrator;
                    return this;
                }
    
                public void Create()
                {
                    Driver.Instance.FindElement(By.Id("Name")).SendKeys(_name);
                    Driver.Instance.FindElement(By.Id("Budget")).SendKeys(_budget.ToString());
                    Driver.Instance.FindElement(By.Id("StartDate")).SendKeys(_startDate.ToString());
                    Driver.Instance.FindElement(By.Id("InstructorID")).SendKeys(_administrator);
    
                    Driver.Instance.FindElement(By.XPath("//input[@value='Create']")).Click();
                }
            }
        }
    }
Create the Tests

To keep everything in layers we’ll create our tests in a new Unit Test project. We need to use the MSTest framework because (jumping ahead here) Microsoft Test Manager only works with MSTest at the moment. So, add a new Unit Test project called ContosoUniversity.Web.AutoTests and complete these steps:

  1. Create a project reference to ContosoUniversity.Web.SeFramework.
  2. Add a new class called ContosoTest.cs and ensure it contains the following code:
    using ContosoUniversity.Web.SeFramework;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    
    namespace ContosoUniversity.Web.UnitTests
    {
        public class ContosoTest
        {
            [TestInitialize]
            public void Init()
            {
                Driver.Initialize();
            }
    
            [TestCleanup]
            public void Cleanup()
            {
                Driver.Close();
            }
        }
    }
  3. Add a new class called DepartmentTests.cs and ensure it contains the following code:
    using ContosoUniversity.Web.SeFramework;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using System;
    
    namespace ContosoUniversity.Web.UnitTests
    {
        [TestClass]
        public class DepartmentTests : ContosoTest
        {
            [TestMethod]
            public void Can_Navigate_To_Departments()
            {
                DepartmentsPage.GoTo();
                Assert.AreEqual(DepartmentsPage.Name, "Departments");
            }
    
            [TestMethod]
            public void Can_Create_Departmemt()
            {
                var departmentName = Guid.NewGuid().ToString();
    
                NewDepartmentPage.GoTo();
                NewDepartmentPage.CreateDepartment(departmentName)
                    .WithBudget(13000)
                    .WithStartDate(DateTime.Now)
                    .WithAdministrator("Kapoor")
                    .Create();
    
                Assert.IsTrue(DepartmentsPage.DoesDepartmentExistWithName(departmentName));
            }
        }
    }
  4. Build the solution so the tests are found in Test Explorer. Select the Can_Cerate_Department and Can_Navigate_To_Departments tests then add them to a new playlist by right-clicking and selecting Add to Playlist. Save the playlist in the root of ContosoUniversity.Web.AutoTests.
    visual-studio-new-playlist
Running the Tests

In order to run the tests using the code above you’ll need to install FireFox. You can’t just run the tests though because you need to take steps to ensure there is a web server to handle the requests. The technique is to run the solution so the application starts and IIS Express is running (the icon should appear in the System Tray). Then from the Debug menu in Visual Studio select Detach All. This will close the browser that is running the application but will leave IIS Express running. You can now run the tests (make sure you are running in a Debug configuration) and watch Selenium do all the hard work!

What Have we Done Here?

I want to reiterate that this post isn’t meant to be a tutorial on how to write automated tests and you should regard the code as an example of how to get up-and-running quickly rather than being of production-ready quality. Although this isn’t a tutorial some explanation of what’s going on is in order.

In the ContosoUniversity.Web.SeFramework project the Driver class is essentially the link to FireFox and also has some methods (not used here) to help with tricky web pages that take time to do their thing. The DepartmentsPage has a method to navigate to the page that lists all of the departments and a helper property and method for use in Assert statements. The interesting class is NewDepartmentPage since this illustrates the technique for writing code that allows the use of a fluent syntax for writing tests.

In the ContosoUniversity.Web.AutoTests project the ContosoTest class is a base class that contains common functionality (starting and stopping the browser) for actual test classes to inherit. DepartmentTests inherits ContosoTest and uses the fluent API to cause the browser to navigate around the application doing things that we want to test. It’s all very basic but hopefully enough to illustrate the huge potential of this type of testing.

With our automated web tests created we now need to configure the infrastructure and tooling to automate their execution according to a schedule. Watch out for the next instalment when we’ll be doing just that.

Cheers – Graham

The post Continuous Delivery with TFS: Creating Automated Web Tests with Selenium appeared first on Please Release Me.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)