{!See https://docs.google.com/document/d/1takg_GmIBBKKTj-GHZCwzxohpQz7Bhekivkk72kYMtE/edit for reference implementation of OneTrust, dataLayer and GTM} {!OneTrust Cookies Consent} {!OneTrust Cookies Consent end} {!dataLayer initialization push} {!dataLayer initialization push end} {!Google Tag Manager} {!Google Tag Manager end} 15. Test cases | Test Framework | 1.3.9
docs.unity3d.com
Search Results for

    Show / Hide Table of Contents

    15. Test cases

    Learning objectives

    This section will cover [TestCase] and similar NUnit attributes and how to work with them in UnityTests.

    Intro and motivation

    NUnit has a few tools for parameterized tests, which can be used to specify test cases with variating parameters. This can drastically reduce the amount of repeated code and make the test cleaner to use.

    An example of a parameterized test using the [TestCase] attribute:

    [Test]
    [TestCase(49, "a string", true)]
    [TestCase(9, "something", false)]
    public void MyTest(int firstValue, string secondValue, bool expectedOutcome)
    {
     ...
    }  
    

    This will generate two tests, each with a different input to the method body.

    In addition to the [TestCase] attribute, NUnit also has a [Values] attribute, which specifies a set of values on each individual input. An example of such is:

    [Test]
    public void MyTest([Values(49, 9)]int firstValue, [Values("a string", "something")]string secondValue)
    {
     ...
    }  
    

    When specifying multiple input parameters, they are treated as combinatorial. That means that each combination of them will be tested. For the above example, that will result in a total of 4 cases:

    MyTest(49, "a string")
    MyTest(49, "something")
    MyTest(9, "a string")
    MyTest(9, "something") 
    

    This can easily explode into many combinations. The combinations might not all be valuable and would just waste time, so use this with care.

    For both the [TestCase] and [Values] attributes, there is a more dynamic version called [TestCaseSource] and [ValueSource] accordingly. These each take in a static method or array, returning a collection of objects.

    Of these 4 methods, the [ValueSource] attribute is currently the only one supported by [UnityTest]. Since this would produce combinational tests, if multiple arguments with [ValueSource] are provided, then it is recommended to make a test case struct, if multiple arguments are needed for the test. An example of such could look like this:

    [UnityTest]
    public IEnumerator AddAsyncCalculatesCorrectValue([ValueSource(nameof(TestCases))] TestCase testCase)
    {
     ...
    }
    
    private static IEnumerable TestCases()
    {
     yield return new TestCase {value1 = 4, value2 = "a string"};
     yield return new TestCase {value1 = 8, value2 = "another string"};
    }
    
    public struct TestCase
    {
     public int value1;
     public string value2;
    
     public override string ToString()
     {
      return $"{value1}, {value2}";
     }
    }
    

    Exercise

    In the sample 15_TestCases a class is set up with some basic math. It has two methods:

    • Add which takes two integers and adds them together.

    • AddAsync also adds two integers together, but does so asynchronously, yielding back an IEnumerator

    The task is to add tests for the two methods. The AddAsync method first returns the result after a few frames, so that will be best suited for a [UnityTest]. Note that it is not enough to yield back the IEnumerator, as the test framework does not curently support nested yields. Instead, create a loop to move over each element until it's done. At each step of the while loop, let the test yield back null.

    Hints

    • The ToString() implementation in the struct is there to provide readable info in the test runner treeview. Without it, it would just show the struct name as the test argument for every case.

    Solution

    A solution for the exercise is available in the sample 15_TestCases_Solution. Tests for both methods can be implemented as follows:

    [Test]
    [TestCase(24, 80, 104)]
    [TestCase(10, -15, -5)]
    [TestCase(int.MaxValue, 10, int.MinValue + 9)]
    public void AddCalculatesCorrectValue(int valueA, int valueB, int expectedResult)
    {
     var myClass = new MyClass();
    
     var result = myClass.Add(valueA, valueB);
     
     Assert.That(result, Is.EqualTo(expectedResult));
    }
    
    [UnityTest]
    public IEnumerator AddAsyncCalculatesCorrectValue([ValueSource(nameof(AdditionCases))] AddCase addCase)
    {
     var myClass = new MyClass();
    
     var enumerator = myClass.AddAsync(addCase.valueA, addCase.valueB);
     while (enumerator.MoveNext())
     {
      yield return null;
     }
     var result = enumerator.Current;
     
     Assert.That(result, Is.EqualTo(addCase.expectedResult));
    }
    
    private static IEnumerable AdditionCases()
    {
     yield return new AddCase {valueA = 24, valueB = 80, expectedResult = 104};
     yield return new AddCase {valueA = 10, valueB = -15, expectedResult = -5};
     yield return new AddCase {valueA = int.MaxValue, valueB = 10, expectedResult = int.MinValue + 9};
    }
    
    public struct AddCase
    {
     public int valueA;
     public int valueB;
     public int expectedResult;
    
     public override string ToString()
     {
      return $"{valueA} + {valueB} = {expectedResult}";
     }
    }
    

    Did you find this page useful? Please give it a rating:

    Thanks for rating this page!

    Report a problem on this page

    What kind of problem would you like to report?

    • This page needs code samples
    • Code samples do not work
    • Information is missing
    • Information is incorrect
    • Information is unclear or confusing
    • There is a spelling/grammar error on this page
    • Something else

    Thanks for letting us know! This page has been marked for review based on your feedback.

    If you have time, you can provide more information to help us fix the problem faster.

    Provide more information

    You've told us this page needs code samples. If you'd like to help us further, you could provide a code sample, or tell us about what kind of code sample you'd like to see:

    You've told us there are code samples on this page which don't work. If you know how to fix it, or have something better we could use instead, please let us know:

    You've told us there is information missing from this page. Please tell us more about what's missing:

    You've told us there is incorrect information on this page. If you know what we should change to make it correct, please tell us:

    You've told us this page has unclear or confusing information. Please tell us more about what you found unclear or confusing, or let us know how we could make it clearer:

    You've told us there is a spelling or grammar error on this page. Please tell us what's wrong:

    You've told us this page has a problem. Please tell us more about what's wrong:

    Thank you for helping to make the Unity documentation better!

    Your feedback has been submitted as a ticket for our documentation team to review.

    We are not able to reply to every ticket submitted.

    In This Article
    • Learning objectives
    • Intro and motivation
    • Exercise
    • Hints
    • Solution
    Back to top
    Copyright © 2023 Unity Technologies — Trademarks and terms of use
    • Legal
    • Privacy Policy
    • Cookie Policy
    • Do Not Sell or Share My Personal Information
    • Your Privacy Choices (Cookie Settings)