Launching WebDrivers in .net Core

Launching WebDrivers in .net Core

This entry is part 3 of 9 in the series Launching WebDrivers in .NET Core the easy way

As discussed last time, the goal is to be able to run my tests on any .net Core platform. So right from the get go, lets work out how to get a WebDriver fired up. As ever I develop on Windows and I still have Ubuntu 18.4 installed on the Windows Subsystem for Linux (WSL) with an Xming Xserver so in theory I can also test in Linux. Unfortunately, whatever happened to my network whilst I was on holiday finally killed off the old Mac I had acquired so no MacOs testing for now.

First exploration

So let’s start off with a minimal test project and see what happens. Aware that this is the first time I’ve been writing about writing in C#. As I am working in Windows I am lucky enough to have access to Microsoft’s premier IDE, Visual Studio. I’ll have a play with some of the other tools out there later. Fortunately if you are just exploring and learning C# the free community version of Visual Studio is a fully featured IDE. At the time of writing this up I am using version 15.8.7, and I installed Windows 10 version 1809 (the October 2018 Update) a few days ago.

Open it up and create a new test project in .net Core (v2.1). Rather than configuring a build.gradle file as in Java, you have the option to use the UI to manage nuget packages. For the purposes of this quick demo we need to add the following:

  • FluentAssertions
  • Microsoft.NET.Test.Sdk
  • NUnit
  • NUnit.Console
  • NUnit3TestAdapter
  • Selenium.WebDriver
  • Selenium.WebDriver.ChromeDriver
  • Selenium.WebDriver.GeckoDriver.Win64
  • Selenium.WebDriver.IEDriver

Then a simple Nunit test class:

using FluentAssertions;
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Edge;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.IE;

namespace webdriverlaunch
{
    [TestFixture]
    public class WebDriverLaunchTests
    {
        [Test]
        public void ChromeDriverCanBeLaunched()
        {
            IWebDriver driver = new ChromeDriver();
            AssertThatTheWebDriverHasLoadedAPage(driver);
        }

        [Test]
        public void EdgeDriverCanBeLaunched()
        {
            IWebDriver driver = new EdgeDriver();
            AssertThatTheWebDriverHasLoadedAPage(driver);
        }
        [Test]
        public void FirefoxDriverCanBeLaunched()
        {
            IWebDriver driver = new FirefoxDriver();
            AssertThatTheWebDriverHasLoadedAPage(driver);
        }
        [Test]
        public void InternetExplorerDriverCanBeLaunched()
        {
            IWebDriver driver = new InternetExplorerDriver();
            AssertThatTheWebDriverHasLoadedAPage(driver);
        }

        private void AssertThatTheWebDriverHasLoadedAPage(IWebDriver driver)
        {
            driver.Url = "http://www.example.com";
            driver.Title.Should().NotBeNullOrEmpty();
            driver.Quit();
        }
    }
}

And let’s see what happens:

Basic Launcher Tests

In fact before the Windows 10 upgrade even the Edge test failed with the same issue. This is a little surprising given that IWebDriver driver = new ChromeDriver();  works just fine in a .net Framework 4.7.1 project. Looking at the error:

Message: OpenQA.Selenium.DriverServiceNotFoundException : The geckodriver.exe file does not exist in the current directory or in a directory on the PATH environment variable. The driver can be downloaded at https://github.com/mozilla/geckodriver/releases.

Ok so we could ensure that we find the path of the driver files and add it to the System Path, but much better if we can find and pass the path programmatically.

Passing the driver path to the constructor.

Fortunately I was not the first person to look into this and it has previously been written about on the excellent AutomateThePlanet blog.

So passing:

Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)

to the WebDriver constructor should do the trick:

Adding the DriverPath to the constructor.

Now we can see that everything except the EdgeWebDriver is working properly, and in fact again this was working until the Windows 10 update.

So what’s the deal with Edge in the Windows 10 October 2018 update?

One of the downsides of Edge’s close integration in Windows 10 means that it only gets major feature updates with new Windows versions. In this case Edge now has its W3C standard driver, and following on from the trend set by Safari on MacOS it can be activated simply by enabling Developer mode in Edge.

Alternatively in an elevated command prompt / PowerShell enter DISM.exe /Online /Add-Capability /CapabilityName:Microsoft.WebDriver~~~~0.0.1.0  to enable it.

While you are at it, don’t forget to reset all Internet Explorer Security zones to the same Protected Mode setting (I set them all to Enabled) as the default mix settings are reset.

Final Code then:

So no DriverPath for Edge, but pass it for the rest. I suspect (but can’t currently check) that Safari also does not require this if you are on your Mac. and add some code to only test if on a supported platform.

using System.IO;
using System.Reflection;
using FluentAssertions;
using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Edge;
using OpenQA.Selenium.Firefox;
using OpenQA.Selenium.IE;

namespace webdriverlaunch
{
    [TestFixture]
    public class WebDriverLaunchTests
    {
        private readonly string driverPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);

        [Test]
        public void ChromeDriverCanBeLaunched()
        {
            IWebDriver driver = new ChromeDriver(driverPath);
            AssertThatTheWebDriverHasLoadedAPage(driver);
        }

        [Test]
        public void EdgeDriverCanBeLaunched()
        {
            Assume.That(() => Platform.CurrentPlatform.IsPlatformType(PlatformType.Windows));
            IWebDriver driver = new EdgeDriver();
            AssertThatTheWebDriverHasLoadedAPage(driver);
        }

        [Test]
        public void FirefoxDriverCanBeLaunched()
        {
            IWebDriver driver = new FirefoxDriver(driverPath);
            AssertThatTheWebDriverHasLoadedAPage(driver);
        }

        [Test]
        public void InternetExplorerDriverCanBeLaunched()
        {
            Assume.That(() => Platform.CurrentPlatform.IsPlatformType(PlatformType.Windows));
            IWebDriver driver = new InternetExplorerDriver(driverPath);
            AssertThatTheWebDriverHasLoadedAPage(driver);
        }

        [Test]
        public void SafariDriverCanBeLaunched()
        {
            Assume.That(() => Platform.CurrentPlatform.IsPlatformType(PlatformType.Mac));
            IWebDriver driver = new InternetExplorerDriver(driverPath);
            AssertThatTheWebDriverHasLoadedAPage(driver);
        }

        private void AssertThatTheWebDriverHasLoadedAPage(IWebDriver driver)
        {
            driver.Url = "http://www.example.com";
            driver.Title.Should().NotBeNullOrEmpty();
            driver.Quit();
        }
    }
}

FYI: If you are looking to use page objects in your tests you might want to check out my post: C# and the disappearing PageFactory – My next steps in Selenium testing

and the results in Windows

Checking on all .net Core desktop platforms

And as for how to test on all platforms. Running tests from the command line could barely be easier:

dotnet test in the directory containg the .sln file.

And we can do the same in Linux, only first we have sitch to the approriate nuget package for the linux firefox driver (Selenium.WebDriver.GeckoDriver) and build first:

dotnet build then dotnet test : Unfortunately I have completely hosed my Chrome installation but Firefox runs as expected:

Run on Linux WSL – sadly my Chrome install is corrupted

Progress made:

  • Found out how to launch WebDriver from a .net Core project.

Lessons learnt:

  • I need to find another Mac. (Anyone got an old MacBook with a broken screen going spare?)
  • I have properly broken Chrome on my Ubuntu: I should install a proper linux instance, either a VM or an alternate boot configuration.
  • Switching packages between OSes is a pain, better to have separated projects for each OS I want to test against.
  • Next time try to build this into a WebDriverFactory for my framework.

A reminder:

If you want to ask me a question, Twitter is undoubtedly the fastest place to get a response. I have changed my Username to @AlexanderOnTest to make myself easier to find. My DMs are always open for questions, and I publicise my new blog posts there too.

I still have plenty more to write about. Next time: The crazy adventures that were my first attempts at writing and publishing my own WebDriverFactory package on nuget.org.

[Edit 26/6/19 Moved into the new series: Launching WebDrivers in .NET Core the easy way]
Series Navigation<< Starting to build a (new) .net Core PageFactoryCreating an internal WebDriverFactory >>
Comments are closed.