Selenium WebDriver + .NET Core 2.0- What Everyone Ought to Know

WebDriver
95 Shares
Selenium WebDriver + .NET Core 2.0

In my WebDriver Series, you can find lots of useful information about how to use Selenium WebDriver for UI automation. As you probably know one of the newest and coolest Microsoft technologies is .NET Core. However, prior the release of Visual Studio 2017 Preview 2 we were unable to run WebDriver tests using .NET Core projects. In this article, I am going to show you how to combine them and "experience the future".

What Problem Are We Trying to Solve?

If you use Visual Studio 2017 15.2 and try to create .NET Standard library, by default the library targets .NETStandard 1.4.

Visual Studio 2017 15.2 .NETStandard 1.4

When you try to install the Selenium.WebDriver NuGet the following error occurs.

Package Manager Selenium.WebDriver Install Error

Old NuGets that target .NET Framework are not compatible with applications that target .NET Core or .NET Standard < 2.0. From 2.0 version and above Microsoft will make them work. You can check this article to see all changes. So our goal here will be to upgrade our projects to .NETStandard 2.0.

Read more about .NET Core here.

Selenium WebDriver + .NET Core

First, you will need to install Visual Studio 2017 Preview 2. This is an early access version of the tooling where .NET Core 2.0 and .NET Standard 2.0 are supported. This means that you will be able to combine .NET Core applications with .NET Framework NuGets that do not have .NET Core support. This is the case of Selenium.WebDriver. Also, you can download the .NET Core SDK and command line tools from here. I will show you later how you can use them to run simultaneously tests that use different test frameworks such as MSTest, NUnit and XUnit

When you are ready, create a new .NET Standard class library and open the project's Properties. You will need to change the target framework to .NETStandard 2.0.

Change Target Framework

Install WebDriver NuGets

I will show you how to configure the most common drivers- FirefoxDriver, ChromeDriver and EdgeDriver. So we will need to install a couple of NuGets to do that. One of the coolest new feature of the .NET Core tooling is that the package.config is gone and all packages are referenced directly in the project's MSBuild file. Moreover, you can edit the project files without unloading and reloading the projects. 

<PackageReference Include="Selenium.Chrome.WebDriver" Version="2.30.0" />
<PackageReference Include="Selenium.Firefox.WebDriver" Version="0.17.0" />
<PackageReference Include="Selenium.Support" Version="3.4.0" />
<PackageReference Include="Selenium.WebDriver" Version="3.4.0" />
<PackageReference Include="Selenium.WebDriver.MicrosoftDriver" Version="15.15063.0" />

When you run your tests, you will notice that error about System.Security.Permissions DLL occurs. To fix it, you need to install the System.Security.Permissions NuGet package (the prerelease version).

Install MSTest Framework NuGets

You need to install the MSTest.TestFramework and MSTest.TestAdapter NuGets. Through the later, you will see your tests in the Test Explorer window. 

Install NUnit Framework NuGets

For NUnit, you need the NUnit and NUnit3TestAdapter NuGets. Make sure that you check the "Include prerelease" checkbox in the NuGet Packages Window. You will need to install an alpha version of the NUnit test adapter. The older(stable) versions are not compatible with .NET Core.

<PackageReference Include="NUnit" Version="3.7.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.8.0-alpha1" />

Install xUnit Framework NuGets

Similar to others you need xunit and xunit.runner.visualstudio packages to be able to run XUnit tests.

Finally, you need one last NuGet package so that you can execute tests from .NET Standard class library- Microsoft.NET.Test.Sdk. Below you can find the list of all references, you need only to copy them to your project file, and they will be installed automatically.

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.3.0-preview-20170628-02" />
<PackageReference Include="MSTest.TestAdapter" Version="1.1.17" />
<PackageReference Include="MSTest.TestFramework" Version="1.1.17" />
<PackageReference Include="NUnit" Version="3.7.1" />
<PackageReference Include="NUnit3TestAdapter" Version="3.8.0-alpha1" />
<PackageReference Include="Selenium.Chrome.WebDriver" Version="2.30.0" />
<PackageReference Include="Selenium.Firefox.WebDriver" Version="0.17.0" />
<PackageReference Include="Selenium.Support" Version="3.4.0" />
<PackageReference Include="Selenium.WebDriver" Version="3.4.0" />
<PackageReference Include="Selenium.WebDriver.MicrosoftDriver" Version="15.15063.0" />
<PackageReference Include="System.Security.Permissions" Version="4.4.0-preview2-25405-01" />
<PackageReference Include="xunit" Version="2.3.0-beta3-build3705" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.3.0-beta3-build3705" />
</ItemGroup>

Configure Different Selenium Drivers

FirefoxDriver

You can use FirefoxDriver without any problems but as you will see this is not the case for the rest of the drivers.

[Test]
public void TestWithFirefoxDriver()
{
using (var driver = new FirefoxDriver())
{
driver.Navigate().GoToUrl(@"https://automatetheplanet.com/multiple-files-page-objects-item-templates/");
var link = driver.FindElement(By.PartialLinkText("TFS Test API"));
var jsToBeExecuted = $"window.scroll(0, {link.Location.Y});";
((IJavaScriptExecutor)driver).ExecuteScript(jsToBeExecuted);
var wait = new WebDriverWait(driver, TimeSpan.FromMinutes(1));
var clickableElement = wait.Until(ExpectedConditions.ElementToBeClickable(By.PartialLinkText("TFS Test API")));
clickableElement.Click();
}
}

ChromeDriver

If you use the default constructor of ChromeDriver, the following exception is thrown.

Message: OpenQA.Selenium.DriverServiceNotFoundException : The chromedriver.exe file does not exist in the current directory or in a directory on the PATH environment variable. The driver can be downloaded at http://chromedriver.storage.googleapis.com/index.html.

This happens because the NuGet packages for .NET Core projects are loaded from a global place instead of the packages folder of the .NET Framework projects. To fix it, we need to specify the path to the execution folder.

[Test]
public void TestWithChromeDriver()
{
using (var driver = new ChromeDriver(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)))
{
driver.Navigate().GoToUrl(@"https://automatetheplanet.com/multiple-files-page-objects-item-templates/");
var link = driver.FindElement(By.PartialLinkText("TFS Test API"));
var jsToBeExecuted = $"window.scroll(0, {link.Location.Y});";
((IJavaScriptExecutor)driver).ExecuteScript(jsToBeExecuted);
var wait = new WebDriverWait(driver, TimeSpan.FromMinutes(1));
var clickableElement = wait.Until(ExpectedConditions.ElementToBeClickable(By.PartialLinkText("TFS Test API")));
clickableElement.Click();
}
}

EdgeDriver

A similar exception is thrown for the EdgeDriver, the fix is similar.

[Test]
public void TestWithEdgeDriver()
{
using (var driver = new EdgeDriver(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)))
{
driver.Navigate().GoToUrl(@"https://automatetheplanet.com/multiple-files-page-objects-item-templates/");
var link = driver.FindElement(By.PartialLinkText("TFS Test API"));
var jsToBeExecuted = $"window.scroll(0, {link.Location.Y});";
((IJavaScriptExecutor)driver).ExecuteScript(jsToBeExecuted);
var wait = new WebDriverWait(driver, TimeSpan.FromMinutes(1));
var clickableElement = wait.Until(ExpectedConditions.ElementToBeClickable(By.PartialLinkText("TFS Test API")));
clickableElement.Click();
}
}

MSTest Tests in .NET Core

[TestClass]
public class AutomateThePlanetTestsMsTest
{
[TestMethod]
public void TestWithFirefoxDriver()
{
using (var driver = new FirefoxDriver())
{
driver.Navigate().GoToUrl(@"https://automatetheplanet.com/multiple-files-page-objects-item-templates/");
var link = driver.FindElement(By.PartialLinkText("TFS Test API"));
var jsToBeExecuted = $"window.scroll(0, {link.Location.Y});";
((IJavaScriptExecutor)driver).ExecuteScript(jsToBeExecuted);
var wait = new WebDriverWait(driver, TimeSpan.FromMinutes(1));
var clickableElement = wait.Until(ExpectedConditions.ElementToBeClickable(By.PartialLinkText("TFS Test API")));
clickableElement.Click();
}
}
[TestMethod]
public void TestWithEdgeDriver()
{
using (var driver = new EdgeDriver(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)))
{
driver.Navigate().GoToUrl(@"https://automatetheplanet.com/multiple-files-page-objects-item-templates/");
var link = driver.FindElement(By.PartialLinkText("TFS Test API"));
var jsToBeExecuted = $"window.scroll(0, {link.Location.Y});";
((IJavaScriptExecutor)driver).ExecuteScript(jsToBeExecuted);
var wait = new WebDriverWait(driver, TimeSpan.FromMinutes(1));
var clickableElement = wait.Until(ExpectedConditions.ElementToBeClickable(By.PartialLinkText("TFS Test API")));
clickableElement.Click();
}
}
[TestMethod]
public void TestWithChromeDriver()
{
using (var driver = new ChromeDriver(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)))
{
driver.Navigate().GoToUrl(@"https://automatetheplanet.com/multiple-files-page-objects-item-templates/");
var link = driver.FindElement(By.PartialLinkText("TFS Test API"));
var jsToBeExecuted = $"window.scroll(0, {link.Location.Y});";
((IJavaScriptExecutor)driver).ExecuteScript(jsToBeExecuted);
var wait = new WebDriverWait(driver, TimeSpan.FromMinutes(1));
var clickableElement = wait.Until(ExpectedConditions.ElementToBeClickable(By.PartialLinkText("TFS Test API")));
clickableElement.Click();
}
}
}

NUnit Tests in .NET Core

[TestFixture]
public class AutomateThePlanetTests
{
[Test]
public void TestWithFirefoxDriver()
{
using (var driver = new FirefoxDriver())
{
driver.Navigate().GoToUrl(@"https://automatetheplanet.com/multiple-files-page-objects-item-templates/");
var link = driver.FindElement(By.PartialLinkText("TFS Test API"));
var jsToBeExecuted = $"window.scroll(0, {link.Location.Y});";
((IJavaScriptExecutor)driver).ExecuteScript(jsToBeExecuted);
var wait = new WebDriverWait(driver, TimeSpan.FromMinutes(1));
var clickableElement = wait.Until(ExpectedConditions.ElementToBeClickable(By.PartialLinkText("TFS Test API")));
clickableElement.Click();
}
}
[Test]
public void TestWithEdgeDriver()
{
using (var driver = new EdgeDriver(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)))
{
driver.Navigate().GoToUrl(@"https://automatetheplanet.com/multiple-files-page-objects-item-templates/");
var link = driver.FindElement(By.PartialLinkText("TFS Test API"));
var jsToBeExecuted = $"window.scroll(0, {link.Location.Y});";
((IJavaScriptExecutor)driver).ExecuteScript(jsToBeExecuted);
var wait = new WebDriverWait(driver, TimeSpan.FromMinutes(1));
var clickableElement = wait.Until(ExpectedConditions.ElementToBeClickable(By.PartialLinkText("TFS Test API")));
clickableElement.Click();
}
}
[Test]
public void TestWithChromeDriver()
{
using (var driver = new ChromeDriver(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)))
{
driver.Navigate().GoToUrl(@"https://automatetheplanet.com/multiple-files-page-objects-item-templates/");
var link = driver.FindElement(By.PartialLinkText("TFS Test API"));
var jsToBeExecuted = $"window.scroll(0, {link.Location.Y});";
((IJavaScriptExecutor)driver).ExecuteScript(jsToBeExecuted);
var wait = new WebDriverWait(driver, TimeSpan.FromMinutes(1));
var clickableElement = wait.Until(ExpectedConditions.ElementToBeClickable(By.PartialLinkText("TFS Test API")));
clickableElement.Click();
}
}
}

xUnit Tests in .NET Core

public class AutomateThePlanetTestsXUnit
{
[Fact]
public void TestWithFirefoxDriver()
{
using (var driver = new FirefoxDriver())
{
driver.Navigate().GoToUrl(@"https://automatetheplanet.com/multiple-files-page-objects-item-templates/");
var link = driver.FindElement(By.PartialLinkText("TFS Test API"));
var jsToBeExecuted = $"window.scroll(0, {link.Location.Y});";
((IJavaScriptExecutor)driver).ExecuteScript(jsToBeExecuted);
var wait = new WebDriverWait(driver, TimeSpan.FromMinutes(1));
var clickableElement = wait.Until(ExpectedConditions.ElementToBeClickable(By.PartialLinkText("TFS Test API")));
clickableElement.Click();
}
}
[Fact]
public void TestWithEdgeDriver()
{
using (var driver = new EdgeDriver(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)))
{
driver.Navigate().GoToUrl(@"https://automatetheplanet.com/multiple-files-page-objects-item-templates/");
var link = driver.FindElement(By.PartialLinkText("TFS Test API"));
var jsToBeExecuted = $"window.scroll(0, {link.Location.Y});";
((IJavaScriptExecutor)driver).ExecuteScript(jsToBeExecuted);
var wait = new WebDriverWait(driver, TimeSpan.FromMinutes(1));
var clickableElement = wait.Until(ExpectedConditions.ElementToBeClickable(By.PartialLinkText("TFS Test API")));
clickableElement.Click();
}
}
[Fact]
public void TestWithChromeDriver()
{
using (var driver = new ChromeDriver(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)))
{
driver.Navigate().GoToUrl(@"https://automatetheplanet.com/multiple-files-page-objects-item-templates/");
var link = driver.FindElement(By.PartialLinkText("TFS Test API"));
var jsToBeExecuted = $"window.scroll(0, {link.Location.Y});";
((IJavaScriptExecutor)driver).ExecuteScript(jsToBeExecuted);
var wait = new WebDriverWait(driver, TimeSpan.FromMinutes(1));
var clickableElement = wait.Until(ExpectedConditions.ElementToBeClickable(By.PartialLinkText("TFS Test API")));
clickableElement.Click();
}
}
}

Run All Tests from Command Line

As I previously told you, you can run all of your different test framework tests from the Test Explorer window. However, if you have installed the .NET Core command line tools, you can run all of your tests from the command line as well. You can use the following command to do so- dotnet test --logger=trx

You can find more about the dotnet test command in the official documentation.

As you can see from the image below all of our tests are run through a single command. It ran 3 MSTest, 3 NUnit and 3 xUnit tests. Amazing! Welcome to the Future! I cannot wait .NET Core 2.0 and .NET Standard to be officially released. You can check the official .NET Core Roadmap for more info.

dotnet test Run All Test Framework Tests

  • Jon Hallam

    Which driver is needed when running within LINUX. My app runs in docker on a ubuntu server.

  • Christophe Mandrillon

    If the NuGet package is still in .NET Framework (not .NET Standard) it’s mean that you cannot run test on linux build server?

    • I think this is the main benefit of using .NET Core 2.0 that it will allow you to do so. However, you need to install the .NET Core 2.0 Runtime on the Linux as well.

      • Christophe Mandrillon

        Does it work? I mean, .NET Core 2.0 allow to reference .NET Framework libraries, but does it will work on Linux, since the library use a reference that is not present on the system?