Selenium with .NET Core


May 1, 2017 Update – http://www.dotnetcatch.com/2017/05/01/selenium-with-net-core-may-1-2017-update/


For the early adopters of .NET Core it can be tough waiting for third party dependendencies to provide updated Nuget packages with support for .NET Core.  We all know its early days and they will eventually be provided for any active projects but that doesn’t help us today.

Selenium is one of the big packages that the community is anxiously waiting for.  This is needed so we can write Selenium tests in a .NET Core C# project.  (There is no problem testing an ASP.NET Core web application, if you write your Selenium tests in a Full .NET Framework project.)

In June, Frederik Carlier (qmfrederik on Github) submitted a pull request (open source works!) to add .NET Core support to Selenium.  The SeleniumHQ core team is reviewing the request, evaluating the new .NET Core build tools and have promised they will eventually support .NET but they suspect it won’t be supported until VS 2017 hits GA.

https://github.com/SeleniumHQ/selenium/pull/2269

Thankfully, Frederik also published a Nuget package which provides .NET Core support for those of us who can’t wait.  Obviously, this is not a good long term solution but it does allow us to start building our Selenium tests in .NET Core and we can replace this package with the official Selenium package once .NET Core is officially supported.

http://www.nuget.org/packages/CoreCompat.Selenium.WebDriver/2.54.0-beta002

Demo TIme!

The remainder of this post will walk through how to get this working and prove out the solution on both Windows and Linux.  Its really not that hard to setup but hopefully this helps others get it up and running that much faster.

A Test Project

Create a new .NET Core class library in Visual Studio and then install the xUnit and CoreCompat.Selenium WebDriver Nuget packages.

 "dependencies": { "xunit": "2.2.0-beta2-build3300", "dotnet-test-xunit": "2.2.0-preview2-build1029", "CoreCompat.Selenium.WebDriver": "2.54.0-beta002" }, 

Next create a simple test class.  The xUnit documentation provides really great documentation for this:

https://xunit.github.io/docs/getting-started-dotnet-core.html#run-tests-console

In the test class/method, instantiate the Selenium RemoteWebDriver and perform some UI automation.  I used some sample code I found on the web:

 public class On_google_search_page : IDisposable { private IWebDriver _driver; public On_google_search_page() { var capabilities = DesiredCapabilities.InternetExplorer(); _driver = new RemoteWebDriver(new Uri("http://localhost:5555"), capabilities); } public void Dispose() { _driver.Dispose(); } [Fact] public void Should_find_search_box() { _driver.Navigate().GoToUrl("http://www.google.com/ncr"); Console.WriteLine(_driver.Title); IWebElement query = _driver.FindElement(By.Name("q")); query.SendKeys("TestingBot"); query.Submit(); Console.WriteLine(_driver.Title); _driver.Quit(); } } 

Selenium Server Setup

To execute this test we need to have a Selenium server running.  There are multiple options here but I found the InternetExplorerDriver to be the easiest to setup on a Windows development machine.  Its a single executable that you execute to get a server up and running at http://localhost:5555 by default.

 >IEDriverServer.exe Started InternetExplorerDriver server (32-bit) 2.53.1.0 Listening on port 5555 Only local connections are allowed 

If you navigate to this URL you will see the server is running:

image

Executing Tests in Windows

For testing in Windows you can set the RemoteWebDriver URI to the default address above and it just works.  You can execute tests from VisualStudio:

image

Or using the dotnet CLI command dotnet test:

 >dotnet test Project seleniumindotnetcoretest (.NETCoreApp,Version=v1.0) was previously compiled. Skipping compilation. xUnit.net .NET CLI test runner (64-bit .NET Core win7-x64) Discovering: seleniumindotnetcoretest Discovered: seleniumindotnetcoretest Starting: seleniumindotnetcoretest Google TestingBot - Google Search Finished: seleniumindotnetcoretest === TEST EXECUTION SUMMARY === seleniumindotnetcoretest Total: 1, Errors: 0, Failed: 0, Skipped: 0, Time: 15.558s SUMMARY: Total: 1 targets, Passed: 1, Failed: 0. 

I was little surprised this all just worked the very first time with so little effort.  I almost stopped here but then decided I couldn’t write this blog post without also proving the tests can be run in Linux successfully as well.

Now in Linux via Docker

I wasn’t sure how to handle this at first but then remembered Docker and decided this was a perfect use case.  To be clear I’m very new to Docker so there may be a better way to do this but this seemed reasonably easy to me. I had previously installed Docker on my personal Surface 3 with Windows 10 using the Docker for Windows installer which worked perfectly.  (See my post on Accessing a Docker Container from the Docker Windows Host for more details).  For this post, I was testing from my work laptop running Windows 7 which the Docker for Windows installer doesn’t support.  Sad smile

That’s no problem though, Docker also provides the Docker Toolbox for older versions of Windows. The toolbox utilizes and automatically installs VirtualBox to run the Linux Docker Host.  This was only slightly less convenient/easy than Docker for Windows which uses Hyper-V.

Create a Container

Once you have Docker installed locally, you need a Dockerfile to instruct Docker how to create a container image and run it.  Add a file named Dockerfile to the root of the project with the following contents:

 FROM microsoft/dotnet:1.0.1-sdk-projectjson WORKDIR /dotnetapp # copy and build everything else COPY . . RUN dotnet restore ENTRYPOINT ["dotnet", "test"] 

The first line instructs Docker to use a base image with the .NET Core 1.0.1 runtime and SDK which can be found on DockerHub.  Next the container working directory is set and we copy our test project code to the container.  Then we call dotnet restore to get all our package dependencies.  Finally we set our entry point to call dotnet test from the Linux Docker container.

Selenium Server Changes

If you remember the early output from the InternetExplorerDriver Selenium server it specified the server would only be accessible locally.  Now that we are running the tests in a Docker container on a virtual network the tests would fail to connect to the existing server without changes.

So we can stop the server with CTRL+C and restart it with a few more arguments to support this use case:

 >IEDriverServer.exe /host=192.168.99.1 /whitelisted-ips=192.168.99.100,192.168.99.1,10.40.20.28,10.40.73.18,192.168.56.1,10.0.10.1 Started InternetExplorerDriver server (32-bit) 2.53.1.0 Listening on port 5555 Bound to network adapter with IP address 192.168.99.1 IP addresses allowed to connect are 192.168.99.100,192.168.99.1,10.40.20.28,10.40.73.18,192.168.56.1,10.0.10.1 

Here we specify we want the server to listen on the VirtualBox Host-Only Network IP 192.168.99.1 and provide a list of IPs to whitelist.  I defined this list by running ipconfig from the commandline of my development machine to get a list of all the IPs for this machine and also included the IP of the Docker Host. I found this IP by connecting to the Docker host VM in VirtualBox and running ifconfig.  (I’m sure there is a better way to find this.)

Now we can update our test class to use the 192.168.99.1 IP instead of localhost and we can run the tests from Windows or the Linux container.

Running the Container

Finally we can build and then run our container by opening the Docker Terminal, navigating to the path of our test project and running docker build/run.

 $ docker build -t seleniumtest . Sending build context to Docker daemon 513.5 kB Step 1 : FROM microsoft/dotnet:1.0.1-sdk-projectjson ---> 6434cf84b3bc Step 2 : WORKDIR /dotnetapp ---> Using cache ---> 0b447f7d46a1 Step 3 : COPY . . ---> f39d735b7442 Removing intermediate container eb8eb31e3b7a Step 4 : RUN dotnet restore ---> Running in 9baa7ca67dc1 log : Restoring packages for /dotnetapp/project.json... ... Removing intermediate container 9baa7ca67dc1 Step 5 : ENTRYPOINT dotnet test ---> Running in 6f94d902b066 ---> 5fc9daf1efdf Removing intermediate container 6f94d902b066 Successfully built 5fc9daf1efdf $ docker run -it seleniumtest Project dotnetapp (.NETCoreApp,Version=v1.0) will be compiled because the version or bitness of the CLI changed since the last build Compiling dotnetapp for .NETCoreApp,Version=v1.0 Compilation succeeded. 0 Warning(s) 0 Error(s) Time elapsed 00:00:01.4217177 xUnit.net .NET CLI test runner (64-bit .NET Core debian.8-x64) Discovering: dotnetapp Discovered: dotnetapp Starting: dotnetapp Google TestingBot - Google Search Finished: dotnetapp === TEST EXECUTION SUMMARY === dotnetapp Total: 1, Errors: 0, Failed: 0, Skipped: 0, Time: 8.481s SUMMARY: Total: 1 targets, Passed: 1, Failed: 0. 

During execution the dotnet test call connects to the server on my Windows OS, which open an IE browser and runs the tests.  From the output above you can see the test passes successfully.

Summary

You can author Selenium tests in .NET Core and run those tests on Windows and Linux today using Frederik’s CoreCompat.Selenium.WebDriver Nuget package.  I’m sure there will be edge cases that have not been addressed but hopefully this is a valuable short term solution that folks can start using today ahead of the official support.

None of this would be possible without Frederik’s work so please send him a quick thank you on GitHub or Twitter when you get a chance.

If you want to test this for yourself, the source for my working solution is on Github at https://github.com/rschiefer/SeleniumInDotNetCoreTest.  Check it out!

If this post was helpful and/or you try this solution please leave a comment below to share your feedback/experience.

Happy testing/coding!

10 thoughts on “Selenium with .NET Core

    1. The Selenium server is hosted in Windows if you are using the InternetExplorerDriver but you can execute the tests from any OS that support .NET Core. The last part of the blog post proves that the tests will execute on Linux and leverage the remote Windows server to automate a browser. You could swap the InternetExplorerDriver with any other Selenium driver on any OS they support.

  1. Hi Am trying to get a test automation framework working using dotNetCore, Selenium Webdriver, PhantomJS on a ReactJS web app but the selenium driver is not finding the elements, tried many locator types to no avail. Any suggestions on either a different headless browser type?

Leave a Reply