A lot of testers avoid any consideration of C# because it’s a Microsoft created language and the assumption is that it only has relevance on Windows. That’s not true. Just as Java learned a lot (and corrected a lot) from C and C++, C# did something similar with Java. Here I want to focus on how you can use C# on other platforms by creating a test solution in Xamarin.
To play along, what you can do is download the MonoDevelop package for Xamarin Studio. There’s sometimes confusion about MonoDevelop and Xamarin. In a nutshell, MonoDevelop became Xamarin Studio. The main difference is that while MonoDevelop was essentially the .NET compiler implementations on non-Windows platforms, the inclusion of it into Xamarin Studio brought in the possibility to develop iOS and Android applications.
I gave you a walkthrough of some aspects in the previous post on Using C# with Selenium WebDriver, so this time around I’m going to use much of the same coding but this time I’ll do so in an NUnit context. While I’m doing this in Xamarin Studio, you could be creating the same project in Windows Visual Studio. The nice thing about Xamarin Studio is that, unlike Visual Studio, you can use it on Windows, Mac, and Linux.
Incidentally, you can also get Visual Studio Code, which runs on Windows, Mac, and Linux. Do note that this is not the full Visual Studio but rather a different IDE with many Visual Studio features. This is not something I would be using for the project we’re talking about here but you can use it to practice with C# code.
Create the Project
In Xamarin Studio, go the menu choice File –> New –> Solution. Or you can click on the “New Solution” widget, which should be at the top left of your Xamarin interface. In the Dialog, go to Other and select .NET. From there choose NUnit Library Project.
While I’m sticking with Xamarin for this post, I’ll just note that in Visual Studio you would simply do File –> New –> Project. Then, in the New Project dialog, select Visual C# and then Test. Within there, you’ll see Unit Test Project. Note that Visual Studio — perhaps interestingly — does not come with a template for NUnit, but rather it’s own unit test framework. (That’s what I showed in the previous post on this topic.) Microsoft does have an NUnit Project Template.
If you install that, you’ll then have an NUnit Test Project available. That being said, you’re often better installing it via Tools –> Extensions and Updates.Name the project you are going to create Symbiote. Click “Create”.
Install the Packages
Once your project is set up, right click the project name. Then go to Add –> Add NuGet Packages. In the dialog search for “Selenium”. Select “Selenium WebDriver” and “Selenium WebDriver Support Classes” and then click “Add Packages”.
Starting Code
What should happen is that you end up with the following in a file called Test.cs (or NUnitTest1.cs in Visual Studio):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
using NUnit.Framework; using System; namespace Symbiote { [TestFixture ()] public class Test { [Test ()] public void TestCase () { } } } |
In my last post I showed you that Visual Studio’s built in test framework uses [TestClass]. NUnit uses [TestFixture]. Likewise, while Visual Studio’s UnitTest uses [TestMethod] for any methods that are tests, NUnit uses [Test]. The empty parentheses in both are indications that they can be parameterized. This gets into a more involved subject so I’ll hold off on parameterizing methods for now. As a note, only the Xamarin Studio NUnit template inserts the empty parentheses; you won’t see that in Visual Studio. For the rest of this post, I’ll strip those out.
Notice how the project template named the methods fairly generically: Test and TestCase respectively. Let’s change those to Symbiote and LoginAsAdmin. Also, let’s add our using statements for OpenQA.Selenium and OpenQA.Selenium.Firefox. Your code should now look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
using NUnit.Framework; using System; using OpenQA.Selenium; using OpenQA.Selenium.Firefox; namespace Symbiote { [TestFixture] public class Symbiote { [Test] public void LoginAsAdmin () { } } } |
Add Setup and Teardown
In the previous post, with Visual Studio’s UnitTest I showed how you could use [TestInitialize] and [TestCleanup] attributes on methods to indicate logic that should run before all tests and after all tests. NUnit has something similar but calls the attributes [SetUp] and [TearDown] respectively. Let’s add the same code from the last post. Your code will look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
using NUnit.Framework; using System; using OpenQA.Selenium; using OpenQA.Selenium.Firefox; namespace Symbiote { [TestFixture] public class Symbiote { private IWebDriver driver; string url = "http://symbiote-app.herokuapp.com/"; [SetUp] public void TestSetup () { driver = new FirefoxDriver (); driver.Navigate ().GoToUrl (url); } [TearDown] public void Cleanup () { driver.Quit (); } [Test] public void LoginAsAdmin () { } } } |
Now let’s try to run it. In Xamarin go to Run –> Run Unit Tests. You’ll see that a Firefox browser opens and closes but not much happens because we don’t have any logic.
Adding Test Logic
Now let’s add in the same logic we did in the last post to the LoginAsAdmin method. Your method should look like this:
1 2 3 4 5 6 7 8 |
[Test] public void LoginAsAdmin () { driver.FindElement (By.Id ("open")).Click (); driver.FindElement (By.Id ("username")).SendKeys ("admin"); driver.FindElement (By.Id ("password")).SendKeys ("admin"); driver.FindElement (By.Id ("login-button")).Click (); } |
If you run the test again, you’ll find it works just as it did in the previous post.
As you can hopefully see here there is very little difference with running Selenium-based tests with C# using either the built in UnitTest mechanism (via Visual Studio) or using NUnit (either in Visual Studio or Xamarin).
Beautifully explained Jeff
How do you use Excel to data drive your selenium test using Xamarin on a Mac?
Generally, I don’t. I don’t even use Excel primarily on Windows. Rather, what I do is use formats like CSV. That has the benefit of being valid on any platform but can be imported into tools like Excel or Open Office or any tool that recognizes CSV.
Excel is an example of what I would call an artifact crutch. It forces you to focus on the tool rather than what you really want to do, which, in this case, is to be able to reference data.
Even this being said, I generally don’t use CSV that much either. I’ll tend to use formats like JSON or YAML because they allow structuring elements to the format. Here’s an (admittedly simple) example:
https://github.com/jeffnyman/lucid_ruby/blob/master/config/environments.yml
A few others:
https://github.com/jeffnyman/lucid_ruby/blob/master/data/stardates/stardate_conditions.yml
https://github.com/jeffnyman/lucid_ruby/blob/master/data/overlord/bomb_messages.yml
How I use them requires some context. Regarding more numerical environments — say, lots of data (accounting, clinical trials, hedge funds) — then I generally do use CSV since what I need there is not so much a queryable structure but simply a delimited structure.
When I try to run the program it shows an error
Ah, yes, this is due to the change regarding how Firefox now uses Geckodriver. It actually has for a few years but at the time I wrote this article, that was not the case. Basically you have to make sure geckodriver is on your path. On Mac, for example, you can just do
brew install geckodriver
but, basically, you can just need a version of the geckodriver binary available to your automation. I will need to update these posts to reflect that.