Swimburger

How to UI test using Selenium and .NET Core on Windows, Ubuntu, and maybe MacOS? 🤷‍♀️🤷‍♂️

- DotNet -
.NET Core + Selenium logo steering a web browser window

Selenium is a browser automation tool mainly used for UI testing and automating tasks. Selenium is agnostic of operating system, programming language, and browser.
You can automate Chrome on MacOS using C#, FireFox using Python on Windows, or Opera using NodeJS on Linux to give you a few examples. Refer to this page on the Selenium website for a full list of supported OS's, programming languages, and browsers.

In this post you'll learn how to create a minimal Selenium test using .NET Core on both Windows and Ubuntu (Linux).
FYI, this post should also apply for MacOS, though I have not verified this. To follow along you'll need the following:

  • .NET Core SDK (2.2)
  • Windows, Linux, or MacOS dev machine
  • Chrome/Chromium web browser
  • Chrome WebDriver (make sure the driver version matches the browser version)

1. Creating the .NET Core test project #

mkdir Selenium_DotNet
cd Selenium_DotNet
dotnet new solution
mkdir Demo.SeleniumTests
cd Demo.SeleniumTests
dotnet new mstest
cd ..
dotnet sln add Demo.SeleniumTests

Using the above commands, the skeleton of your test project is ready. Navigate to your test project and run the following command to test out the dummy test:

cd Demo.SeleniumTests
dotnet test

2. Add Selenium to the test project #

To start integrating Selenium into your test project, you'll need to add the Selenium.WebDriver Nuget package.
Use the following dotnet cli command to add the dependency.

dotnet add package Selenium.WebDriver --version 3.141.0

Once the package has been added, you'll be able to use the Selenium API in your C# project but you'll need to make the ChromeDriver available before it'll start working. More on that later.

3. Write a UI test using Selenium #

Using your editor of choice, write a UI test. Keep it simple for now, you can write a more advanced test after getting a simple test working.
Here's a more advanced sample, but feel free to strip it to the minimum:

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

namespace Demo.SeleniumTests
{
    [TestClass]
    public class DotNetSiteTests
    {
        [TestMethod]
        public void TestGetStarted()
        {
            // Chrome Driver was manually downloaded from https://sites.google.com/a/chromium.org/chromedriver/downloads
            // parameter "." will instruct to look for the chromedriver.exe in the current folder
            using (var driver = new ChromeDriver("."))
            {
                //Navigate to DotNet website
                driver.Navigate().GoToUrl("https://dotnet.microsoft.com/");
                //Click the Get Started button
                driver.FindElement(By.LinkText("Get Started")).Click();

                // Get Started section is a multi-step wizard
                // The following sections will find the visible next step button until there's no next step button left
                IWebElement nextLink = null;
                do
                {
                    nextLink?.Click();
                    nextLink = driver.FindElements(By.CssSelector(".step:not([style='display:none;']):not([style='display: none;']) .step-select")).FirstOrDefault();
                } while (nextLink != null);

                // on the last step, grab the title of the step wich should be equal to "Next steps"
                var lastStepTitle = driver.FindElement(By.CssSelector(".step:not([style='display:none;']):not([style='display: none;']) h2")).Text;

                // verify the title is the expected value "Next steps"
                Assert.AreEqual(lastStepTitle, "Next steps");
            }
        }
    }
}

Note: The test is likely to break when the dotnet site changes.

Pay attention to the constructor of 'ChromeDriver' on line 16. By default the ChromeDriver class when instantiated without parameters will search for​ the chromedriver executable (from chromedriver.chromium.org) inside your Path environment variable.
Alternatively, you can pass in the path of the ChromeDriver executable to the constructor. By passing in ".", Selenium will search for the executable in the current working directory.

4. Run the UI test #

To run the test follow these steps:

  1. Run the dotnet build command inside your test project
  2. Copy the chromedriver.exe/chromedriver executable to "Selenium_DotNet\Demo.SeleniumTests\bin\Debug\netcoreapp2.2​"
    See example scripts below for Ubuntu and PowerShell.
  3. Run the dotnet test command and watch the magic 🧙‍♂️

For Ubuntu you can use these commands to download the ChromeDriver (modify driver URL as needed):

cd bin/Debug/netcoreapp2.2/
wget https://chromedriver.storage.googleapis.com/75.0.3770.140/chromedriver_linux64.zip
unzip chromedriver_linux64.zip # sudo apt install unzip
chmod 774 chromedriver

For Windows you can use this PowerShell script (modify driver URL as needed):

cd bin/Debug/netcoreapp2.2/;
Invoke-WebRequest -Uri "https://chromedriver.storage.googleapis.com/75.0.3770.90/chromedriver_win32.zip" -OutFile ./chromedriver_win32.zip;
Expand-Archive ./chromedriver_win32.zip -DestinationPath ./chromedriver_win32;
Copy-Item ./chromedriver_win32/chromedriver.exe -Destination .;

Troubleshooting: if the test fails due to Chrome/Chromium errors, follow these steps

Summary #

Using .NET Core you can write cross-platform UI tests using C# and Selenium. You can swap out the ChromeDriver with any other supported browser to verify cross-browser compatibility. You can use this GitHub repository as a reference in case you run into any roadblocks.
In the next post, learn how you can run these UI tests inside of Azure DevOps deployment pipelines.

Cheers 🥂

Notes:

  1. The reason I don't suggest using Nuget packages to pull in the ChromeDriver executable is because executable is only offered by 3rd party unverified package owners which introduces a risky dependency into your codebase.
  2. I suggest not including the ChromeDriver executable in your .csproj file or Source Control since there's no guarantee ahead of time that your Chrome browser will be compatible with your ChromeDriver. For example, when you pass this test to a test server, the Chrome browser may be on a version incompatible with your ChromeDriver. Some solutions to this would be to:
    • include the ChromeDriver in the path environment variable of the test server;
    • download the correct ChromeDriver as part of your CI/CD system and copy it next to your test dll's;
    • pass in the location of the ChromeDriver through TestRunParameters;

Related Posts

Related Posts