Selenium is a library that helps us automate browser behavior. We can use it for different purposes, but its primary use is for automated testing of web applications.

In this article, we are going to use Selenium to write automated UI tests and with that finish our testing series. Selenium has support for many different browsers and for this article, we are going to use the ChromeDriver. It also contains many different useful methods (Navigate, GoToUrl, FindElement, SendKees, Click…) which help us manipulate different HTML elements. These methods are going to be of great use in our examples.

You can download the source code on our GitHub repository.

For the complete navigation of this series, you can visit ASP.NET Core MVC Testing.

These are the topics that we are going to cover:

So, let’s get down to business.

Project Preparation and Selenium Installation

First thing first.

We are going to create a new xUnit (.NET Core) test project and name it EmployeesApp.AutomatedUITests. After the creation process, we are going to rename the existing class to AutomatedUITests:

Project creation - Selenium

Now we can open the NuGet Package Manager window and install two required libraries, Selenium.WebDriver and Selenium.WebDriver.ChromeDriver:

Selenium libraries

Or you can use the Package Manager window:

PM> Install-Package Selenium.WebDriver -Version 3.141.0

PM> Install-Package Selenium.WebDriver.ChromeDriver -Version 76.0.0

That’s all it takes. We are now prepared to write automated UI tests.

Writing the First UI Test

Let’s open the AutomatedUITests class and modify it by implementing the IDisposable interface:

We are going to use the Dispose method to close a chrome window opened by the ChromeDriver and also to dispose of it. To continue on, let’s create our driver:

So, we instantiate the IWebDriver object by using the ChromeDriver class and in the Dispose method, dispose of it. With that done, everything is ready for the first UI test:

We use the Navigate method to instruct the driver to navigate the browser to another location and with the GoToUrl method, we provide that location. Once the browser has navigated to the requested Url, the Title and PageSource properties of the _driver object will be populated.

So, we just make assertions on those properties to verify that we have actually navigated to the Create page. Before we start the Test Explorer window, we need to start our application without debugging (CTRL+F5) because a running server is required for UI tests to pass:

First UI test pass - Selenium testing

As soon as we run our test, we are going to see a new browser window opened and soon after that closed because we call the Quit method in the Dispose method. A little bit later, our test will pass.

Excellent!

We can shut down our app, and move on to the other tests.

Using Selenium to Manipulate Input Fields and Executing Additional Tests

Let’s write another test where we verify that the error message appears on the screen if we populate some input fields, not all of them, and click the Create button:

One more time, we navigate to the required location by using the Navigate and the GoToUrl methods. After that, we start populating our input fields. Of course, we have to find an element first. To achieve that we use the FindElement(By.Id(„Name“)) expression.

The FindElement method will find an element on the HTML page and it accepts a parameter of type By. The By class consists of the different methods which allow us to search different elements on our page (Id, ClassName, CssSelector, TagName, etc.).

Once we find the element, we use the SendKeys method to populate it. The same process is repeated for the Age element and the Create button, just for the Create button we use the Click method to click on it.

Finally, we extract the error message from the page and make an assertion.

If you want, you can debug this test code to see how our driver opens the page and manipulates the input fields and the button.

Let’s start our app without debugging again and run our test:

Secont UI test fail

We can see that it fails, and the message explains it pretty well. The FindElement method can’t find our button with the Create value for the Id attribute. So, we can inspect our page source and look for a valid attribute or we can change our code a bit. We are going to change the code.

Let’s open the Create view in the main project and just add the Id attribute to the button element:

Now, let’s start the app and run the Test Explorer window:

Second UI test passes

It passes now.

Additional UI Test

Let’s write one additional test where we populate all the fields, click the Create button and then verify that the Index page is loaded with a new employee:

We can see that there are small differences between this code and the previous one. Here we just populate all the fields and making assertions on the page’s title and newly created data.

So, let’s try if this passes:

Last selenium UI test

And it does.

Great job. Now, let’s refactor our code to eliminate repetitions and make it more readable.

Making the Code Even Better

We can see that we have a lot of redundant code in our testing methods when we navigate to the URI or find different elements on the HTML page.

This is something we want to avoid.

This pattern, that we are going to use, is called Page Object Model Design Pattern. But, we are not going to use the PageFactory class (as you can see in many different examples) because it is not supported in .NET Core and it is getting obsolete in .NET Framework.

So, let’s start by creating a new EmployeePage class in the EmployeesApp.UITests project and modifying it:

This code is pretty easy to understand because we only extract the logic for finding HTML elements and add some methods to populate them and click the Create button. We additionally extract the logic for the Title, Source and error message.

After these changes, we can modify the AutomatedUITests class:

And that is it. It is pretty obvious that this code is much cleaner and easier to read.

You can run the test explorer to verify that all tests pass as they did before.

Conclusion

And there we go. With this article, we have finished our Testing series.

Now you should have enough knowledge to write your own tests and to deeply explore testing features in ASP.NET Core MVC.

We hope you have enjoyed this series as much as we did.

If you have enjoyed reading this article and if you would like to receive the notifications about the freshly published .NET Core content we encourage you to subscribe to our blog.