Automated UI Testing with Selenium in ASP.NET Core

Automated UI Testing with Selenium in ASP.NET Core

Automated UI testing can be performed with Selenium library. In this tutorial I will perform UI testing of an ASP.NET Core app with Selenium. Selenium supports all the major browsers, for this article I will test only the Chrome browser. This is because writing test for other browsers are exactly similar and you can do that by yourself. The source codes of this tutorial can be downloaded from my GitHub Repository.

Project Setup and Selenium Installation

To create the project setup to perform UI Testing with Selenium, you should have 2 projects in your solution.

  1. An ASP.NET Core 5.0 project.
  2. A Class Library (.NET Core) project which should use .NET 5.0 version. This project will be used for doing UI Testing of the ASP.NET Core project. Install 5 packages from NuGet to this class library project, these packages are:
  1. Selenium.WebDriver
  2. Selenium.Chrome.WebDriver
  3. xunit
  4. xunit.runner.visualstudio
  5. Microsoft.NET.Test.Sdk

The most important thing is that you will need to install the 2 Selenium packages from NuGet to your testing project. These packages are:

  1. Selenium.WebDriver
  2. Selenium.Chrome.WebDriver

In the below image I marked these 2 Selenium packages.

Selenium NuGet Packages
Very important – The Selenium.Chrome.WebDriver version should be the same as of yours Chrome browser, otherwise your UI tests will fail. You can check the version of Selenium.Chrome.WebDriver in the NuGet window of your project. I faced this problem as I was using 85 version of Selenium.Chrome.WebDriver and 87 version of Chrome browser, I fixed it by uninstalling my current chrome browser, then I downloaded the lower version of chrome, which was 85, and installed it.

You will also need to reference the ASP.NET Core project in the Class Library project.

I have named my ASP.NET Core project as MyAppT and named the Class Library (.NET Core) project as UITestingProject.

For any confusion regarding creating the projects simply download the source codes for this tutorial from the link given at the bottom. You can also visit my last tutorial How to perform Unit Testing with xUnit in ASP.NET Core where I explained how to create new projects in a solution for performing testing.
What UI Testing will test ?

The ASP.NET Core Project contains a RegisterControllerwhich performs CRUD operations (Create, Read, Update and Delete of records) to an In-Memory database. Here I will perform the integration testing for the Read & Create actions, there code is shown below.

public async Task<IActionResult> Read()
{
    var rl = await context.ListAsync();
    return View(rl);
}
public IActionResult Create()
{
    return View();
}

[HttpPost]
public async Task<IActionResult> Create(Register register)
{
    if (ModelState.IsValid)
    {
        await context.CreateAsync(register);
        return RedirectToAction("Read");
    }
    else
        return View();
}

I will strongly recommend you to have a look to my tutorial called How to use Moq and xUnit for Unit Testing Controllers in ASP.NET Core to look for the procedure of creating the in-memory database in Entity Framework Core.

There I created this “RegisterController” from scratch, make sure to see that tutorial to.

Writing UI tests with Selenium

Create a new class called UITest.cs in the UITestingProject class library project. Implement IDisposable interface in the class.

using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;

namespace UITestingProject
{
    public class UITest: IDisposable
    {
        public void Dispose()
        {
        }
    }
}

Next, in the constructor of the class, instantiate the IWebDriver object by using the ChromeDriver class and dispose it in the Dispose method.

using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using System;
using System.Collections.Generic;
using System.Text;
using Xunit;

namespace UITestingProject
{
    public class UITest: IDisposable
    {
        private readonly IWebDriver driver;
        public UITest()
        {
            driver = new ChromeDriver();
        }
        public void Dispose()
        {
            driver.Quit();
            driver.Dispose();
        }
    }
}

The IWebDriver object provides the user helpful methods /properties to control the browser’s behavious. Some important methods and properties which we will be using here are as follows:

  • Navigate() – it will navigate the browser to another location.
  • GoToUrl(url) – it will navigate the browser to a specified url.
  • PageSource – a property which gets the page source of the current page.
  • Title – a property which gets the page title of the current page.
  • SendKeys(text) – populates an element with a supplied text.
  • Click() – a method to click an element. We use it for simulating a button click.
  • Text – a property which gets the inner html of an input element.
  • FindElement() – it will find the first element that matches the condition specified.

Now let’s move forward and start writing UI tests with Selenium one by one.

UI Test to Check if the View is rendered

The Create action method (of GET type) in the Register Controller returns the “Create” view. In this UI test I am going to check the browser behaviour for this. So add a new test method called Create_GET_ReturnsCreateView to the UITest.cs, it’s code is given below:

[Fact]
public void Create_GET_ReturnsCreateView()
{
    driver.Navigate().GoToUrl("https://localhost:44386/Register/Create");

    Assert.Equal("Create Record - MyAppT", driver.Title);
    Assert.Contains("Create Record", driver.PageSource);
}

In the first line, I told the web browser to navigate to the URL of the Create action method.

driver.Navigate().GoToUrl("https://localhost:44386/Register/Create");

Next, I performed 2 tests with xUnit. These are checking the title of the page which should be “Create Record – MyAppT” and checking the page source should contain “Create Record”.

Assert.Equal("Create Record - MyAppT", driver.Title);
Assert.Contains("Create Record", driver.PageSource);

The checking of the “Create Record” text is done because this text is shown in the Create View as a heading in h1 tag. You can open the url – https://localhost:44386/Register/Create and can clearly see this heading.

Running the UI Tests

The server should be in running state for the UI test to be performed. So, start the application without debugging (CTRL+F5). The right click the test name on the Test Explorer and select “Run”.

As soon as you run the test, notice a new browser window gets opened and soon after that it is closed automatically, because I called the Quit method in the Dispose method. A little bit later, the test will pass.

I have shown this in the below video so do check it now.

UI Test to Check browser behaviour when Model is invalid

Now I will check the UI working of the HTTP POST type Create action method. The scenario will be when the model is invalid, to make this happened I will be adding an invalid age of 30 (age should be 40 to 60). So, add a new method called Create_POST_InvalidModel() to the test class, the code for this method is given below.

[Fact]
public void Create_POST_InvalidModel()
{
    driver.Navigate().GoToUrl("https://localhost:44386/Register/Create");

    driver.FindElement(By.Id("Name")).SendKeys("Test");

    driver.FindElement(By.Id("Age")).SendKeys("30");

    driver.FindElement(By.ClassName("btn-primary")).Click();

    var errorMessage = driver.FindElement(By.CssSelector(".validation-summary-errors > ul > li")).Text;

    Assert.Equal("The field Age must be between 40 and 60.", errorMessage);
}

I loaded the URL of the Create action method but this time populated the Name and Id text boxes with values. Notice I added an invalid age of 30 to the age text box.

driver.FindElement(By.Id("Name")).SendKeys("Test");
driver.FindElement(By.Id("Age")).SendKeys("30");

I used the By.Id() method of the OpenQA.Selenium namespace to find an element by it’s id. The name text box has an id of “Name” and the “Age” text box has an Id of “Age”, therefore I provided it to the By.Id() as it’s parameter in order to find these elements.

Next I simulated the click of the button using Click() method of the driver object. I find the button with it’s CSS class in this case – By.ClassName("btn-primary").

driver.FindElement(By.ClassName("btn-primary")).Click();

Since the age is not valid therefore, we will be receiving validation error messages. The error message “The field Age must be between 40 and 60.” is shown inside the validation summary div that has a CSS called “validation-summary-errors” and ul and li elements.

I am finding it by using the By.CssSelector() method and then making the assertion.

var errorMessage = driver.FindElement(By.CssSelector(".validation-summary-errors > ul > li")).Text;
Assert.Equal("The field Age must be between 40 and 60.", errorMessage);

Check the below image where I have marked the validation summary and the ul li element containing the validation error message.

Selenium By CssSelector

Run the text and it will pass.

UI Test to Check browser behaviour for Valid Model

The final UI test is testing the browser’s behaviour when the Name and age are proper so the clicking of the button will create the record in the database (in-memory in this case).

The browser will then be redirecting to the “Read” action where the newly added record will be shown. So add the test method called Create_POST_ValidModel() whose code is given below.

[Fact]
public void Create_POST_ValidModel()
{
    driver.Navigate().GoToUrl("https://localhost:44386/Register/Create");

    driver.FindElement(By.Id("Name")).SendKeys("Test");

    driver.FindElement(By.Id("Age")).SendKeys("40");

    driver.FindElement(By.ClassName("btn-primary")).Click();

    Assert.Equal("Records - MyAppT", driver.Title);
    Assert.Contains("Test", driver.PageSource);
    Assert.Contains("40", driver.PageSource);
}

Notice Here I am populating the Name and Age in correct values and clicking the button. This will be adding the record and redirecting the user to the Read action.

In the Read action this newly record is shown.

I am next validating the title of the Read action to be “Records – MyAppT” and the name and age getting displayed or not. The codes which do this work are:

Assert.Equal("Records - MyAppT", driver.Title);
Assert.Contains("Test", driver.PageSource);
Assert.Contains("40", driver.PageSource);

All the UI test methods in Selenium are written and tested in xUnit. For the last time run all these tests in the Text Explorer and they will pass. See the below image which confirms that these tests have passed successfully.

Conclusion

This concludes Selenium testing tutorial. If this tutorial adds value then please share it on your facebook, twitter and other social accounts.

SHARE THIS ARTICLE

  • linkedin
  • reddit

ABOUT THE AUTHOR

I am Yogi S. I write DOT NET artciles on my sites hosting.work and yogihosting.com. You can connect with me on Twitter. I hope my articles are helping you in some way or the other, if you like my articles consider buying me a coffee - Buy Me A Coffee

Leave a Reply

Your email address will not be published.

Related Posts based on your interest