Originally ported from Java’s JUnit, NUnit provides a powerful platform for performing unit tests. Combined with the capabilities of Selenium, you can quickly start testing your web application. If you bring our platform into the mix, you now have hundreds of browsers at your disposal. Here, we will get you started with a single NUnit test to a simple Angular ToDo application. We will then move up to the point of running 2 tests in parallel for faster execution.
Get set up
Let's get started by installing some necessary dependencies. From NuGet, we will install NUnit
and Selenium-WebDriver
. From there, we can start putting our tests together. There are a couple components we will need. We will separate starting/closing our WebDriver and running our tests. For starting up, we can use this code to generate our WebDriver:
C#
using System;
using System.IO;
using System.Net;
using System.Text;
using NUnit.Framework;
using OpenQA.Selenium.Remote;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Collections.Specialized;
using OpenQA.Selenium;
namespace CBT_NUnit
{
[TestFixture]
publicclass CBTAPI
{
protected RemoteWebDriver driver;
protectedstring browser;
protectedstring session_id;
publicstring BaseURL = "https://crossbrowsertesting.com/api/v3/selenium";
publicstring username = "YOUR_USERNAME";
publicstring authkey = "YOUR_AUTHKEY";
public CBTAPI()
{
}
public CBTAPI(string browser)
{
this.browser = browser;
}
[SetUp]
publicvoid Initialize()
{
var caps = new RemoteSessionSettings();
caps.AddMetadataSetting("name", "NUnit Test");
caps.AddMetadataSetting("username", username);
caps.AddMetadataSetting("password", authkey);
caps.AddMetadataSetting("platform", "Windows 10");
switch (browser)
{
// These all pull the latest version by default
// To specify version add SetCapability("version", "desired version")
case "chrome":
caps.AddMetadataSetting("browserName", "Chrome");
break;
case "ie":
caps.AddMetadataSetting("browserName", "Internet Explorer");
break;
case "edge":
caps.AddMetadataSetting("browserName", "MicrosoftEdge");
break;
case "firefox":
caps.AddMetadataSetting("browserName", "Firefox");
break;
default:
caps.AddMetadataSetting("browserName", "Chrome");
break;
}
driver = new RemoteWebDriver(new Uri("http://hub.crossbrowsertesting.com:80/wd/hub/"), caps);
}
[TearDown]
publicvoid Cleanup()
{
var session_id = driver.SessionId.ToString();
driver.Quit();
setScore(session_id, "pass");
}
publicvoid setScore(string sessionId, string score)
{
string url = BaseURL + "/" + sessionId;
// Encode the data to be written
ASCIIEncoding encoding = new ASCIIEncoding();
string data = "action=set_score&score=" + score;
byte[] putdata = encoding.GetBytes(data);
// Create the request
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
request.Method = "PUT";
request.Credentials = new NetworkCredential(username, authkey);
request.ContentLength = putdata.Length;
request.ContentType = "application/x-www-form-urlencoded";
request.UserAgent = "HttpWebRequest";
// Write data to stream
Stream newStream = request.GetRequestStream();
newStream.Write(putdata, 0, putdata.Length);
WebResponse response = request.GetResponse();
newStream.Close();
}
}
}
Notice the use of the decorators used by NUnit, [SetUp]
and [TearDown]
. SetUp
is used before each test unit is performed, and in this case we are instantiating the WebDriver
object based of a browser parameter. After it is pointed to our hub with our os/browser api names, you should see the changes reflected in the app. The TearDown
decorator is code that is run after each test is performed. In this case, we are making the call to driver.Quit()
which ends the test session in our app. Additionally, we are using the API here to set the score to pass if we made it through our tests successfully. This is great for quickly seeing the results of your tests from our app rather than just from Visual Studio.
Write tests
At this point, we have only created the driver object. Now let's create the test to be performed:
C#
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using NUnit.Framework;
using OpenQA.Selenium.Remote;
using System.Collections.Generic;
using OpenQA.Selenium;
namespace CBT_NUnit
{
[TestFixture("chrome")]
publicclass BasicTest : CBTAPI
{
public BasicTest(string browser) : base(browser) { }
[Test]
publicvoid TestTodos()
{
driver.Navigate().GoToUrl("http://crossbrowsertesting.github.io/todo-app.html");
// Check the title
driver.FindElement(By.Name("todo-4")).Click();
driver.FindElement(By.Name("todo-5")).Click();
// If both clicks worked, then the following List should have length 2
IList<IWebElement> elems = driver.FindElements(By.ClassName("done-true"));
// so we'll assert that this is correct.
Assert.AreEqual(2, elems.Count);
driver.FindElement(By.Id("todotext")).SendKeys("run your first selenium test");
driver.FindElement(By.Id("addbutton")).Click();
// lets also assert that the new todo we added is in the list
string spanText = driver.FindElement(By.XPath("/html/body/div/div/div/ul/li[6]/span")).Text;
Assert.AreEqual("run your first selenium test", spanText);
driver.FindElement(By.LinkText("archive")).Click();
elems = driver.FindElements(By.ClassName("done-false"));
Assert.AreEqual(4, elems.Count);
}
}
}
Here, we are creating a test that clicks a few check boxes, creates a new ToDo, and archives the ones we checked. Additionally, its asserting throughout the test to ensure that the changes we made worked correctly. Notice also that our test extends our CBTAPI class so that the driver instantiation and tear down is handled outside of our class. To run it, simply right click within the method and click "Run Test". Switch over to the app, and you can see it running.
Parallel testing
Want to get the same job done in half of the time? That is where parallel testing comes into play, and we are all for parallel testing at CrossBrowserTesting. NUnit makes it simple by providing a single additional decorator, [Parallelizable(ParallelScope.Fixtures)]
. Additionally, we will give our test a few more browser parameters. Check out the below code:
C#
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using NUnit.Framework;
using OpenQA.Selenium.Remote;
using System.Collections.Generic;
using OpenQA.Selenium;
namespace CBT_NUnit
{
[TestFixture("chrome")]
[TestFixture("firefox")]
[Parallelizable(ParallelScope.Fixtures)]
publicclass ParallelTest : CBTAPI
{
public ParallelTest(string browser) : base(browser) { }
[Test]
publicvoid TestTodos()
{
driver.Navigate().GoToUrl("http://crossbrowsertesting.github.io/todo-app.html");
// Check the title
driver.FindElement(By.Name("todo-4")).Click();
driver.FindElement(By.Name("todo-5")).Click();
// If both clicks worked, then the following List should have length 2
IList<IWebElement> elems = driver.FindElements(By.ClassName("done-true"));
// so we'll assert that this is correct.
Assert.AreEqual(2, elems.Count);
driver.FindElement(By.Id("todotext")).SendKeys("run your first selenium test");
driver.FindElement(By.Id("addbutton")).Click();
// Let's also assert that the new todo we added is in the list
string spanText = driver.FindElement(By.XPath("/html/body/div/div/div/ul/li[6]/span")).Text;
Assert.AreEqual("run your first selenium test", spanText);
driver.FindElement(By.LinkText("archive")).Click();
elems = driver.FindElements(By.ClassName("done-false"));
Assert.AreEqual(4, elems.Count);
}
}
}
Running this should start a test to two different browsers at once. This halves the execution time. Increasing your level of parallelization similarly cuts time and makes your job easier :)
For examples and source code to this tutorial, check out our NUnit GitHub Repository
If you have any trouble getting setup, do not hesitate to reach out to us. We are happy to help.
See Also
Test Frameworks and Tools
About Selenium Testing
Selenium and C#
SpecFlow