NashTech Blog

Test Execution: Parallel Testing in C# with NUnit and Selenium Grid

Table of Contents

Introduction:

In the rapidly evolving field of software development, time is critical. Our applications’ complexity increases along with the number of automated tests needed to guarantee their quality. Performing these tests one after the other can cause a major bottleneck that slows down the feedback loop and delays releases. The use of parallel testing is helpful in this situation. Concurrent testing allows us to drastically cut down on test execution time, which improves productivity and provides faster feedback. This blog post will discuss how to use N Unit and Selenium Grid to implement parallel testing in C#.

Understanding the Benefits of Parallel Testing:

Reduced Execution Time:

The most immediate and noticeable benefit of parallel testing is the drastic reduction in test execution time. Traditional sequential test execution can be time-consuming, especially as test suites grow in size. With parallel testing, tests that would typically run one after another can be executed concurrently, significantly cutting down the total runtime. For example, a test suite that takes 60 minutes to complete when run sequentially can potentially finish in just 10 minutes if the tests are distributed across six parallel threads. This accelerated execution not only improves productivity but also aligns with the need for rapid release cycles in agile and DevOps environments.

Faster Feedback Loop:

In software development, time-to-feedback is crucial. Developers need quick validation of their changes to proceed with confidence or address issues without delay. Parallel testing plays a vital role in shortening the fedback loop by delivering test results much faster than traditional testing methods. With rapid feedback, teams can detect bugs or regressions early in the development lifecycle, making it easier and cheaper to fix issues before they reach production. This agility helps maintain high code quality while supporting frequent and incremental releases.

Improved Resource Utilization:

Another compelling advantage of parallel testing is its ability to maximize the use of available infrastructure. Instead of idly waiting for sequential tests to complete, parallel testing leverages multiple machines, containers, or browser instances at once—fully utilizing the test environment. Whether you’re using local hardware, cloud-based testing platforms, or a Selenium Grid, parallel execution ensures that computing resources are not wasted. This optimized resource utilization not only speeds up testing but also offers better return on investment (ROI) for your infrastructure.

Scalability:

As applications grow in complexity and user demands increase, so do test cases. Manually managing and executing thousands of tests in a sequential fashion becomes a bottleneck. Parallel testing offers the scalability needed to handle large test suites efficiently. As applications grow in complexity and user demands increase, so do test cases. Manually managing and executing thousands of tests in a sequential fashion becomes a bottleneck. Parallel testing offers the scalability needed to handle large test suites efficiently. With the ability to distribute tests across multiple nodes or environments, QA teams can easily scale their testing efforts without compromising on execution speed. This makes parallel testing an ideal approach for enterprise-level applications, cross-browser compatibility checks, and continuous testing in CI/CD pipelines.

Setting Up the Environment:

A. Install .NET SDK: Download and install the latest .NET SDK from the official Microsoft website. For the Linux system we can use the command also:
“sudo apt get install dotnet-sdk-8.0”

B. Install Visual Studio or VS Code: Use Visual Studio for a complete IDE experience or VS Code with the C# extension for a lightweight option.

C. Install NUnit and Selenium WebDriver:

  1. Install N Unit Package File= “dotnet add package NUnit”
  2. Install NUnit3TestAdapter Package File= “dotnet add package NUnit3TestAdapter”
  3. Install Microsoft .NET.Test sdk Package File= “dotnet add package Microsoft.NET.Test.Sdk”
  4. Install Selenium.WebDriver Package File= “dotnet add package Selenium.WebDriver”
  5. Install Selenium WebDriver Chrome Driver Package File = “dotnet add package Selenium.WebDriver.ChromeDriver”
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>

    <IsPackable>false</IsPackable>
    <IsTestProject>true</IsTestProject>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="coverlet.collector" Version="6.0.0" />
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
    <PackageReference Include="NUnit" Version="3.14.0" />
    <PackageReference Include="NUnit.Analyzers" Version="3.9.0" />
    <PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
    <PackageReference Include="Selenium.WebDriver" Version="4.31.0" />
    <PackageReference Include="Selenium.WebDriver.ChromeDriver" Version="135.0.7049.84" />
    <PackageReference Include="Selenium.WebDriver.GeckoDriver" Version="0.36.0" />
    <PackageReference Include="Selenium.WebDriver.MicrosoftDriver" Version="17.17134.0" />
  </ItemGroup>

  <ItemGroup>
    <Using Include="NUnit.Framework" />
  </ItemGroup>

</Project>

Setting Up Selenium Grid:

Selenium Grid allows us to distribute tests across multiple machines and browsers.

Download Selenium Server Standalone:

Download the latest Selenium Server Standalone JAR file from the Selenium website or we can directly run the command in the terminal:
wget https://github.com/SeleniumHQ/selenium/releases/download/selenium-4.31.0/selenium-server-4.31.0.jar

Start the Hub:
  1. Open a command prompt or terminal and navigate to the directory where you saved the JAR file.
  2. Run the following command to start the hub:
java -Dwebdriver.chrome.driver="path/to/chromedriver.exe" -jar selenium-server-standalone-<version>.jar -role hub

replace path/to/chromedriver.exe with the actual path to your ChromeDriver executable, and <version> with the version of your selenium server.

Start the Nodes:
  1. Open another command prompt or terminal for each node you want to create.
  2. Run the following command to start a node:
java -Dwebdriver.chrome.driver="path/to/chromedriver.exe" -jar selenium-server-standalone-<version>.jar -role node -hub http://localhost:4444/grid/register/

Make sure the hub address (http://localhost:4444/grid/register/) matches the address of your hub.

Real Time Example

using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Remote;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Firefox;
using System;

namespace SeleniumGridParallel
{
    [TestFixture("chrome")]
    [TestFixture("edge")]
    [Parallelizable(ParallelScope.Fixtures)]
    public class UnitTest1
    {
        private RemoteWebDriver driver;
        private readonly string browser;
        private readonly string gridUrl = "http://192.168.29.218:4444/wd/hub";

        public UnitTest1(string browser)
        {
            this.browser = browser;
        }

        [SetUp]
        public void Setup()
        {
            if (browser == "chrome")
            {
                var options = new ChromeOptions();
                driver = new RemoteWebDriver(new Uri(gridUrl), options);
            }
            else if (browser == "edge")
            {
                var options = new OpenQA.Selenium.Edge.EdgeOptions();
                driver = new RemoteWebDriver(new Uri(gridUrl), options);
            }

        }

        [Test]
        public void OpenGoogleDotCom()
        {
            driver.Navigate().GoToUrl("https://www.google.com");
            Assert.IsTrue(driver.Title.Contains("Google"));
            driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
        }

        [Test]
        public void OpenExampleDotCom()
        {
            driver.Navigate().GoToUrl("https://www.wikipedia.org");
            Assert.AreEqual("Wikipedia", driver.Title);
        }

        [TearDown]
        public void Teardown()
        {
            if (driver != null)
            {
                driver?.Quit();
                driver?.Dispose();
            }
        }
    }
}

Step By Step Explanation :

1. TestFixture Attributes

[TestFixture("chrome")]
[TestFixture("edge")]
[Parallelizable(ParallelScope.Fixtures)]

These tell NUnit to run the tests with both "chrome" and "edge" as parameters. [Parallelizable(ParallelScope.Fixtures)] means that all tests can be run in parallel—across test cases and even across methods, depending on your test runner’s capabilities.

2. Constructor :
public SeleniumGridTest(string browser)
{
    this.browser = browser;
}

Stores the name of the browser (Chrome or Edge) for each test fixture instance.

3. Setup Method :
[SetUp]
public void Setup()
{
    if (browser == "chrome")
    {
        var options = new ChromeOptions();
        driver = new RemoteWebDriver(new Uri(gridUrl), options);
    }
    else if (browser == "edge")
    {
        var options = new OpenQA.Selenium.Edge.EdgeOptions();
        driver = new RemoteWebDriver(new Uri(gridUrl), options);
    }
}

Based on the browser parameter, it creates the appropriate browser options. Initializes a RemoteWebDriver connected to the Selenium Grid hub.

Test 1: OpenExampleDotCom :
[Test]
public void OpenExampleDotCom()
{
    driver.Navigate().GoToUrl("https://www.wikipedia.org");
    Assert.AreEqual("Wikipedia", driver.Title);
}

Opens Wikipedia’s homepage. Asserts that the page title is exactly "Wikipedia".

Test 2: OpenGoogleDotCom :
[Test]
public void OpenGoogleDotCom()
{
    driver.Navigate().GoToUrl("https://www.google.com");
    Assert.IsTrue(driver.Title.Contains("Google"));
}

Opens Google homepage. Checks that the title contains the word "Google" (a bit more flexible than an exact match).

TearDown Method :
 [TearDown]
        public void Teardown()
        {
            if (driver != null)
            {
                driver?.Quit();
                driver?.Dispose();
            }
        }

This cleans up by quitting the driver after each test to release resources.

Conclusion:

Parallel testing with NUnit and Selenium Grid is a powerful technique for accelerating test execution and improving the efficiency of your testing process. By leveraging the power of concurrency, you can significantly reduce feedback time, enabling faster development cycles and higher-quality software. Remember to carefully consider thread safety, resource management, and test isolation when implementing parallel tests. By following the steps outlined in this blog post, you can effectively implement parallel testing in your C# projects and reap the benefits of faster, more efficient testing.

References:

  1. Selenium Grid Website – https://www.selenium.dev/documentation/grid/
  2. Browser Stack – https://www.browserstack.com/guide/selenium-grid-tutorial
Picture of Divyanshu Jain

Divyanshu Jain

Leave a Comment

Your email address will not be published. Required fields are marked *

Suggested Article

Scroll to Top