Using C# with Selenium WebDriver

In this post, I’ll focus on an ecosystem I haven’t given much attention: that of Windows and the use .NET related technologies. I’ll be covering the use of Selenium WebDriver within a C# context.

Many testers find themselves in Windows shops where there is preference for Visual Studio, Team Foundation Server and other Microsoft technologies. In those contexts, using C# as part of a test solution is not only justified but often mandated. The good news here is that, Windows-haters aside, Visual Studio is one of the best — if not the best — IDE on the market today. C# is an incredibly powerful language, learning much from Java and expanding upon it.

Even if you are someone who works in Java, Python or Ruby contexts, it can be good for you to see that test solutions like Selenium WebDriver are more than viable in a Windows context.

Getting Started

Before we get started, you’ll need to get the relevant parts of the ecosystem set up for you. I recommend reading the “Setting Up C#” section on my automation setup page. As mentioned there, since Visual Studio has fully functional free editions, in this post I’ll be assuming that you are using it.

Also, before getting started on the project, make sure you have a Firefox browser. Selenium is configured to work with Firefox by default. Selenium does support multiple drivers for different browsers and I’ll show you that in due course, but for now we’ll stick with minimum dependencies in our project.

First I’m going to take you through a very simple example using a console project, just to get you up and running and comfortable. Then we’ll move into a specific test project.

Create Console Project

In Visual Studio, create a new project (using the menu path File –> New –> Project). From the dialog, choose ‘Console Application’ (under Templates | Visual C# | Windows). Call the project SymbioteTest.

That’s going to give you a project with a Program.cs file. We’ll get into the contents of that shortly. For now, in the Solution Explorer (which, by default, is on the right side of your Visual Studio interface), right click on your project name and select ‘Manage NuGet Packages’. In the dialog that appears, search for the term “Selenium”. In the list that appears, you should see both Selenium.WebDriver and Selenium.Support. Install both, choosing the latest stable version of each (which should be the default).

After installation, you can see WebDriver and in the References section in the Solution Explorer. You’ll also see a file called packages.config. In that file, you’ll see something like the following:

Now let’s consider Program.cs. Your default file should look like this:

So let’s get started putting our own logic in place. At the end of the set of “using” statements, add the following:

This will allow you to use the Selenium components we just grabbed with NuGet. We’re going to instantiate an instance of the WebDriver interface. Add the following line to the Main method:

The IWebDriver interface allows you to not only control the browser by creating a particular browser instance (in this case, Firefox) but also to interact with web elements that appear in the browser. We’re going to use the instance we just created to navigate to a particular page. Add the following:

Now let’s see if it works! In your toolbar, you’ll see “Start” with a green arrow next to it. You can also go to the Debug menu and click Start Debugging (F5) or Start Without Debugging (CTRL + F5). This is a console application, remember, so you’ll see a console pop-up and then you should see the Firefox browser open and navigate to the page.

You’ll have to close the browser manually for the time being. Now let’s add two more simple commands just to wrap up this post. Modify your Program.cs as follows:

This just shows you that you can control aspects of the browser itself. Here I’m maximizing the browser window and then I’m immediately quitting the browser instance. Note that I’m quitting rather than just closing. You will see code examples with driver.Close();. The problem with the latter is that while it will close down the current browser instance it will not necessary free up that instance and shut down WebDriver’s connection to the browser. So make sure you Quit() if that’s actually what you want to do.

Create a Test Project

So now let’s create an entirely new project. Once again do the File –> New –> Project thing but this time, choose ‘Unit Test Project’ which you’ll find under Templates –> Visual C# –> Test. Give the project a name Symbiote.

With the project you created, you’ll get a file called UnitTest1.cs with the following contents:

Rename the file UnitTest1.cs to Login.cs. That should force the public class called UnitTest1 to Login.

Add WebDriver into Project

As with the previous project, right click on the project name and select ‘Manage NuGet Packages’ and then select the same ones you did before: Selenium.WebDriver and Selenium.Support. Also do a search for “Selenium Chrome” and then install Selenium.WebDriver.ChromeDriver. With the last one being included, you will see chromedriver.exe into your project.

The Test Runner

Notice this key line in the code that was generated for you:

This is the built in unit testing framework in Visual Studio. It is quite possible to use NUnit as well. Let’s first use the built in framework and then we’ll see about switching to NUnit in another post.

This UnitTest namespace has some test attributes that we’re going to use. You already saw two of the attributes in the code generated for you: [TestClass] and [TestMethod]. If you’ve worked with Java, these are very similar to annotations. The [TestClass] attribute is required in the Microsoft Unit Test Framework for any class that contains test methods. The [TestMethod] attribute is used to indicate specific methods inside a [TestClass] as containing code that must be run during a test execution.

For now let’s delete that existing [TestMethod] since ultimately we’re going to write our own logic. Your logic should look like this:

Test Explorer

Visual Studio has a test window that let’s you see at least some details about tests in a given file. Under the Test menu, go to Windows and select Test Explorer. This will open up a panel (by default on the left) that will show you all of the tests you have in the file that is currently being viewed. Specifically, it will show any methods that have the attribute [TestMethod].

Given that we just removed the only such method, this view will currently show you nothing but I’ll refer to it again once we put some logic in place.

Starting to Code

As we did with the our first example, we’re going to add some “using” statements. Add the following to the top of the code:

Now let’s consider what our test is going to do. I want to go to my Symbiote App launch page. I then went to click the Login pull down (at the top of the screen) and login as an administrator user, which simply means a login of “admin” and a password of “admin”. Once I do that, I’ll be taken to the home page of the application that has a navigation list. That navigation list is one way that I’ll know I logged in correctly.

As far as logging in the first thing I need to do is start a browser and call up the site. When the test is done, I’m going to want to clean up by closing the browser and quitting the WebDriver instance.

Initialize and Cleanup Test

Let’s kick the test off by starting up the browser. We’ll start with the Firefox browser and then try the same thing in the Chrome browser. As in the first script we worked on, you initialize the IWebDriver interface. We’ll be doing this in the [TestClass]. However, initializing the browser is something we might want to do with multiple tests. So we’re going to create a special method for this. Likewise, closing the browser down is something that multiple tests may have to rely on. So add the following to your Login.cs logic:

I’ve declared my IWebDriver instance variable and a URL for the site. I’ve done this outside of any methods so that I can use these in various methods. he [TestInitialize] attribute can be used to any method which you want to runs prior to running any [TestMethod] attribute methods. Likewise, the [TestCleanup] attribute method is what you want to run after [TestMethod] methods.

You’ll notice here that I’m using the FirefoxDriver just as we did in the previous example. This time around, however, we have added the ChromeDriver so if you did want to change this test to run on Chrome, you could just update line 12 from above to read:

Add Test Logic

Earlier I had you delete the auto-generated attribute [TestMethod] and the associated method. Now we’re going to add that back but, of course, put in our own logic. Any method with the [TestMethod] attribute will contains the actual code. Any such methods will, as I stated before, run after a method with attribute [TestInitialize]. Put the following method in place:

Now with that method in place, let’s build the project. You should be able to go to the Build menu and select Build Solution. You can also just press F6. Make sure you have the Test Explorer window that I mentioned earlier visible. After the build, you will see that the LoginAsAdmin method will now be displayed. This is happening because the method is annotated with the attribute [TestMethod].

To test the code, click on the ‘Run All’ option in the Test Explorer window. You will see new Firefox browser instance launched, the web site will be launched, and then the browser will be closed.

You can use the full power of Visual Studio here. For example, you can run that test in debug mode and you can put break points into your code and step through that. To run in debug mode you need to run test via Test Tool bar. Select the test in Test Explorer and Go to Test -> Debug -> Selected Tests.

Logging In

Now we will work on implementation of test steps themselves. Let’s consider what the login form looks like on my site:

In order to deal with these elements, you’re going to need to use the IWebElement interface. This interface represents any given HTML element on a web page. If you want to operate on something on a web page, you will be doing so in the context of an IWebElement instance. So let’s put the logic in place that will log a user in as the admin:

Notice the calls to By.Id which are passed arguments. Those arguments correspond to the id values of the HTML elements that I showed you in the HTML snippet from the Symbiote site.

That code logic should work in that if you run it now, you’ll see the site being logged in to. You’ll also see the test listed in Test Explorer show as green. However, one problem here is that I’m not actually checking for anything. So I don’t really have an assertion and thus I don’t really have a test. I just have a set of actions. As I mentioned, once you login you are on a home page that has a navigation list. So I’ll add a check that looks for that.

Do note that this will require you adding a “using” statement at the top:

This logic essentially waits ten seconds for a given element (in this case, the one with an id of “navlist”) to appear. If that element does not appear in that time span, then an exception is raised. This is effectively acting as an assertion to say that there was apparently a problem with verifying that you ended up in the right place.

You can do a more traditional assert approach along these lines:

That being said, this doesn’t have the benefit of the time waiting aspect. What I showed you earlier was an explicit wait but you can do an implicit wait as well, which is a setting you place on the driver that will work for all cases of elements attempting to be found by WebDriver. Here’s an example of what you could do (likely in your [TestInitialize] code):

This sets an implicit wait of ten seconds when looking for elements.

Welcome to the .NET Ecosystem!

This post has shown you how to get up and running with some very basic Selenium logic within the context of Visual Studio and C#. I’ll be doing further posts on this in the future. I’ll cover the use of NUnit as well as tools like SpecFlow, which bring some BDD to the C# world.

About Jeff Nyman

Anything I put here is an approximation of the truth. You're getting a particular view of myself ... and it's the view I'm choosing to present to you. If you've never met me before in person, please realize I'm not the same in person as I am in writing. That's because I can only put part of myself down into words. If you have met me before in person then I'd ask you to consider that the view you've formed that way and the view you come to by reading what I say here may, in fact, both be true. I'd advise that you not automatically discard either viewpoint when they conflict or accept either as truth when they agree.
This entry was posted in Automation, C#, Selenium. Bookmark the permalink.

Leave a Reply

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