Introduction

This is an introduction article to use MsTest as your Test Runner for a simple Selenium introduction. This is a selenium series which will be produced and take readers through 0-100 in hopefully fun articles which also link to source code examples.

Background

This article will run through the very basics of MsTest and Selenium. On top of this, we will touch Shouldly but more indepth articles to come on that. If you have an interest in testing, web testing and learning how to use MsTest, Selenium and Shouldly Assertions, then this is the place to be. In order to execute the tests, you will need the following:

  • Visual Studio 2015 ideally and above
  • C# knowledge
  • Firefox installed, we’ll cover running tests against Internet Explorer, Chrome and Safari in other articles
  • The source code cloned / downloaded from GitHub:
  • The want to go test and break things!

Let’s Get Started!

So you want to know how to use MsTest with Selenium and some Shouldly asserts for our tests, let’s go! This is going to be a basic article to get us going and then Chapter 2 onwards which I plan on producing weekly will become more and more indepth.

So hopefully, the source code is downloaded from the repo provided in the background section or can be downloaded from the Selenium Series attachment on the article and it’s built successfully in Visual Studio. If so, then you will see in the Test Explorer window which can be found in Visual Studio under Test -> Windows -> Test Explorer the below:

Test Explorer

Notice how the tests are ordered by Class, this is because we have 4 test classes in our solution we’re looking at. They are as follows and let’s begin testing!

OurFirstMsTest

These tests offer MsTest setup in a unit test fashion. Since MsTest is going to be what drives our Selenium Tests throughout these chapters until we use Specflow on occasion, I thought it prudent to demostrate some simple set up items on MsTest which I’m running a series on separately. Below shows a simple Person class which has some properties and get methods to be tested. This is found in the Solution under, Code -> Person.cs.

internal class Person
    {
        public int Age { get; set; }
        public string Name { get; set; }
        public int HeightInCm { get; set; }
        public string HairColour { get; set; }
        public int GetAge() => Age;
        public string GetName() => Name;
        public string GetHairColour() => HairColour;
        public int GetHeightInCm() => HeightInCm;
    }

Now the 4 MsTests are found in Tests -> 001_Our_First_MsTest -> OurFirstMsTest.cs which house 4 tests as shown below in the Test Explorer and code snippet of one of the tests named, AgeIs31.

Age31 Test Code below, this shows that the MsTest has a test method named AgeIs31(). The method needs to be decorated with an attribute of [TestMethod] that is how MsTest knows that this is a test, without this, the method is seen by Visual Studio as just a normal working method so very important.

Since tests are always Arranging, Acting and Asserting, I’ve included this in the code broken up as such to understand the stages of the test. Now I understand as written a lot of publications on this about BDD / TDD, etc. and that flow of arrange act and assert but in general, the principle is solid no which layer you test. So the below test creates a new Person object as shown, calls the GetAge method and makes sure that the age of Sean is 31, simple stuff but fundamentals needed to be understood before moving to Selenium given the MsTest Content.

[TestMethod]
public void AgeIs31()
{
    //Arrange
    var person = new Person
    {
         HairColour = "Blonde",
         Age = 31,
         HeightInCm = 183,
         Name = "Sean"
     };

     //Act
     var actualAge = person.GetAge();

     //Assert
     Assert.AreEqual(31, actualAge);
 }

OurFirstShouldlyTest

I’ve mentioned Shouldly and you may ask what that is, in short, it’s a way to assert in expressive English, some refer to it as Fluent assertions.

Shown below are the differences in how MsTest vs Shouldly look in our tests, if you look at the tests and execute them called OurFirstShouldlyTest in the solution, then you can compare which you prefer. Both are excellent, however I feel Shouldly is a little more expressive at times for what we’re doing here.

// MsTest Assertion
   Assert.AreEqual(31, actualAge);

// Shouldly Assertion
   actualAge.ShouldBe(31);

An example Shouldy test, notice the assert, the MsTest Framework is being used which is awesome, but our assertion is a Shouldbe.

[TestMethod]
public void Shouldy_IsCalledSean()
{
    //Arrange
    var person = new Person
    {
        HairColour = "Blonde",
        Age = 31,
        HeightInCm = 183,
        Name = "Sean"
    };

    //Act
    var actualName = person.GetName();

    //Assert
    actualName.ShouldBe("Sean");

UsingTestAttributes

This is a test file containing 3 tests, which have MsTest Attributes on each test method, now what does that mean? That means we can group our tests in logical groupings that make sense to us when we test. Some test Categories you might want to consider are fast, medium and slow running tests. These can be grouped by adding the below to the test methods, see below we have HIGH, MEDIUM and LOW. Also note that we can add many TestCategories or none to a test method.

[TestCategory("HIGH")]
[TestCategory("PERSON-TESTS")]
[TestMethod]
public void Shouldy_IsCalledSean()
{
    //Arrange
    var person = new Person
    {
        HairColour = "Blonde",
        Age = 31,
        HeightInCm = 183,
        Name = "Sean"
    };

    //Act
    var actualName = person.GetName();

    //Assert
    actualName.ShouldBe("Sean");
}

[TestCategory("MEDIUM")]
[TestCategory("PERSON-TESTS")]
[TestMethod]
public void Shouldy_IsCalledSean_CaseInsensitive()
{
    //Arrange
    var person = new Person
    {
        HairColour = "Blonde",
        Age = 31,
        HeightInCm = 183,
        Name = "Sean"
    };

    //Act
    var actualName = person.GetName();

    //Assert
    actualName.ShouldBe("sean", StringCompareShould.IgnoreCase);
}

[TestCategory("LOW")]
[TestCategory("PERSON-TESTS")]
[TestMethod]
public void Shouldly_AgeIsGreaterThan30()
{
    //Arrange
    var person = new Person
    {
        HairColour = "Blonde",
        Age = 31,
        HeightInCm = 183,
        Name = "Sean"
    };

    //Act
    var actualAge = person.GetAge();

    //Assert
    actualAge.ShouldBeGreaterThan(30);
}

You may ask why have them and how can we use them. Let’s look at the Test Explorer, if you right click on it and Group By -> Traits, you should see your tests are all grouped by Category and you can target them neatly and execute them by Category now, pretty cool basic stuff in VS and MsTest. Let’s get the Selenium Tests going now we know the basic Runner in MsTest, framework, traits / categories and structure. Let the Web Driven Tests begin.

Our First Selenium Tests – Let’s Get Going

This is what we’re here for now, getting our first few tests running in Selenium and understanding them. Now we’ve run all the tests in the solution from above and understand MsTest, Categories and how to run the tests. Let’s focus on the tests in the WEB Trait, which are in the test class named OurFirstSeleniumTests.

There are two tests which are as shown below, very simple tests and our starting path to becoming Web Testing Gurus.

[TestCategory("WEB")]
[TestCategory("FAST")]
[TestMethod]
public void VisitTheSeleniumWebsite_CheckTheTitleIsPresent_AndMentionsSelenium()
{
    // Arrange
    var driver = new FirefoxDriver();
    driver.Manage().Window.Maximize();
    driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));

    //Act
    driver.Navigate().GoToUrl("https://www.seleniumhq.org/");

    //Assert
    driver.Title.ShouldNotBeEmpty();
    driver.Title.ShouldBe("Selenium - Web Browser Automation");

    // clean up
    driver.Quit();
}

[TestCategory("WEB")]
[TestCategory("FAST")]
[TestMethod]
public void VisitTheSeleniumWebsite_NavigateTheMenu_ToTheDocumentationPage()
{
    // Arrange
    var driver = new FirefoxDriver();
    driver.Manage().Window.Maximize();
    driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
    driver.Manage().Timeouts().SetPageLoadTimeout(TimeSpan.FromSeconds(10));

    //Act
    driver.Navigate().GoToUrl("https://www.seleniumhq.org/");

    var docMenu = driver.FindElement(By.Id("menu_documentation"));
    docMenu.Click();

    var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5));
    wait.Until(drv => drv.Title.Contains("Documentation"));

    //Assert
    driver.Url.ShouldBe("http://www.seleniumhq.org/docs/");
    driver.Title.ShouldContain("Selenium Documentation");

    // clean up
    driver.Quit();
}

Let’s execute the tests as shown below. Right click, run Selected Tests which is the WEB trait, and the two tests should trigger and you should see them execute and run and pass.

We have our first Selenium Tests running, executing, and passing, so congrats on sticking this far and passing your first tests!!! Logically, the next question if new to Selenium is what’s actually going on? Let’s see…

  1. We need to create what’s called a WebDriver, this is what launches our browser version and maximizes the screen. In this instance, we use FirefoxDriver() which means we must have Firefox installed, otherwise our tests will fail as we can’t communicate with the browser we have specified. We will look at Internet Explorer, Chrome, Edge and Safari in later chapters, but for now we’re using Firefox the default Selenium go to. The below is important as without it, we can’t get going, this is our arrange loosely.
    // Arrange
    var driver = new FirefoxDriver();
    driver.Manage().Window.Maximize();
    driver.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(10));
  2. Let’s go do some stuff as shown below, let’s navigate to the Selenium Website, we do this by passing into our Driver object the URL into the GoToUrl method, pretty straight forward and logical, that’s what I love about Selenium, it’s so logical 99% of the time. We can argue the navigate.
    //Act
    driver.Navigate().GoToUrl("https://www.seleniumhq.org/");
  3. Now we’ve navigated to the page the URL we want to assert we are there, now there are a number of ways to do this. Let’s keep it simple and assert the title is not empty, and also assert the title is called Selenium – Web Browser Automation. If either are untrue, then naturally as we know as developers / testers, this test will fail and report that to use.
    //Assert
    driver.Title.ShouldNotBeEmpty();
    driver.Title.ShouldBe("Selenium - Web Browser Automation");
  4. Finally, where normally on Unit tests we’re finished after the assert, not in integration or web tests, we need to tidy up whether that’s closing connections to a DB or closing down our browser instance. In this case, as we’re UI Testers since we opened the browser, we must close the browser and that’s done in Selenium by calling the Quit() method. Once done, we’ve tested via the UI using Selenium direct and tidied up. Congrats!!
    // clean up
    driver.Quit();

What Next?

Why not create a 3rd test in the solution and do something you want too such as Assert the homepage has a Logo or there is some text present in an element. Other than that if you’ve followed, understood and it’s all good, then I thank you and look forward to moving quicker in Chapters 2 onwards to really get our learning going and our tests growing using Selenium, MsTest and Shouldly.