Data Driven Testing with Nunit using JSON

Overview

Data driven testing is supported by Nunit by using [TestCase] and [TestCaseSource] attribute (https://docs.nunit.org/articles/nunit/writing-tests/attributes/testcasesource.html). It requires you to define another class to contain test data. In real world, there will be many situations you will need to use JSON file as your data.

In real world, there will be many situations you will need to use JSON file as your data.

But Nunit does not support it natively. You still need some hacking here!

Examples

Firstly create a Console App through Visual Studio and add this to your nuget package manager (your .csproj file) to get Nhamcrest and its adapter for Nunit framework.To help you fully understand how to use JSON file as test data in Nunit, I will go through the real problem. Consider you have to test the login feature of this website “https://saucedemo.com

You have to test if all there above account is valid for login. You can consider store these username and password in a JSON file and parse it to object and get data for running testcases. This is Data-Driven Testing in Automation Testing. Use multiple kinds of data for our testcase.

Install

Create a Nunit Test Project using Visual Studio first. After that, install below dependecies through Nuget Manager:

<ItemGroup>
    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
    <PackageReference Include="NUnit" Version="3.13.3" />
    <PackageReference Include="NUnit3TestAdapter" Version="4.2.1" />
    <PackageReference Include="NUnit.Analyzers" Version="3.3.0" />
    <PackageReference Include="coverlet.collector" Version="3.1.2" />
    <PackageReference Include="Selenium.WebDriver" Version="4.8.1" />
    <PackageReference Include="WebDriverManager" Version="2.16.2" />
</ItemGroup>

In this article, I will not focus on explaining how to use all of above dependecies. If you are fresher, maybe you still need to do research to fully understand this example.

Usage

1. Firstly, create a BaseDataSource class in DataConfig folder as below:

using Newtonsoft.JSON;
using Newtonsoft.JSON.Linq;
using System.Collections;
using System.Reflection;

namespace NunitJSONData.DataConfig
{
    public class BaseDataSource<T> : IEnumerable
    {
        protected virtual string DataFolder => "TestData";

        protected virtual string BaseFile => "base";

        private string GetFilePath()
        {
            var directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            if (directoryName == null)
                throw new Exception("Couldn't get assembly directory");

            return Path.Combine(directoryName, DataFolder, $"{BaseFile}.JSON");
        }

        public IEnumerator GetEnumerator()
        {
            var testFixtureParams = JSONConvert.DeserializeObject<JObject>(File.ReadAllText(GetFilePath()))!;
            var genericItems = testFixtureParams[$"{typeof(T).Name}"]!.ToObject<IEnumerable<T>>()!;

            foreach (var item in genericItems)
            {
                yield return new object[] { item! };
            }
        }
    }
}

=> This class extends from IEnumrable interface. It has a generic type called T. T is the mapped class for JSON object.

DataFolder property returns the folder name of JSON file

BaseFile property returns the name of JSON file. You can name it anything. It can also be an empty JSON file.

GetFilePath() method will return path to your JSON file.

GetEnumrator() will parse JSON data to new .NET object which will be mapped to specific class later (T class). Finally the method will return a collection contains all newly created object

2. Create a CredentialDataSource class in same folder as below:

namespace NunitJSONData.DataConfig
{
    public class CredentialDataSource<T> : BaseDataSource<T>
    {
        protected override string BaseFile => "credential";
    }
}

=> This class must extends from BaseDataSource and override the BaseFile property. Its value is the specific JSON file. In this situation, it is “credential.JSON” file which contains username and password you want to store.

3. Next, create a class called Credential to map with JSON object:

namespace NunitJSONData.DataConfig
{
    public class Credential
    {
        public string? Username { get; set; }

        public string? Password { get; set; }
    }
}

=> Please note that class name and property name must be strictly equal to property of JSON Object (case sensitive). If not, JSON object won’t be parsed.

4. Create a TestData folder which contains our JSON file

“base.json” can be an empty JSON object

And “credential.json” will be like this:

{
  "Credential": [
    {
      "Username": "standard_user",
      "Password": "secret_sauce"
    },
    {
      "Username": "problem_user",
      "Password": "secret_sauce"
    },
    {
      "Username": "performance_glitch_user",
      "Password": "secret_sauce"
    }
  ]
}

=> Note that properties are all uppercase (must be same as property name of Credential class). Key “Credential” will contain an array with three JSON objects

5. Finally, create a test class and use it with [TestCaseSource] attribute of Nunit as below:

[TestCaseSource(typeof(CredentialDataSource<Credential>))]
    public void TC_01(Credential credential)
    {
        driver.FindElement(By.CssSelector("#user-name")).SendKeys(credential.Username);

        driver.FindElement(By.CssSelector("#password")).SendKeys(credential.Password);

        driver.FindElement(By.CssSelector("#login-button")).Click();

        Assert.That(driver.FindElement(By.CssSelector("span.title")).Displayed, Is.True);
    }

=> It will run testcase three times corresponding to the number of JSON objects in above array.

Below is full code:

using NUnit.Framework;
using NunitJsonData.DataConfig;
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using WebDriverManager;
using WebDriverManager.DriverConfigs.Impl;

namespace NunitJsonData.TestCases;
public class Demo
{

    IWebDriver driver;

    [SetUp]
    public void SetUp()
    {
        new DriverManager().SetUpDriver(new ChromeConfig());

        driver = new ChromeDriver();
        driver.Url = "https://www.saucedemo.com/";
        driver.Manage().Window.Maximize();
        driver.Manage().Timeouts().ImplicitWait = TimeSpan.FromSeconds(10);
    }

    [TestCaseSource(typeof(CredentialDataSource<Credential>))]
    public void TC_01(Credential credential)
    {
        driver.FindElement(By.CssSelector("#user-name")).SendKeys(credential.Username);

        driver.FindElement(By.CssSelector("#password")).SendKeys(credential.Password);

        driver.FindElement(By.CssSelector("#login-button")).Click();

        Assert.That(driver.FindElement(By.CssSelector("span.title")).Displayed, Is.True);
    }

    [TearDown]
    public void TearDown()
    {
        if (driver is not null)
        {
            driver.Manage().Cookies.DeleteAllCookies();
            driver.Quit();
        }
    }
}

Conclusion

Nunit does not natively support json file as test data. But it is not complicated to read and parse json file with other library. You can download full code here. Anyway, thanks for watching!

Ask me anything