App & Browser Testing Made Easy

Give your users a seamless experience by testing on 3000+ real devices and browsers. Don't compromise with emulators and simulators

Get Started free
Home Guide How to write Nunit Parameterized Test

How to write Nunit Parameterized Test

By Gurudatt S A, Community Contributor -

Nunit is a very popular unit testing framework for all .net languages. Nunit provides parametirization for its tests using which we can reuse the test for various data sets.

Nunit provides four different ways to pass paramertization to the test as seen below:

Nunit Parameterization

Let’s deep dive into each of these parameterization methods to make our tests more reusable and powerful.

Parameterization techniques in NUnit

There are Four ways to group the parameter and can be passed to the test in Nunit

  1. Inline – As Test Case Attribute
  2. Inline – As Random Attribute, Range Attribute, Values Attribute
  3. Separate – TestCaseSource Attribute
  4. Separate – ValueSource Attribute

Inline – As Test Case Attribute

In this technique, Nunit uses the TestCase attribute to pass the various data sets at Test level. This technique is helpful when we want to repeat complete test for various data sets. For the examples we’ll be using BrowserStack’s demo application

Attribute syntax is

[TestCase(“input1”, “input2”)]

For example,

using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using System.IO;
using System;
using OpenQA.Selenium.Support.UI;


namespace NunitSeleniumDemo
{

public class Tests
{
private IWebDriver driver;
[SetUp]
public void Setup()
{
String path = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..\\..\\..\\"));
driver = new ChromeDriver(path + "\\drivers");
driver.Manage().Window.Maximize();
driver.Url = "https://bstackdemo.com/";
}

[TestCase("OnePlus", "6 Product(s) found.")]
[TestCase("Google", "3 Product(s) found.")]
public void NunitSeleniumTest(String model, String message)
{


DefaultWait<IWebDriver> fluentWait = new DefaultWait<IWebDriver>(driver);
fluentWait.Timeout = TimeSpan.FromSeconds(5);
fluentWait.PollingInterval = TimeSpan.FromMilliseconds(250);
fluentWait.Until(driver => driver.Title == "StackDemo");
driver.FindElement(By.XPath($"//*[@class='checkmark' and contains(text(),'{model}')]")).Click();
driver.Manage().Timeouts().ImplicitWait = (TimeSpan.FromSeconds(6));
String searchResults = driver.FindElement(By.XPath("//*[@class='products-found']//span")).Text;
Assert.AreEqual(searchResults, $"{message}");
driver.FindElement(By.XPath($"//*[@class='checkmark' and contains(text(),'{model}')]")).Click();

}

[TearDown]
public void tearDown()
{
driver.Close();
driver.Quit();
}
}
}

In this example, reusing the same test for validating the search result after clicking a specific phone model.

As observed, first declaring the Attribute with the values you need to pass at test level

 [TestCase("OnePlus", "6 Product(s) found.")]
[TestCase("Google", "3 Product(s) found.")]

We receive these values as input parameters for our test method when Nunit runs, hence we declare two parameters for our test method

public void NunitSeleniumTest(String model, String message)

And now you can use these parameters in our code where the code clicks on the model and verifies the message

driver.FindElement(By.XPath($"//*[@class='checkmark' and contains(text(),'{model}')]")).Click();
driver.Manage().Timeouts().ImplicitWait = (TimeSpan.FromSeconds(6));
String searchResults = driver.FindElement(By.XPath("//*[@class='products-found']//span")).Text;
Assert.AreEqual(searchResults, $"{message}");
driver.FindElement(By.XPath($"//*[@class='checkmark' and contains(text(),'{model}')]")).Click();

In this way, you can reuse our test for various datasets.

Inline – As Random Attribute, Range Attribute, Values Attribute

Range Attribute

In this technique, Nunit allows two array parameters, which can be passed to the test method.

First parameter is the Values and the Second is the Range. Test repeats for all the Values provided for the range provided.

This can be used when you want to test various ranges for a given Value.

In the below example, the value is a selector, and the quantity is the range. With the given selector, test adds the Phone to the cart and validates the cart with the quantity.

using NUnit.Framework;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using System.IO;
using System;
using OpenQA.Selenium.Support.UI;


namespace NunitSeleniumDemo
{
public class InlineDemo
{

private IWebDriver driver;
[OneTimeSetUp]
public void Setup()
{
String path = Path.GetFullPath(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..\\..\\..\\"));
driver = new ChromeDriver(path + "\\drivers");
driver.Manage().Window.Maximize();
driver.Url = "https://bstackdemo.com/";
}

[Test]
public void checkQuantity([Values(".shelf-container")] String selector,
[Range(2,3,1)] int value)
{
DefaultWait<IWebDriver> fluentWait = new DefaultWait<IWebDriver>(driver);
fluentWait.Timeout = TimeSpan.FromSeconds(5);
fluentWait.PollingInterval = TimeSpan.FromMilliseconds(250);
fluentWait.IgnoreExceptionTypes(typeof(FormatException));
fluentWait.Until(driver => driver.Title == "StackDemo");
driver.FindElement(By.CssSelector($"{selector} .shelf-item:nth-of-type({value}) .shelf-item__buy-btn")).Click();
driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(120);
fluentWait.Until(driver => Int32.Parse(driver.FindElement(By.CssSelector(".float-cart__header .bag__quantity")).Text) == (value - 1));
int cartQty = Int32.Parse( driver.FindElement(By.CssSelector(".float-cart__header .bag__quantity")).Text);
Assert.AreEqual(cartQty, (value-1));
}

[OneTimeTearDown]
public void tearDown()
{
driver.Close();
driver.Quit();
}
}
}

Values Attribute

In this technique, Nunit allows two Values array parameters to be passed to the test. For every first value parameter, the Values in the Second parameter will be repeated.

Executing the below example

[Test]
public void inlineValueTest([Values(1,2)] int value1,
[Values(2, 3)] int value2)
{
Console.WriteLine("Value 1 is : " + value2);
Console.WriteLine("Value 2 is : " + value2);
}

The tests will be divided into 

Executing NUnit Parameterized Tests using Inline Value Attribute

Random Attribute

In this technique, the Nunit allows you to pass Random Attribute Array with 1 to 3 parameters

Syntax:

Random(int count)
Random(int minNumber, int MaxNumber, int count)

In the below example, we are specifying the Random number to be in range from 0 to 10 and repeat the test for every value 3 times

Executing the below example

[Test]
public void inlineValueTest([Values(1,2)] int value1,
[Random(0,10, 3)] int value2)
{
Console.WriteLine("Value 1 is : " + value2);
Console.WriteLine("Value 2 is : " + value2);
}

Nunit generates test with below combinations

Executing NUnit Parameterized Tests using Inline Random Attribute

Separate – TestCaseSource Attribute

In this technique, Nunit allows passing the data from different sources using Attribute [TestCaseSource]. This will allow us to keep the test data away from the test and can be used to read the data from External sources like a JSON file or Database.

[TestCaseSource(nameof(UserData))]
public void testReadingFromDataSource(String userName, String password)
{
Console.WriteLine("Value 1 is : " + userName);
Console.WriteLine("Value 2 is : " + password);
}

static object[] UserData =
{
new object[]
{
"username1",
"passsword1"
},
new object[]
{
"username2",
"passsword2"
}
};

As we can see our test data is coming from a method called UserData which returns an array of objects. Nunit will run the test for every returning object array

Separate – ValueSource Attribute

In this technique, Nunit allows us to pass named data source at test method parameter level using attribute [ValueSource].

[Test]
public void testReadingFromDataSource([ValueSource("UserData")] Object[] userObject)
{
Console.WriteLine("userName is : " + userObject[0]);
Console.WriteLine("password is : " + userObject[1]);

}

static object[] UserData =
{
new object[]
{
"username1",
"passsword1"
},
new object[]
{
"username2",
"passsword2"
}
};

As observed, the userData object now is applied to the test method’s parameter. Nunit will generate tests like below

Executing NUnit Parameterized Tests using Separate TestCaseSource Attribute

Conclusion

Parameterization is a powerful way of implementing our tests in a flexible way and can be reused for various data sets if designed properly. This will reduce the repetitive tests and also allows us to Maintain the tests keeping test data tidy. With TestCaseSource we can easily keep the test data outside the test which will make the test reusable against different test environments where test data might change.

 

 

 

Tags
Automation Testing Website Testing

Featured Articles

Getting started with Selenium and NUnit Framework: Tutorial

JUnit vs NUnit: Framework Comparison

App & Browser Testing Made Easy

Seamlessly test across 20,000+ real devices with BrowserStack