Commit af571a61 authored by BlackAngle233's avatar BlackAngle233
Browse files

212

parent 1d9b5391
# Edit Mode vs. Play Mode tests # Edit Mode vs. Play Mode tests
Let’s clarify a bit what Play Mode and Edit Mode test means from the Unity Test Framework perspective: Let’s clarify a bit what Play Mode and Edit Mode test means from the Unity Test Framework perspective:
## Edit Mode tests ## Edit Mode tests
**Edit Mode** tests (also known as Editor tests) are only run in the Unity Editor and have access to the Editor code in addition to the game code. **Edit Mode** tests (also known as Editor tests) are only run in the Unity Editor and have access to the Editor code in addition to the game code.
With Edit Mode tests it is possible to test any of your [Editor extensions](https://docs.unity3d.com/Manual/ExtendingTheEditor.html) using the [UnityTest](./reference-attribute-unitytest.md) attribute. For Edit Mode tests, your test code runs in the [EditorApplication.update](https://docs.unity3d.com/ScriptReference/EditorApplication-update.html) callback loop. With Edit Mode tests it is possible to test any of your [Editor extensions](https://docs.unity3d.com/Manual/ExtendingTheEditor.html) using the [UnityTest](./reference-attribute-unitytest.md) attribute. For Edit Mode tests, your test code runs in the [EditorApplication.update](https://docs.unity3d.com/ScriptReference/EditorApplication-update.html) callback loop.
> **Note**: You can also control entering and exiting Play Mode from your Edit Mode test. This allow your test to make changes before entering Play Mode. > **Note**: You can also control entering and exiting Play Mode from your Edit Mode test. This allow your test to make changes before entering Play Mode.
Edit Mode tests should meet one of the following conditions: Edit Mode tests should meet one of the following conditions:
* They should have an [assembly definition](./workflow-create-test-assembly.md) with reference to *nunit.framework.dll* and has only the Editor as a target platform: * They should have an [assembly definition](./workflow-create-test-assembly.md) with reference to *nunit.framework.dll* and has only the Editor as a target platform:
```assembly ```assembly
"includePlatforms": [ "includePlatforms": [
"Editor" "Editor"
], ],
``` ```
* Legacy condition: put tests in the project’s [Editor](https://docs.unity3d.com/Manual/SpecialFolders.html) folder. * Legacy condition: put tests in the project’s [Editor](https://docs.unity3d.com/Manual/SpecialFolders.html) folder.
## Play Mode tests ## Play Mode tests
You can run **Play Mode** tests as a [standalone in a Player](./workflow-run-playmode-test-standalone.md) or inside the Editor. Play Mode tests allow you to exercise your game code, as the tests run as [coroutines](https://docs.unity3d.com/ScriptReference/Coroutine.html) if marked with the `UnityTest` attribute. You can run **Play Mode** tests as a [standalone in a Player](./workflow-run-playmode-test-standalone.md) or inside the Editor. Play Mode tests allow you to exercise your game code, as the tests run as [coroutines](https://docs.unity3d.com/ScriptReference/Coroutine.html) if marked with the `UnityTest` attribute.
Play Mode tests should correspond to the following conditions: Play Mode tests should correspond to the following conditions:
* Have an [assembly definition](./workflow-create-test-assembly.md) with reference to *nunit.framework.dll*. * Have an [assembly definition](./workflow-create-test-assembly.md) with reference to *nunit.framework.dll*.
* Have the test scripts located in a folder with the .asmdef file. * Have the test scripts located in a folder with the .asmdef file.
* The test assembly should reference an assembly within the code that you need to test. * The test assembly should reference an assembly within the code that you need to test.
```assembly ```assembly
"references": [ "references": [
"NewAssembly" "NewAssembly"
], ],
"optionalUnityReferences": [ "optionalUnityReferences": [
"TestAssemblies" "TestAssemblies"
], ],
"includePlatforms": [], "includePlatforms": [],
``` ```
## Recommendations ## Recommendations
### Attributes ### Attributes
Use the [NUnit](http://www.nunit.org/) `Test` attribute instead of the `UnityTest` attribute, unless you need to [yield special instructions](./reference-custom-yield-instructions.md), in Edit Mode, or if you need to skip a frame or wait for a certain amount of time in Play Mode. Use the [NUnit](http://www.nunit.org/) `Test` attribute instead of the `UnityTest` attribute, unless you need to [yield special instructions](./reference-custom-yield-instructions.md), in Edit Mode, or if you need to skip a frame or wait for a certain amount of time in Play Mode.
### References ### References
It is possible for your Test Assemblies to reference the test tools in `UnityEngine.TestRunner` and `UnityEditor.TestRunner`. The latter is only available in Edit Mode. You can specify these references in the `Assembly Definition References` on the Assembly Definition. It is possible for your Test Assemblies to reference the test tools in `UnityEngine.TestRunner` and `UnityEditor.TestRunner`. The latter is only available in Edit Mode. You can specify these references in the `Assembly Definition References` on the Assembly Definition.
\ No newline at end of file
# Extending Unity Test Framework # Extending Unity Test Framework
It is possible to extend the Unity Test Framework (UTF) in many ways, for custom workflows for your projects and for other packages to build on top of UTF. It is possible to extend the Unity Test Framework (UTF) in many ways, for custom workflows for your projects and for other packages to build on top of UTF.
These extensions are a supplement to the ones already offered by [NUnit](https://github.com/nunit/docs/wiki/Framework-Extensibility). These extensions are a supplement to the ones already offered by [NUnit](https://github.com/nunit/docs/wiki/Framework-Extensibility).
Some workflows for extending UTF include: Some workflows for extending UTF include:
* [How to split the build and run process for standalone Play Mode tests](./reference-attribute-testplayerbuildmodifier.md#split-build-and-run-for-player-mode-tests) * [How to split the build and run process for standalone Play Mode tests](./reference-attribute-testplayerbuildmodifier.md#split-build-and-run-for-player-mode-tests)
* [How to run tests programmatically](./extension-run-tests.md) * [How to run tests programmatically](./extension-run-tests.md)
* [How to get test results](./extension-get-test-results.md) * [How to get test results](./extension-get-test-results.md)
* [How to retrieve the list of tests](./extension-retrieve-test-list.md)  * [How to retrieve the list of tests](./extension-retrieve-test-list.md) 
\ No newline at end of file
# How to get test results # How to get test results
You can receive callbacks when the active test run, or individual tests, starts and finishes. You can register callbacks by invoking `RegisterCallbacks` on the [TestRunnerApi](./reference-test-runner-api.md) with an instance of a class that implements [ICallbacks](./reference-icallbacks.md). There are four `ICallbacks` methods for the start and finish of both the whole run and each level of the test tree. You can receive callbacks when the active test run, or individual tests, starts and finishes. You can register callbacks by invoking `RegisterCallbacks` on the [TestRunnerApi](./reference-test-runner-api.md) with an instance of a class that implements [ICallbacks](./reference-icallbacks.md). There are four `ICallbacks` methods for the start and finish of both the whole run and each level of the test tree.
## Example ## Example
An example of how listeners can be set up: An example of how listeners can be set up:
> **Note**: Listeners receive callbacks from all test runs, regardless of the registered `TestRunnerApi` for that instance. > **Note**: Listeners receive callbacks from all test runs, regardless of the registered `TestRunnerApi` for that instance.
``` C# ``` C#
public void SetupListeners() public void SetupListeners()
{ {
var api = ScriptableObject.CreateInstance<TestRunnerApi>(); var api = ScriptableObject.CreateInstance<TestRunnerApi>();
api.RegisterCallbacks(new MyCallbacks()); api.RegisterCallbacks(new MyCallbacks());
} }
private class MyCallbacks : ICallbacks private class MyCallbacks : ICallbacks
{ {
public void RunStarted(ITestAdaptor testsToRun) public void RunStarted(ITestAdaptor testsToRun)
{ {
} }
public void RunFinished(ITestResultAdaptor result) public void RunFinished(ITestResultAdaptor result)
{ {
} }
public void TestStarted(ITestAdaptor test) public void TestStarted(ITestAdaptor test)
{ {
} }
public void TestFinished(ITestResultAdaptor result) public void TestFinished(ITestResultAdaptor result)
{ {
if (!result.HasChildren && result.ResultState != "Success") if (!result.HasChildren && result.ResultState != "Success")
{ {
Debug.Log(string.Format("Test {0} {1}", result.Test.Name, result.ResultState)); Debug.Log(string.Format("Test {0} {1}", result.Test.Name, result.ResultState));
} }
} }
} }
``` ```
> **Note**: The registered callbacks are not persisted on domain reloads. So it is necessary to re-register the callback after a domain reloads, usually with [InitializeOnLoad](https://docs.unity3d.com/Manual/RunningEditorCodeOnLaunch.html). > **Note**: The registered callbacks are not persisted on domain reloads. So it is necessary to re-register the callback after a domain reloads, usually with [InitializeOnLoad](https://docs.unity3d.com/Manual/RunningEditorCodeOnLaunch.html).
It is possible to provide a `priority` as an integer as the second argument when registering a callback. This influences the invocation order of different callbacks. The default value is zero. It is also possible to provide `RegisterCallbacks` with a class instance that implements [IErrorCallbacks](./reference-ierror-callbacks.md) that is an extended version of `ICallbacks`. `IErrorCallbacks` also has a callback method for `OnError` that invokes if the run fails to start, for example, due to compilation errors or if an [IPrebuildSetup](./reference-setup-and-cleanup.md) throws an exception. It is possible to provide a `priority` as an integer as the second argument when registering a callback. This influences the invocation order of different callbacks. The default value is zero. It is also possible to provide `RegisterCallbacks` with a class instance that implements [IErrorCallbacks](./reference-ierror-callbacks.md) that is an extended version of `ICallbacks`. `IErrorCallbacks` also has a callback method for `OnError` that invokes if the run fails to start, for example, due to compilation errors or if an [IPrebuildSetup](./reference-setup-and-cleanup.md) throws an exception.
\ No newline at end of file
# How to retrieve the list of tests # How to retrieve the list of tests
It is possible to use the [TestRunnerApi](./reference-test-runner-api.md) to retrieve the test tree for a given test mode (**Edit Mode** or **Play Mode**). You can retrieve the test tree by invoking `RetrieveTestList` with the desired `TestMode` and a callback action, with an [ITestAdaptor](./reference-itest-adaptor.md) representing the test tree. It is possible to use the [TestRunnerApi](./reference-test-runner-api.md) to retrieve the test tree for a given test mode (**Edit Mode** or **Play Mode**). You can retrieve the test tree by invoking `RetrieveTestList` with the desired `TestMode` and a callback action, with an [ITestAdaptor](./reference-itest-adaptor.md) representing the test tree.
## Example ## Example
The following example retrieves the test tree for Edit Mode tests and prints the number of total test cases: The following example retrieves the test tree for Edit Mode tests and prints the number of total test cases:
``` C# ``` C#
var api = ScriptableObject.CreateInstance<TestRunnerApi>(); var api = ScriptableObject.CreateInstance<TestRunnerApi>();
api.RetrieveTestList(TestMode.EditMode, (testRoot) => api.RetrieveTestList(TestMode.EditMode, (testRoot) =>
{ {
Debug.Log(string.Format("Tree contains {0} tests.", testRoot.TestCaseCount)); Debug.Log(string.Format("Tree contains {0} tests.", testRoot.TestCaseCount));
}); });
``` ```
# How to run tests programmatically # How to run tests programmatically
## Filters ## Filters
Run tests by calling `Execute` on the [TestRunnerApi](./reference-test-runner-api.md), and provide some execution settings that consists of a [Filter](./reference-filter.md). The `Filter` specifies what tests to run. Run tests by calling `Execute` on the [TestRunnerApi](./reference-test-runner-api.md), and provide some execution settings that consists of a [Filter](./reference-filter.md). The `Filter` specifies what tests to run.
### Example ### Example
The following is an example of how to run all **Play Mode** tests in a project: The following is an example of how to run all **Play Mode** tests in a project:
``` C# ``` C#
var testRunnerApi = ScriptableObject.CreateInstance<TestRunnerApi>(); var testRunnerApi = ScriptableObject.CreateInstance<TestRunnerApi>();
var filter = new Filter() var filter = new Filter()
{ {
testMode = TestMode.PlayMode testMode = TestMode.PlayMode
}; };
testRunnerApi.Execute(new ExecutionSettings(filter)); testRunnerApi.Execute(new ExecutionSettings(filter));
``` ```
## Multiple filter values ## Multiple filter values
It is possible to specify a more specific filter by filling out the fields on the `Filter` class in more detail. It is possible to specify a more specific filter by filling out the fields on the `Filter` class in more detail.
Many of the fields allow for multiple values. The runner tries to match tests against at least one of the values provided and then runs any tests that match. Many of the fields allow for multiple values. The runner tries to match tests against at least one of the values provided and then runs any tests that match.
### Example ### Example
In this example, the API runs tests with full names that fit either of the two names provided: In this example, the API runs tests with full names that fit either of the two names provided:
``` C# ``` C#
var api = ScriptableObject.CreateInstance<TestRunnerApi>(); var api = ScriptableObject.CreateInstance<TestRunnerApi>();
api.Execute(new ExecutionSettings(new Filter() api.Execute(new ExecutionSettings(new Filter()
{ {
testNames = new[] {"MyTestClass.NameOfMyTest", "SpecificTestFixture.NameOfAnotherTest"} testNames = new[] {"MyTestClass.NameOfMyTest", "SpecificTestFixture.NameOfAnotherTest"}
})); }));
``` ```
## Multiple filter fields ## Multiple filter fields
If using multiple different fields on the filter, then it matches against tests that fulfill all the different fields. If using multiple different fields on the filter, then it matches against tests that fulfill all the different fields.
### Example ### Example
In this example, it runs any test that fits either of the two test names, and that also belongs to a test assembly that fits the given name. In this example, it runs any test that fits either of the two test names, and that also belongs to a test assembly that fits the given name.
``` C# ``` C#
var api = ScriptableObject.CreateInstance<TestRunnerApi>(); var api = ScriptableObject.CreateInstance<TestRunnerApi>();
api.Execute(new ExecutionSettings(new Filter() api.Execute(new ExecutionSettings(new Filter()
{ {
assemblyNames = new [] {"MyTestAssembly"}, assemblyNames = new [] {"MyTestAssembly"},
testNames = new [] {"MyTestClass.NameOfMyTest", "MyTestClass.AnotherNameOfATest"} testNames = new [] {"MyTestClass.NameOfMyTest", "MyTestClass.AnotherNameOfATest"}
})); }));
``` ```
## Multiple constructor filters ## Multiple constructor filters
The execution settings take one or more filters in its constructor. If there is no filter provided, then it runs all **Edit Mode** tests by default. If there are multiple filters provided, then a test runs if it matches any of the filters. The execution settings take one or more filters in its constructor. If there is no filter provided, then it runs all **Edit Mode** tests by default. If there are multiple filters provided, then a test runs if it matches any of the filters.
### Example ### Example
In this example, it runs any tests that are either in the assembly named `MyTestAssembly` or if the full name of the test matches either of the two provided test names: In this example, it runs any tests that are either in the assembly named `MyTestAssembly` or if the full name of the test matches either of the two provided test names:
``` C# ``` C#
var api = ScriptableObject.CreateInstance<TestRunnerApi>(); var api = ScriptableObject.CreateInstance<TestRunnerApi>();
api.Execute(new ExecutionSettings( api.Execute(new ExecutionSettings(
new Filter() new Filter()
{ {
assemblyNames = new[] {"MyTestAssembly"}, assemblyNames = new[] {"MyTestAssembly"},
}, },
new Filter() new Filter()
{ {
testNames = new[] {"MyTestClass.NameOfMyTest", "MyTestClass.AnotherNameOfATest"} testNames = new[] {"MyTestClass.NameOfMyTest", "MyTestClass.AnotherNameOfATest"}
} }
)); ));
``` ```
> **Note**: Specifying different test modes or platforms in each `Filter` is not currently supported. The test mode and platform is from the first `Filter` only and defaults to Edit Mode, if not supplied. > **Note**: Specifying different test modes or platforms in each `Filter` is not currently supported. The test mode and platform is from the first `Filter` only and defaults to Edit Mode, if not supplied.
\ No newline at end of file
# Getting started with Unity Test Framework # Getting started with Unity Test Framework
To access the Unity Test Framework (UTF) in the Unity Editor, open the **Test Runner** window; go to **Window** > **General** > **Test Runner**. To access the Unity Test Framework (UTF) in the Unity Editor, open the **Test Runner** window; go to **Window** > **General** > **Test Runner**.
![Unity Test Runner window](./images/test-runner-window.png) ![Unity Test Runner window](./images/test-runner-window.png)
To get started with UTF, follow the workflows below: To get started with UTF, follow the workflows below:
* [How to create a new test assembly](./workflow-create-test-assembly.md) * [How to create a new test assembly](./workflow-create-test-assembly.md)
* [How to create a test](./workflow-create-test.md) * [How to create a test](./workflow-create-test.md)
* [How to run a test](./workflow-run-test.md) * [How to run a test](./workflow-run-test.md)
* [How to create a Play Mode test](./workflow-create-playmode-test.md) * [How to create a Play Mode test](./workflow-create-playmode-test.md)
* [How to run a Play Mode test as standalone](./workflow-run-playmode-test-standalone.md) * [How to run a Play Mode test as standalone](./workflow-run-playmode-test-standalone.md)
For further information, see the [resources](./resources.md) and [reference](./manual.md#reference) sections. For further information, see the [resources](./resources.md) and [reference](./manual.md#reference) sections.
# About Unity Test Framework # About Unity Test Framework
The Unity Test Framework (UTF) enables Unity users to test their code in both **Edit Mode** and **Play Mode**, and also on target platforms such as [Standalone](https://docs.unity3d.com/Manual/Standalone.html), Android, iOS, etc. The Unity Test Framework (UTF) enables Unity users to test their code in both **Edit Mode** and **Play Mode**, and also on target platforms such as [Standalone](https://docs.unity3d.com/Manual/Standalone.html), Android, iOS, etc.
This package provides a standard test framework for users of Unity and developers at Unity so that both benefit from the same features and can write tests the same way. This package provides a standard test framework for users of Unity and developers at Unity so that both benefit from the same features and can write tests the same way.
UTF uses a Unity integration of NUnit library, which is an open-source unit testing library for .Net languages. For more information about NUnit, see the [official NUnit website](http://www.nunit.org/) and the [NUnit documentation on GitHub](https://github.com/nunit/docs/wiki/NUnit-Documentation). UTF uses a Unity integration of NUnit library, which is an open-source unit testing library for .Net languages. For more information about NUnit, see the [official NUnit website](http://www.nunit.org/) and the [NUnit documentation on GitHub](https://github.com/nunit/docs/wiki/NUnit-Documentation).
> **Note**: UTF is not a new concept or toolset; it is an adjusted and more descriptive naming for the toolset otherwise known as Unity Test Runner, which is now available as this package. > **Note**: UTF is not a new concept or toolset; it is an adjusted and more descriptive naming for the toolset otherwise known as Unity Test Runner, which is now available as this package.
# Installing Unity Test Framework # Installing Unity Test Framework
To install this package, follow the instructions in the [Package Manager documentation](https://docs.unity3d.com/Packages/com.unity.package-manager-ui@latest/index.html). To install this package, follow the instructions in the [Package Manager documentation](https://docs.unity3d.com/Packages/com.unity.package-manager-ui@latest/index.html).
> **Note**: Search for the Test Framework package. In Unity 2019.2 and higher, you may need to enable the package before use. > **Note**: Search for the Test Framework package. In Unity 2019.2 and higher, you may need to enable the package before use.
# Using Unity Test Framework # Using Unity Test Framework
To learn how to use the Unity Test Framework package in your project, read the [manual](./manual.md). To learn how to use the Unity Test Framework package in your project, read the [manual](./manual.md).
# Technical details # Technical details
## Requirements ## Requirements
This version of the Unity Test Framework is compatible with the following versions of the Unity Editor: This version of the Unity Test Framework is compatible with the following versions of the Unity Editor:
* 2019.2 and later. * 2019.2 and later.
## Known limitations ## Known limitations
Unity Test Framework version 1.0.18 includes the following known limitations: Unity Test Framework version 1.0.18 includes the following known limitations:
* The `UnityTest` attribute does not support WebGL and WSA platforms. * The `UnityTest` attribute does not support WebGL and WSA platforms.
* The `UnityTest` attribute does not support [Parameterized tests](https://github.com/nunit/docs/wiki/Parameterized-Tests) (except for `ValueSource`). * The `UnityTest` attribute does not support [Parameterized tests](https://github.com/nunit/docs/wiki/Parameterized-Tests) (except for `ValueSource`).
* The `UnityTest` attribute does not support the `NUnit` [Repeat](https://github.com/nunit/docs/wiki/Repeat-Attribute) attribute. * The `UnityTest` attribute does not support the `NUnit` [Repeat](https://github.com/nunit/docs/wiki/Repeat-Attribute) attribute.
* Nested test fixture cannot run from the Editor UI. * Nested test fixture cannot run from the Editor UI.
* When using the `NUnit` [Retry](https://github.com/nunit/docs/wiki/Retry-Attribute) attribute in PlayMode tests, it throws `InvalidCastException`. * When using the `NUnit` [Retry](https://github.com/nunit/docs/wiki/Retry-Attribute) attribute in PlayMode tests, it throws `InvalidCastException`.
## Package contents ## Package contents
The following table indicates the root folders in the package where you can find useful resources: The following table indicates the root folders in the package where you can find useful resources:
| Location | Description | | Location | Description |
| :----------------------------------------- | :------------------------------------------ | | :----------------------------------------- | :------------------------------------------ |
| _/com.unity.test-framework/Documentation~_ | Contains the documentation for the package. | | _/com.unity.test-framework/Documentation~_ | Contains the documentation for the package. |
## Document revision history ## Document revision history
| Date | Reason | | Date | Reason |
| :----------- | :---------------------------------------------------- | | :----------- | :---------------------------------------------------- |
| August 23, 2019 | Applied feedback to the documentation | | August 23, 2019 | Applied feedback to the documentation |
| July 25, 2019 | Documentation updated to include features in version 1.1.0 | | July 25, 2019 | Documentation updated to include features in version 1.1.0 |
| July 11, 2019 | Documentation updated. Matches package version 1.0.18 | | July 11, 2019 | Documentation updated. Matches package version 1.0.18 |
| May 27, 2019 | Documentation created. Matches package version 1.0.14 | | May 27, 2019 | Documentation created. Matches package version 1.0.14 |
# Unity Test Framework manual # Unity Test Framework manual
This is the manual for the Unity Test Framework (UTF): This is the manual for the Unity Test Framework (UTF):
## **Introduction** ## **Introduction**
* [Unity Test Framework overview](./index.md) * [Unity Test Framework overview](./index.md)
* [Edit Mode vs. Play Mode tests](edit-mode-vs-play-mode-tests.md) * [Edit Mode vs. Play Mode tests](edit-mode-vs-play-mode-tests.md)
## **Getting started** ## **Getting started**
* [Getting started with UTF](./getting-started.md) * [Getting started with UTF](./getting-started.md)
* Workflows: * Workflows:
* [How to create a new test assembly](./workflow-create-test-assembly.md) * [How to create a new test assembly](./workflow-create-test-assembly.md)
* [How to create a test](./workflow-create-test.md) * [How to create a test](./workflow-create-test.md)
* [How to run a test](workflow-run-test.md) * [How to run a test](workflow-run-test.md)
* [How to create a Play Mode test](./workflow-create-playmode-test.md) * [How to create a Play Mode test](./workflow-create-playmode-test.md)
* [How to run a Play Mode test in player](./workflow-run-playmode-test-standalone.md) * [How to run a Play Mode test in player](./workflow-run-playmode-test-standalone.md)
* [Resources](./resources.md) * [Resources](./resources.md)
## Extending UTF ## Extending UTF
* [Extending UTF](./extending.md) * [Extending UTF](./extending.md)
* Workflows: * Workflows:
* [How to split the build and run process for standalone Play Mode tests](./reference-attribute-testplayerbuildmodifier.md#split-build-and-run) * [How to split the build and run process for standalone Play Mode tests](./reference-attribute-testplayerbuildmodifier.md#split-build-and-run)
* [How to run tests programmatically](./extension-run-tests.md) * [How to run tests programmatically](./extension-run-tests.md)
* [How to get test results](./extension-get-test-results.md) * [How to get test results](./extension-get-test-results.md)
* [How to retrieve the list of tests](./extension-retrieve-test-list.md) * [How to retrieve the list of tests](./extension-retrieve-test-list.md)
## Reference ## Reference
* [Running tests from the command-line](./reference-command-line.md) * [Running tests from the command-line](./reference-command-line.md)
* [UnityTest attribute](./reference-attribute-unitytest.md) * [UnityTest attribute](./reference-attribute-unitytest.md)
* [Setup and cleanup at build time](./reference-setup-and-cleanup.md) * [Setup and cleanup at build time](./reference-setup-and-cleanup.md)
* [IPrebuildSetup](./reference-setup-and-cleanup.md#iprebuildsetup) * [IPrebuildSetup](./reference-setup-and-cleanup.md#iprebuildsetup)
* [IPostBuildCleanup](./reference-setup-and-cleanup.md#ipostbuildcleanup) * [IPostBuildCleanup](./reference-setup-and-cleanup.md#ipostbuildcleanup)
* [Actions outside of tests](./reference-actions-outside-tests.md) * [Actions outside of tests](./reference-actions-outside-tests.md)
* [Action execution order](./reference-actions-outside-tests.md#action-execution-order) * [Action execution order](./reference-actions-outside-tests.md#action-execution-order)
* [UnitySetUp and UnityTearDown](./reference-actions-outside-tests.md#unitysetup-and-unityteardown) * [UnitySetUp and UnityTearDown](./reference-actions-outside-tests.md#unitysetup-and-unityteardown)
* [OuterUnityTestAction](./reference-actions-outside-tests.md#outerunitytestaction) * [OuterUnityTestAction](./reference-actions-outside-tests.md#outerunitytestaction)
* [Domain Reloads](./reference-actions-outside-tests.md#domain-reloads) * [Domain Reloads](./reference-actions-outside-tests.md#domain-reloads)
* [Custom attributes](./reference-custom-attributes.md) * [Custom attributes](./reference-custom-attributes.md)
* [ConditionalIgnore attribute](./reference-attribute-conditionalignore.md) * [ConditionalIgnore attribute](./reference-attribute-conditionalignore.md)
* [PostBuildCleanup attribute](./reference-setup-and-cleanup.md#prebuildsetup-and-postbuildcleanup) * [PostBuildCleanup attribute](./reference-setup-and-cleanup.md#prebuildsetup-and-postbuildcleanup)
* [PrebuildSetup attribute](./reference-setup-and-cleanup.md#prebuildsetup-and-postbuildcleanup) * [PrebuildSetup attribute](./reference-setup-and-cleanup.md#prebuildsetup-and-postbuildcleanup)
* [TestMustExpectAllLogs attribute](./reference-attribute-testmustexpectalllogs.md) * [TestMustExpectAllLogs attribute](./reference-attribute-testmustexpectalllogs.md)
* [TestPlayerBuildModifier attribute](./reference-attribute-testplayerbuildmodifier.md) * [TestPlayerBuildModifier attribute](./reference-attribute-testplayerbuildmodifier.md)
* [TestRunCallback attribute](./reference-attribute-testruncallback.md) * [TestRunCallback attribute](./reference-attribute-testruncallback.md)
* [UnityPlatform attribute](./reference-attribute-unityplatform.md) * [UnityPlatform attribute](./reference-attribute-unityplatform.md)
* [UnitySetUp attribute](./reference-actions-outside-tests.md#unitysetup-and-unityteardown) * [UnitySetUp attribute](./reference-actions-outside-tests.md#unitysetup-and-unityteardown)
* [UnityTearDown attribute](./reference-actions-outside-tests.md#unitysetup-and-unityteardown) * [UnityTearDown attribute](./reference-actions-outside-tests.md#unitysetup-and-unityteardown)
* [UnityTest attribute](./reference-attribute-unitytest.md) * [UnityTest attribute](./reference-attribute-unitytest.md)
* [Custom equality comparers](./reference-custom-equality-comparers.md) * [Custom equality comparers](./reference-custom-equality-comparers.md)
* [ColorEqualityComparer](./reference-comparer-color.md) * [ColorEqualityComparer](./reference-comparer-color.md)
* [FloatEqualityComparer](./reference-comparer-float.md) * [FloatEqualityComparer](./reference-comparer-float.md)
* [QuaternionEqualityComparer](./reference-comparer-quaternion.md) * [QuaternionEqualityComparer](./reference-comparer-quaternion.md)
* [Vector2EqualityComparer](./reference-comparer-vector2.md) * [Vector2EqualityComparer](./reference-comparer-vector2.md)
* [Vector3EqualityComparer](./reference-comparer-vector3.md) * [Vector3EqualityComparer](./reference-comparer-vector3.md)
* [Vector4EqualityComparer](./reference-comparer-vector4.md) * [Vector4EqualityComparer](./reference-comparer-vector4.md)
* [Custom equality comparers with equals operator](./reference-comparer-equals.md) * [Custom equality comparers with equals operator](./reference-comparer-equals.md)
* [Test Utils](./reference-test-utils.md) * [Test Utils](./reference-test-utils.md)
* [Custom yield instructions](./reference-custom-yield-instructions.md) * [Custom yield instructions](./reference-custom-yield-instructions.md)
* [IEditModeTestYieldInstruction](./reference-custom-yield-instructions.md#IEditModeTestYieldInstruction) * [IEditModeTestYieldInstruction](./reference-custom-yield-instructions.md#IEditModeTestYieldInstruction)
* [EnterPlayMode](./reference-custom-yield-instructions.md#enterplaymode) * [EnterPlayMode](./reference-custom-yield-instructions.md#enterplaymode)
* [ExitPlayMode](./reference-custom-yield-instructions.md#exitplaymode) * [ExitPlayMode](./reference-custom-yield-instructions.md#exitplaymode)
* [Custom assertion](./reference-custom-assertion.md) * [Custom assertion](./reference-custom-assertion.md)
* [LogAssert](./reference-custom-assertion.md#logassert) * [LogAssert](./reference-custom-assertion.md#logassert)
* [Custom constraints](./reference-custom-constraints.md) * [Custom constraints](./reference-custom-constraints.md)
* [Is](./reference-custom-constraints.md#is) * [Is](./reference-custom-constraints.md#is)
* [Parameterized tests](./reference-tests-parameterized.md) * [Parameterized tests](./reference-tests-parameterized.md)
* [MonoBehaviour tests](./reference-tests-monobehaviour.md) * [MonoBehaviour tests](./reference-tests-monobehaviour.md)
* [MonoBehaviourTest<T>](./reference-tests-monobehaviour.md#monobehaviourtestt) * [MonoBehaviourTest<T>](./reference-tests-monobehaviour.md#monobehaviourtestt)
* [IMonoBehaviourTest](./reference-tests-monobehaviour.md#imonobehaviourtest) * [IMonoBehaviourTest](./reference-tests-monobehaviour.md#imonobehaviourtest)
* [TestRunnerApi](./reference-test-runner-api.md) * [TestRunnerApi](./reference-test-runner-api.md)
* [ExecutionSettings](./reference-execution-settings.md) * [ExecutionSettings](./reference-execution-settings.md)
* [Filter](./reference-filter.md) * [Filter](./reference-filter.md)
* [ITestRunSettings](./reference-itest-run-settings.md) * [ITestRunSettings](./reference-itest-run-settings.md)
* [ICallbacks](./reference-icallbacks.md) * [ICallbacks](./reference-icallbacks.md)
* [IErrorCallbacks](./reference-ierror-callbacks.md) * [IErrorCallbacks](./reference-ierror-callbacks.md)
\ No newline at end of file
# Actions outside of tests # Actions outside of tests
When writing tests, it is possible to avoid duplication of code by using the [SetUp and TearDown](https://github.com/nunit/docs/wiki/SetUp-and-TearDown) methods built into [NUnit](http://www.nunit.org/). The Unity Test Framework has extended these methods with extra functionality, which can yield commands and skip frames, in the same way as [UnityTest](./reference-attribute-unitytest.md). When writing tests, it is possible to avoid duplication of code by using the [SetUp and TearDown](https://github.com/nunit/docs/wiki/SetUp-and-TearDown) methods built into [NUnit](http://www.nunit.org/). The Unity Test Framework has extended these methods with extra functionality, which can yield commands and skip frames, in the same way as [UnityTest](./reference-attribute-unitytest.md).
## Action execution order ## Action execution order
The actions related to a test run in the following order: The actions related to a test run in the following order:
* Attributes implementing [IApplyToContext](https://github.com/nunit/docs/wiki/IApplyToContext-Interface) * Attributes implementing [IApplyToContext](https://github.com/nunit/docs/wiki/IApplyToContext-Interface)
* Any attribute implementing [OuterUnityTestAction](#outerunitytestaction) has its `BeforeTest` invoked * Any attribute implementing [OuterUnityTestAction](#outerunitytestaction) has its `BeforeTest` invoked
* Tests with [UnitySetUp](#unitysetup-and-unityteardown) methods in their test class. * Tests with [UnitySetUp](#unitysetup-and-unityteardown) methods in their test class.
* Attributes implementing [IWrapSetUpTearDown](https://github.com/nunit/docs/wiki/ICommandWrapper-Interface) * Attributes implementing [IWrapSetUpTearDown](https://github.com/nunit/docs/wiki/ICommandWrapper-Interface)
* Any [SetUp](https://github.com/nunit/docs/wiki/SetUp-and-TearDown) attributes * Any [SetUp](https://github.com/nunit/docs/wiki/SetUp-and-TearDown) attributes
* [Action attributes](https://nunit.org/docs/2.6/actionAttributes.html) have their `BeforeTest` method invoked * [Action attributes](https://nunit.org/docs/2.6/actionAttributes.html) have their `BeforeTest` method invoked
* Attributes implementing of [IWrapTestMethod](https://github.com/nunit/docs/wiki/ICommandWrapper-Interface) * Attributes implementing of [IWrapTestMethod](https://github.com/nunit/docs/wiki/ICommandWrapper-Interface)
* **The test itself runs** * **The test itself runs**
* [Action attributes](https://nunit.org/docs/2.6/actionAttributes.html) have their `AfterTest` method invoked * [Action attributes](https://nunit.org/docs/2.6/actionAttributes.html) have their `AfterTest` method invoked
* Any method with the [TearDown](https://github.com/nunit/docs/wiki/SetUp-and-TearDown) attribute * Any method with the [TearDown](https://github.com/nunit/docs/wiki/SetUp-and-TearDown) attribute
* Tests with [UnityTearDown](#unitysetup-and-unityteardown) methods in their test class * Tests with [UnityTearDown](#unitysetup-and-unityteardown) methods in their test class
* Any [OuterUnityTestAction](#outerunitytestaction) has its `AfterTest` invoked * Any [OuterUnityTestAction](#outerunitytestaction) has its `AfterTest` invoked
The list of actions is the same for both `Test` and `UnityTest`. The list of actions is the same for both `Test` and `UnityTest`.
## UnitySetUp and UnityTearDown ## UnitySetUp and UnityTearDown
The `UnitySetUp` and `UnityTearDown` attributes are identical to the standard `SetUp` and `TearDown` attributes, with the exception that they allow for [yielding instructions](reference-custom-yield-instructions.md). The `UnitySetUp` and `UnityTearDown` attributes expect a return type of [IEnumerator](https://docs.microsoft.com/en-us/dotnet/api/system.collections.ienumerator?view=netframework-4.8). The `UnitySetUp` and `UnityTearDown` attributes are identical to the standard `SetUp` and `TearDown` attributes, with the exception that they allow for [yielding instructions](reference-custom-yield-instructions.md). The `UnitySetUp` and `UnityTearDown` attributes expect a return type of [IEnumerator](https://docs.microsoft.com/en-us/dotnet/api/system.collections.ienumerator?view=netframework-4.8).
### Example ### Example
```c# ```c#
public class SetUpTearDownExample public class SetUpTearDownExample
{ {
[UnitySetUp] [UnitySetUp]
public IEnumerator SetUp() public IEnumerator SetUp()
{ {
yield return new EnterPlayMode(); yield return new EnterPlayMode();
} }
[Test] [Test]
public void MyTest() public void MyTest()
{ {
Debug.Log("This runs inside playmode"); Debug.Log("This runs inside playmode");
} }
[UnitySetUp] [UnitySetUp]
public IEnumerator TearDown() public IEnumerator TearDown()
{ {
yield return new ExitPlayMode(); yield return new ExitPlayMode();
} }
} }
``` ```
## OuterUnityTestAction ## OuterUnityTestAction
`OuterUnityTestAction` is a wrapper outside of the tests, which allows for any tests with this attribute to run code before and after the tests. This method allows for yielding commands in the same way as `UnityTest`. The attribute must inherit the `NUnit` attribute and implement `IOuterUnityTestAction`. `OuterUnityTestAction` is a wrapper outside of the tests, which allows for any tests with this attribute to run code before and after the tests. This method allows for yielding commands in the same way as `UnityTest`. The attribute must inherit the `NUnit` attribute and implement `IOuterUnityTestAction`.
### Example ### Example
```c# ```c#
using System.Collections; using System.Collections;
using NUnit.Framework; using NUnit.Framework;
using NUnit.Framework.Interfaces; using NUnit.Framework.Interfaces;
using UnityEngine; using UnityEngine;
using UnityEngine.TestTools; using UnityEngine.TestTools;
public class MyTestClass public class MyTestClass
{ {
[UnityTest, MyOuterActionAttribute] [UnityTest, MyOuterActionAttribute]
public IEnumerator MyTestInsidePlaymode() public IEnumerator MyTestInsidePlaymode()
{ {
Assert.IsTrue(Application.isPlaying); Assert.IsTrue(Application.isPlaying);
yield return null; yield return null;
} }
} }
public class MyOuterActionAttribute : NUnitAttribute, IOuterUnityTestAction public class MyOuterActionAttribute : NUnitAttribute, IOuterUnityTestAction
{ {
public IEnumerator BeforeTest(ITest test) public IEnumerator BeforeTest(ITest test)
{ {
yield return new EnterPlayMode(); yield return new EnterPlayMode();
} }
public IEnumerator AfterTest(ITest test) public IEnumerator AfterTest(ITest test)
{ {
yield return new ExitPlayMode(); yield return new ExitPlayMode();
} }
} }
``` ```
## Domain Reloads ## Domain Reloads
In **Edit Mode** tests it is possible to yield instructions that can result in a domain reload, such as entering or exiting **Play Mode** (see [Custom yield instructions](./reference-custom-yield-instructions.md)). When a domain reload happens, all non-Unity actions (such as `OneTimeSetup` and `Setup`) are rerun before the code, which initiated the domain reload, continues. Unity actions (such as `UnitySetup`) are not rerun. If the Unity action is the code that initiated the domain reload, then the rest of the code in the `UnitySetup` method runs after the domain reload. In **Edit Mode** tests it is possible to yield instructions that can result in a domain reload, such as entering or exiting **Play Mode** (see [Custom yield instructions](./reference-custom-yield-instructions.md)). When a domain reload happens, all non-Unity actions (such as `OneTimeSetup` and `Setup`) are rerun before the code, which initiated the domain reload, continues. Unity actions (such as `UnitySetup`) are not rerun. If the Unity action is the code that initiated the domain reload, then the rest of the code in the `UnitySetup` method runs after the domain reload.
\ No newline at end of file
# ConditionalIgnore attribute # ConditionalIgnore attribute
This attribute is an alternative to the standard `Ignore` attribute in [NUnit](http://www.nunit.org/). It allows for ignoring tests only under a specified condition. The condition evaluates during `OnLoad`, referenced by ID. This attribute is an alternative to the standard `Ignore` attribute in [NUnit](http://www.nunit.org/). It allows for ignoring tests only under a specified condition. The condition evaluates during `OnLoad`, referenced by ID.
## Example ## Example
The following example shows a method to use the `ConditionalIgnore` attribute to ignore a test if the Unity Editor is running macOS: The following example shows a method to use the `ConditionalIgnore` attribute to ignore a test if the Unity Editor is running macOS:
```C# ```C#
using UnityEditor; using UnityEditor;
using NUnit.Framework; using NUnit.Framework;
using UnityEngine.TestTools; using UnityEngine.TestTools;
[InitializeOnLoad] [InitializeOnLoad]
public class OnLoad public class OnLoad
{ {
static OnLoad() static OnLoad()
{ {
var editorIsOSX = false; var editorIsOSX = false;
#if UNITY_EDITOR_OSX #if UNITY_EDITOR_OSX
editorIsOSX = true; editorIsOSX = true;
#endif #endif
ConditionalIgnoreAttribute.AddConditionalIgnoreMapping("IgnoreInMacEditor", editorIsOSX); ConditionalIgnoreAttribute.AddConditionalIgnoreMapping("IgnoreInMacEditor", editorIsOSX);
} }
} }
public class MyTestClass public class MyTestClass
{ {
[Test, ConditionalIgnore("IgnoreInMacEditor", "Ignored on Mac editor.")] [Test, ConditionalIgnore("IgnoreInMacEditor", "Ignored on Mac editor.")]
public void TestNeverRunningInMacEditor() public void TestNeverRunningInMacEditor()
{ {
Assert.Pass(); Assert.Pass();
} }
} }
``` ```
> **Note**: You can only use `InitializeOnLoad` in **Edit Mode** tests. > **Note**: You can only use `InitializeOnLoad` in **Edit Mode** tests.
\ No newline at end of file
# TestMustExpectAllLogs attribute # TestMustExpectAllLogs attribute
The presence of this attribute causes the **Test Runner** to expect every single log. By default, the Test Runner only fails on error logs, but `TestMustExpectAllLogs` fails on warnings and info level messages as well. It is the same as calling the method [LogAssert.NoUnexpectedReceived](./reference-custom-assertion.md#static-methods) at the bottom of every affected test. The presence of this attribute causes the **Test Runner** to expect every single log. By default, the Test Runner only fails on error logs, but `TestMustExpectAllLogs` fails on warnings and info level messages as well. It is the same as calling the method [LogAssert.NoUnexpectedReceived](./reference-custom-assertion.md#static-methods) at the bottom of every affected test.
## Assembly-wide usage ## Assembly-wide usage
You can apply this attribute to test assemblies (that affects every test in the assembly), fixtures (affects every test in the fixture), or on individual test methods. It is also inherited from base fixtures. You can apply this attribute to test assemblies (that affects every test in the assembly), fixtures (affects every test in the fixture), or on individual test methods. It is also inherited from base fixtures.
The `MustExpect` property (`true` by default) lets you enable or disable the higher level value. The `MustExpect` property (`true` by default) lets you enable or disable the higher level value.
For example when migrating an assembly to this more strict checking method, you might attach `[assembly:TestMustExpectAllLogs]` to the assembly itself, but then whitelist failing fixtures and test methods with `[TestMustExpectAllLogs(MustExpect=false)]` until you have migrated them. This also means new tests in that assembly would have the more strict checking. For example when migrating an assembly to this more strict checking method, you might attach `[assembly:TestMustExpectAllLogs]` to the assembly itself, but then whitelist failing fixtures and test methods with `[TestMustExpectAllLogs(MustExpect=false)]` until you have migrated them. This also means new tests in that assembly would have the more strict checking.
\ No newline at end of file
# TestPlayerBuildModifier attribute # TestPlayerBuildModifier attribute
You can use the `TestPlayerBuildModifier` attribute to accomplish a couple of different scenarios: You can use the `TestPlayerBuildModifier` attribute to accomplish a couple of different scenarios:
## Modify the Player build options for Play Mode tests ## Modify the Player build options for Play Mode tests
It is possible to change the [BuildPlayerOptions](https://docs.unity3d.com/ScriptReference/BuildPlayerOptions.html) for the test **Player**, to achieve custom behavior when running **Play Mode** tests. Modifying the build options allows for changing the target location of the build as well as changing [BuildOptions](https://docs.unity3d.com/ScriptReference/BuildOptions.html). It is possible to change the [BuildPlayerOptions](https://docs.unity3d.com/ScriptReference/BuildPlayerOptions.html) for the test **Player**, to achieve custom behavior when running **Play Mode** tests. Modifying the build options allows for changing the target location of the build as well as changing [BuildOptions](https://docs.unity3d.com/ScriptReference/BuildOptions.html).
To modify the `BuildPlayerOptions`, do the following: To modify the `BuildPlayerOptions`, do the following:
* Implement the `ITestPlayerBuildModifier` * Implement the `ITestPlayerBuildModifier`
* Reference the implementation type in a `TestPlayerBuildModifier` attribute on an assembly level. * Reference the implementation type in a `TestPlayerBuildModifier` attribute on an assembly level.
### Example ### Example
```c# ```c#
using UnityEditor; using UnityEditor;
using UnityEditor.TestTools; using UnityEditor.TestTools;
[assembly:TestPlayerBuildModifier(typeof(BuildModifier))] [assembly:TestPlayerBuildModifier(typeof(BuildModifier))]
public class BuildModifier : ITestPlayerBuildModifier public class BuildModifier : ITestPlayerBuildModifier
{ {
public BuildPlayerOptions ModifyOptions(BuildPlayerOptions playerOptions) public BuildPlayerOptions ModifyOptions(BuildPlayerOptions playerOptions)
{ {
if (playerOptions.target == BuildTarget.iOS) if (playerOptions.target == BuildTarget.iOS)
{ {
playerOptions.options |= BuildOptions.SymlinkLibraries; // Enable symlink libraries when running on iOS playerOptions.options |= BuildOptions.SymlinkLibraries; // Enable symlink libraries when running on iOS
} }
playerOptions.options |= BuildOptions.AllowDebugging; // Enable allow Debugging flag on the test Player. playerOptions.options |= BuildOptions.AllowDebugging; // Enable allow Debugging flag on the test Player.
return playerOptions; return playerOptions;
} }
} }
``` ```
> **Note:** When building the Player, it includes all `TestPlayerBuildModifier` attributes across all loaded assemblies, independent of the currently used test filter. As the implementation references the `UnityEditor` namespace, the code is typically implemented in an Editor only assembly, as the `UnityEditor` namespace is not available otherwise. > **Note:** When building the Player, it includes all `TestPlayerBuildModifier` attributes across all loaded assemblies, independent of the currently used test filter. As the implementation references the `UnityEditor` namespace, the code is typically implemented in an Editor only assembly, as the `UnityEditor` namespace is not available otherwise.
## Split build and run ## Split build and run
It is possible to use the Unity Editor for building the Player with tests, without [running the tests](./workflow-run-playmode-test-standalone.md). This allows for running the Player on e.g. another machine. In this case, it is necessary to modify the Player to build and implement a custom handling of the test result. It is possible to use the Unity Editor for building the Player with tests, without [running the tests](./workflow-run-playmode-test-standalone.md). This allows for running the Player on e.g. another machine. In this case, it is necessary to modify the Player to build and implement a custom handling of the test result.
By using `TestPlayerBuildModifier`, you can alter the `BuildOptions` to not start the Player after the build as well as build the Player at a specific location. Combined with [PostBuildCleanup](./reference-setup-and-cleanup.md#prebuildsetup-and-postbuildcleanup), you can automatically exit the Editor on completion of the build. By using `TestPlayerBuildModifier`, you can alter the `BuildOptions` to not start the Player after the build as well as build the Player at a specific location. Combined with [PostBuildCleanup](./reference-setup-and-cleanup.md#prebuildsetup-and-postbuildcleanup), you can automatically exit the Editor on completion of the build.
### Example ### Example
```c# ```c#
using System; using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using Tests; using Tests;
using UnityEditor; using UnityEditor;
using UnityEditor.TestTools; using UnityEditor.TestTools;
using UnityEngine; using UnityEngine;
using UnityEngine.TestTools; using UnityEngine.TestTools;
[assembly:TestPlayerBuildModifier(typeof(HeadlessPlayModeSetup))] [assembly:TestPlayerBuildModifier(typeof(HeadlessPlayModeSetup))]
[assembly:PostBuildCleanup(typeof(HeadlessPlayModeSetup))] [assembly:PostBuildCleanup(typeof(HeadlessPlayModeSetup))]
namespace Tests namespace Tests
{ {
public class HeadlessPlayModeSetup : ITestPlayerBuildModifier, IPostBuildCleanup public class HeadlessPlayModeSetup : ITestPlayerBuildModifier, IPostBuildCleanup
{ {
private static bool s_RunningPlayerTests; private static bool s_RunningPlayerTests;
public BuildPlayerOptions ModifyOptions(BuildPlayerOptions playerOptions) public BuildPlayerOptions ModifyOptions(BuildPlayerOptions playerOptions)
{ {
// Do not launch the player after the build completes. // Do not launch the player after the build completes.
playerOptions.options &= ~BuildOptions.AutoRunPlayer; playerOptions.options &= ~BuildOptions.AutoRunPlayer;
// Set the headlessBuildLocation to the output directory you desire. It does not need to be inside the project. // Set the headlessBuildLocation to the output directory you desire. It does not need to be inside the project.
var headlessBuildLocation = Path.GetFullPath(Path.Combine(Application.dataPath, ".//..//PlayModeTestPlayer")); var headlessBuildLocation = Path.GetFullPath(Path.Combine(Application.dataPath, ".//..//PlayModeTestPlayer"));
var fileName = Path.GetFileName(playerOptions.locationPathName); var fileName = Path.GetFileName(playerOptions.locationPathName);
if (!string.IsNullOrEmpty(fileName)) if (!string.IsNullOrEmpty(fileName))
{ {
headlessBuildLocation = Path.Combine(headlessBuildLocation, fileName); headlessBuildLocation = Path.Combine(headlessBuildLocation, fileName);
} }
playerOptions.locationPathName = headlessBuildLocation; playerOptions.locationPathName = headlessBuildLocation;
// Instruct the cleanup to exit the Editor if the run came from the command line. // Instruct the cleanup to exit the Editor if the run came from the command line.
// The variable is static because the cleanup is being invoked in a new instance of the class. // The variable is static because the cleanup is being invoked in a new instance of the class.
s_RunningPlayerTests = true; s_RunningPlayerTests = true;
return playerOptions; return playerOptions;
} }
public void Cleanup() public void Cleanup()
{ {
if (s_RunningPlayerTests && IsRunningTestsFromCommandLine()) if (s_RunningPlayerTests && IsRunningTestsFromCommandLine())
{ {
// Exit the Editor on the next update, allowing for other PostBuildCleanup steps to run. // Exit the Editor on the next update, allowing for other PostBuildCleanup steps to run.
EditorApplication.update += () => { EditorApplication.Exit(0); }; EditorApplication.update += () => { EditorApplication.Exit(0); };
} }
} }
private static bool IsRunningTestsFromCommandLine() private static bool IsRunningTestsFromCommandLine()
{ {
var commandLineArgs = Environment.GetCommandLineArgs(); var commandLineArgs = Environment.GetCommandLineArgs();
return commandLineArgs.Any(value => value == "-runTests"); return commandLineArgs.Any(value => value == "-runTests");
} }
} }
} }
``` ```
If the Editor is still running after the Play Mode tests have run, the Player tries to report the results back, using [PlayerConnection](https://docs.unity3d.com/ScriptReference/Networking.PlayerConnection.PlayerConnection.html), which has a reference to the IP address of the Editor machine, when built. If the Editor is still running after the Play Mode tests have run, the Player tries to report the results back, using [PlayerConnection](https://docs.unity3d.com/ScriptReference/Networking.PlayerConnection.PlayerConnection.html), which has a reference to the IP address of the Editor machine, when built.
To implement a custom way of reporting the results of the test run, let one of the assemblies in the Player include a [TestRunCallback](./reference-attribute-testruncallback.md). At `RunFinished`, it is possible to get the full test report as XML from the [NUnit](http://www.nunit.org/) test result by calling `result.ToXml(true)`. You can save the result and then save it on the device or send it to another machine as needed. To implement a custom way of reporting the results of the test run, let one of the assemblies in the Player include a [TestRunCallback](./reference-attribute-testruncallback.md). At `RunFinished`, it is possible to get the full test report as XML from the [NUnit](http://www.nunit.org/) test result by calling `result.ToXml(true)`. You can save the result and then save it on the device or send it to another machine as needed.
# TestRunCallback attribute # TestRunCallback attribute
It is possible for the test framework to invoke callbacks as the current test run progresses. To do this, there is a `TestRunCallback` attribute which takes the type of `ITestRunCallback` implementation. You can invoke the callbacks with [NUnit](http://www.nunit.org/) `ITest` and `ITestResult` classes. It is possible for the test framework to invoke callbacks as the current test run progresses. To do this, there is a `TestRunCallback` attribute which takes the type of `ITestRunCallback` implementation. You can invoke the callbacks with [NUnit](http://www.nunit.org/) `ITest` and `ITestResult` classes.
At the `RunStarted` and `RunFinished` methods, the test and test results are for the whole test tree. These methods invoke at each node in the test tree; first with the whole test assembly, then with the test class, and last with the test method. At the `RunStarted` and `RunFinished` methods, the test and test results are for the whole test tree. These methods invoke at each node in the test tree; first with the whole test assembly, then with the test class, and last with the test method.
From these callbacks, it is possible to read the partial or the full results, and it is furthermore possible to save the XML version of the result for further processing or continuous integration. From these callbacks, it is possible to read the partial or the full results, and it is furthermore possible to save the XML version of the result for further processing or continuous integration.
## Example ## Example
```C# ```C#
using NUnit.Framework.Interfaces; using NUnit.Framework.Interfaces;
using UnityEngine; using UnityEngine;
using UnityEngine.TestRunner; using UnityEngine.TestRunner;
[assembly:TestRunCallback(typeof(MyTestRunCallback))] [assembly:TestRunCallback(typeof(MyTestRunCallback))]
public class MyTestRunCallback : ITestRunCallback public class MyTestRunCallback : ITestRunCallback
{ {
public void RunStarted(ITest testsToRun) public void RunStarted(ITest testsToRun)
{ {
} }
public void RunFinished(ITestResult testResults) public void RunFinished(ITestResult testResults)
{ {
} }
public void TestStarted(ITest test) public void TestStarted(ITest test)
{ {
} }
public void TestFinished(ITestResult result) public void TestFinished(ITestResult result)
{ {
if (!result.Test.IsSuite) if (!result.Test.IsSuite)
{ {
Debug.Log($"Result of {result.Name}: {result.ResultState.Status}"); Debug.Log($"Result of {result.Name}: {result.ResultState.Status}");
} }
} }
} }
``` ```
> **Note:** The `TestRunCallback` does not need any references to the `UnityEditor` namespace and is thus able to run in standalone Players, on the **Player** side. > **Note:** The `TestRunCallback` does not need any references to the `UnityEditor` namespace and is thus able to run in standalone Players, on the **Player** side.
\ No newline at end of file
# UnityPlatform attribute # UnityPlatform attribute
Use this attribute to define a specific set of platforms you want or do not want your test(s) to run on. Use this attribute to define a specific set of platforms you want or do not want your test(s) to run on.
You can use this attribute on the test method, test class, or test assembly level. Use the supported [RuntimePlatform](https://docs.unity3d.com/ScriptReference/RuntimePlatform.html) enumeration values to specify the platforms. You can also specify which platforms to test by passing one or more `RuntimePlatform` values along with or without the include or exclude properties as parameters to the [Platform](https://github.com/nunit/docs/wiki/Platform-Attribute) attribute constructor. You can use this attribute on the test method, test class, or test assembly level. Use the supported [RuntimePlatform](https://docs.unity3d.com/ScriptReference/RuntimePlatform.html) enumeration values to specify the platforms. You can also specify which platforms to test by passing one or more `RuntimePlatform` values along with or without the include or exclude properties as parameters to the [Platform](https://github.com/nunit/docs/wiki/Platform-Attribute) attribute constructor.
The test(s) skips if the current target platform is: The test(s) skips if the current target platform is:
- Not explicitly specified in the included platforms list - Not explicitly specified in the included platforms list
- In the excluded platforms list - In the excluded platforms list
```c# ```c#
using UnityEngine; using UnityEngine;
using UnityEngine.TestTools; using UnityEngine.TestTools;
using NUnit.Framework; using NUnit.Framework;
[TestFixture] [TestFixture]
public class TestClass public class TestClass
{ {
[Test] [Test]
[UnityPlatform(RuntimePlatform.WindowsPlayer)] [UnityPlatform(RuntimePlatform.WindowsPlayer)]
public void TestMethod() public void TestMethod()
{ {
Assert.AreEqual(Application.platform, RuntimePlatform.WindowsPlayer); Assert.AreEqual(Application.platform, RuntimePlatform.WindowsPlayer);
} }
} }
``` ```
## Properties ## Properties
| Syntax | Description | | Syntax | Description |
| --------------------------- | ------------------------------------------------------------ | | --------------------------- | ------------------------------------------------------------ |
| `RuntimePlatform[] exclude` | List the platforms you do not want to have your tests run on. | | `RuntimePlatform[] exclude` | List the platforms you do not want to have your tests run on. |
| `RuntimePlatform[] include` | A subset of platforms you need to have your tests run on. | | `RuntimePlatform[] include` | A subset of platforms you need to have your tests run on. |
# UnityTest attribute # UnityTest attribute
`UnityTest` attribute is the main addition to the standard [NUnit](http://www.nunit.org/) library for the Unity Test Framework. This type of unit test allows you to skip a frame from within a test (so background tasks can finish) or give certain commands to the Unity **Editor**, such as performing a domain reload or entering **Play Mode** from an **Edit Mode** test. `UnityTest` attribute is the main addition to the standard [NUnit](http://www.nunit.org/) library for the Unity Test Framework. This type of unit test allows you to skip a frame from within a test (so background tasks can finish) or give certain commands to the Unity **Editor**, such as performing a domain reload or entering **Play Mode** from an **Edit Mode** test.
In Play Mode, the `UnityTest` attribute runs as a [coroutine](https://docs.unity3d.com/Manual/Coroutines.html). Whereas Edit Mode tests run in the [EditorApplication.update](https://docs.unity3d.com/ScriptReference/EditorApplication-update.html) callback loop. In Play Mode, the `UnityTest` attribute runs as a [coroutine](https://docs.unity3d.com/Manual/Coroutines.html). Whereas Edit Mode tests run in the [EditorApplication.update](https://docs.unity3d.com/ScriptReference/EditorApplication-update.html) callback loop.
The `UnityTest` attribute is, in fact, an alternative to the `NUnit` [Test attribute](https://github.com/nunit/docs/wiki/Test-Attribute), which allows yielding instructions back to the framework. Once the instruction is complete, the test run continues. If you `yield return null`, you skip a frame. That might be necessary to ensure that some changes do happen on the next iteration of either the `EditorApplication.update` loop or the [game loop](https://docs.unity3d.com/Manual/ExecutionOrder.html). The `UnityTest` attribute is, in fact, an alternative to the `NUnit` [Test attribute](https://github.com/nunit/docs/wiki/Test-Attribute), which allows yielding instructions back to the framework. Once the instruction is complete, the test run continues. If you `yield return null`, you skip a frame. That might be necessary to ensure that some changes do happen on the next iteration of either the `EditorApplication.update` loop or the [game loop](https://docs.unity3d.com/Manual/ExecutionOrder.html).
## Edit Mode example ## Edit Mode example
The most simple example of an Edit Mode test could be the one that yields `null` to skip the current frame and then continues to run: The most simple example of an Edit Mode test could be the one that yields `null` to skip the current frame and then continues to run:
```C# ```C#
[UnityTest] [UnityTest]
public IEnumerator EditorUtility_WhenExecuted_ReturnsSuccess() public IEnumerator EditorUtility_WhenExecuted_ReturnsSuccess()
{ {
var utility = RunEditorUtilityInTheBackgroud(); var utility = RunEditorUtilityInTheBackgroud();
while (utility.isRunning) while (utility.isRunning)
{ {
yield return null; yield return null;
} }
Assert.IsTrue(utility.isSuccess); Assert.IsTrue(utility.isSuccess);
} }
``` ```
## Play Mode example ## Play Mode example
In Play Mode, a test runs as a coroutine attached to a [MonoBehaviour](https://docs.unity3d.com/ScriptReference/MonoBehaviour.html). So all the yield instructions available in coroutines, are also available in your test. In Play Mode, a test runs as a coroutine attached to a [MonoBehaviour](https://docs.unity3d.com/ScriptReference/MonoBehaviour.html). So all the yield instructions available in coroutines, are also available in your test.
From a Play Mode test you can use one of Unity’s [Yield Instructions](https://docs.unity3d.com/ScriptReference/YieldInstruction.html): From a Play Mode test you can use one of Unity’s [Yield Instructions](https://docs.unity3d.com/ScriptReference/YieldInstruction.html):
- [WaitForFixedUpdate](https://docs.unity3d.com/ScriptReference/WaitForFixedUpdate.html): to ensure changes expected within the next cycle of physics calculations. - [WaitForFixedUpdate](https://docs.unity3d.com/ScriptReference/WaitForFixedUpdate.html): to ensure changes expected within the next cycle of physics calculations.
- [WaitForSeconds](https://docs.unity3d.com/ScriptReference/WaitForSeconds.html): if you want to pause your test coroutine for a fixed amount of time. Be careful about creating long-running tests. - [WaitForSeconds](https://docs.unity3d.com/ScriptReference/WaitForSeconds.html): if you want to pause your test coroutine for a fixed amount of time. Be careful about creating long-running tests.
The simplest example is to yield to `WaitForFixedUpdate`: The simplest example is to yield to `WaitForFixedUpdate`:
```c# ```c#
[UnityTest] [UnityTest]
public IEnumerator GameObject_WithRigidBody_WillBeAffectedByPhysics() public IEnumerator GameObject_WithRigidBody_WillBeAffectedByPhysics()
{ {
var go = new GameObject(); var go = new GameObject();
go.AddComponent<Rigidbody>(); go.AddComponent<Rigidbody>();
var originalPosition = go.transform.position.y; var originalPosition = go.transform.position.y;
yield return new WaitForFixedUpdate(); yield return new WaitForFixedUpdate();
Assert.AreNotEqual(originalPosition, go.transform.position.y); Assert.AreNotEqual(originalPosition, go.transform.position.y);
} }
``` ```
# Running tests from the command line # Running tests from the command line
It’s pretty simple to run a test project from the command line. Here is an example in Windows: It’s pretty simple to run a test project from the command line. Here is an example in Windows:
```bash ```bash
Unity.exe -runTests -batchmode -projectPath PATH_TO_YOUR_PROJECT -testResults C:\temp\results.xml -testPlatform PS4 Unity.exe -runTests -batchmode -projectPath PATH_TO_YOUR_PROJECT -testResults C:\temp\results.xml -testPlatform PS4
``` ```
For more information, see [Command line arguments](https://docs.unity3d.com/Manual/CommandLineArguments.html). For more information, see [Command line arguments](https://docs.unity3d.com/Manual/CommandLineArguments.html).
## Commands ## Commands
### batchmode ### batchmode
Runs Unity in batch mode and ensures no pop-up windows appear to eliminate the need for any human intervention. Runs Unity in batch mode and ensures no pop-up windows appear to eliminate the need for any human intervention.
### forgetProjectPath ### forgetProjectPath
Don't save your current **Project** into the Unity launcher/hub history. Don't save your current **Project** into the Unity launcher/hub history.
### runTests ### runTests
Runs tests in the Project. Runs tests in the Project.
### testCategory ### testCategory
A semicolon-separated list of test categories to include in the run. If using both `testFilter` and `testCategory`, then tests only run that matches both. A semicolon-separated list of test categories to include in the run. If using both `testFilter` and `testCategory`, then tests only run that matches both.
### testFilter ### testFilter
A semicolon-separated list of test names to run, or a regular expression pattern to match tests by their full name. A semicolon-separated list of test names to run, or a regular expression pattern to match tests by their full name.
### testPlatform ### testPlatform
The platform you want to run tests on. Available platforms are **EditMode** and **PlayMode**. The platform you want to run tests on. Available platforms are **EditMode** and **PlayMode**.
> **Note**: If unspecified, tests run in Edit Mode by default. > **Note**: If unspecified, tests run in Edit Mode by default.
Platform/Type convention is from the [BuildTarget](https://docs.unity3d.com/ScriptReference/BuildTarget.html) enum. Supported platforms are: Platform/Type convention is from the [BuildTarget](https://docs.unity3d.com/ScriptReference/BuildTarget.html) enum. Supported platforms are:
* StandaloneWindows * StandaloneWindows
* StandaloneWindows64 * StandaloneWindows64
* StandaloneLinux64 * StandaloneLinux64
* StandaloneOSX * StandaloneOSX
* iOS * iOS
* Android * Android
* PS4 * PS4
* XboxOne * XboxOne
### assemblyNames ### assemblyNames
A semicolon-separated list of test assemblies to include in the run. A semicolon-separated list of test assemblies to include in the run.
### testResults ### testResults
The path where Unity should save the result file. By default, Unity saves it in the Project’s root folder. The path where Unity should save the result file. By default, Unity saves it in the Project’s root folder.
### playerHeartbeatTimeout ### playerHeartbeatTimeout
The time, in seconds, the editor should wait for heartbeats after starting a test run on a player. This defaults to 10 minutes. The time, in seconds, the editor should wait for heartbeats after starting a test run on a player. This defaults to 10 minutes.
### runSynchronously ### runSynchronously
If included, the test run will run tests synchronously, guaranteeing that all tests runs in one editor update call. Note that this is only supported for EditMode tests, and that tests which take multiple frames (i.e. `[UnityTest]` tests, or tests with `[UnitySetUp]` or `[UnityTearDown]` scaffolding) will be filtered out. If included, the test run will run tests synchronously, guaranteeing that all tests runs in one editor update call. Note that this is only supported for EditMode tests, and that tests which take multiple frames (i.e. `[UnityTest]` tests, or tests with `[UnitySetUp]` or `[UnityTearDown]` scaffolding) will be filtered out.
### testSettingsFile ### testSettingsFile
Path to a *TestSettings.json* file that allows you to set up extra options for your test run. An example of the *TestSettings.json* file could look like this: Path to a *TestSettings.json* file that allows you to set up extra options for your test run. An example of the *TestSettings.json* file could look like this:
```json ```json
{ {
"scriptingBackend":2, "scriptingBackend":2,
"Architecture":null, "Architecture":null,
"apiProfile":0 "apiProfile":0
} }
``` ```
#### apiProfile #### apiProfile
The .Net compatibility level. Set to one of the following values: The .Net compatibility level. Set to one of the following values:
- 1 - .Net 2.0 - 1 - .Net 2.0
- 2 - .Net 2.0 Subset - 2 - .Net 2.0 Subset
- 3 - .Net 4.6 - 3 - .Net 4.6
- 5 - .Net micro profile (used by Mono scripting backend if **Stripping Level** is set to **Use micro mscorlib**) - 5 - .Net micro profile (used by Mono scripting backend if **Stripping Level** is set to **Use micro mscorlib**)
- 6 - .Net Standard 2.0 - 6 - .Net Standard 2.0
#### appleEnableAutomaticSigning #### appleEnableAutomaticSigning
Sets option for automatic signing of Apple devices. Sets option for automatic signing of Apple devices.
#### appleDeveloperTeamID #### appleDeveloperTeamID
Sets the team ID for the apple developer account. Sets the team ID for the apple developer account.
#### architecture #### architecture
Target architecture for Android. Set to one of the following values: Target architecture for Android. Set to one of the following values:
* None = 0 * None = 0
* ARMv7 = 1 * ARMv7 = 1
* ARM64 = 2 * ARM64 = 2
* X86 = 4 * X86 = 4
* All = 4294967295 * All = 4294967295
#### iOSManualProvisioningProfileType #### iOSManualProvisioningProfileType
Set to one of the following values: Set to one of the following values:
* 0 - Automatic * 0 - Automatic
* 1 - Development * 1 - Development
* 2 - Distribution iOSManualProvisioningProfileID * 2 - Distribution iOSManualProvisioningProfileID
#### scriptingBackend #### scriptingBackend
Set to one of the following values: Set to one of the following values:
- Mono2x = 0 - Mono2x = 0
- IL2CPP = 1 - IL2CPP = 1
- WinRT DotNET = 2 - WinRT DotNET = 2
\ No newline at end of file
# ColorEqualityComparer # ColorEqualityComparer
Use this class to compare two `Color` objects. `ColorEqualityComparer.Instance` has default calculation error value set to 0.01f. To set a test specific error value instantiate a comparer instance using the [one argument constructor](#constructors). Use this class to compare two `Color` objects. `ColorEqualityComparer.Instance` has default calculation error value set to 0.01f. To set a test specific error value instantiate a comparer instance using the [one argument constructor](#constructors).
## Static properties ## Static properties
| Syntax | Description | | Syntax | Description |
| ---------- | ------------------------------------------------------------ | | ---------- | ------------------------------------------------------------ |
| `Instance` | A singleton instance of the comparer with a default error value set to 0.01f. | | `Instance` | A singleton instance of the comparer with a default error value set to 0.01f. |
## Constructors ## Constructors
| Syntax | Description | | Syntax | Description |
| ------------------------------------ | ------------------------------------------------------------ | | ------------------------------------ | ------------------------------------------------------------ |
| `ColorEqualityComparer(float error)` | Creates an instance of the comparer with a custom error value. | | `ColorEqualityComparer(float error)` | Creates an instance of the comparer with a custom error value. |
## Public methods ## Public methods
| Syntax | Description | | Syntax | Description |
| -------------------------------------------- | ------------------------------------------------------------ | | -------------------------------------------- | ------------------------------------------------------------ |
| `bool Equals(Color expected, Color actual);` | Compares the actual and expected `Color` objects for equality using `Utils.AreFloatsEqualAbsoluteError` to compare the `RGB` and `Alpha` attributes of `Color`. Returns `true` if expected and actual objects are equal otherwise, it returns `false`. | | `bool Equals(Color expected, Color actual);` | Compares the actual and expected `Color` objects for equality using `Utils.AreFloatsEqualAbsoluteError` to compare the `RGB` and `Alpha` attributes of `Color`. Returns `true` if expected and actual objects are equal otherwise, it returns `false`. |
## Example ## Example
```c# ```c#
[TestFixture] [TestFixture]
public class ColorEqualityTest public class ColorEqualityTest
{ {
[Test] [Test]
public void GivenColorsAreEqual_WithAllowedCalculationError() public void GivenColorsAreEqual_WithAllowedCalculationError()
{ {
// Using default error // Using default error
var firstColor = new Color(0f, 0f, 0f, 0f); var firstColor = new Color(0f, 0f, 0f, 0f);
var secondColor = new Color(0f, 0f, 0f, 0f); var secondColor = new Color(0f, 0f, 0f, 0f);
Assert.That(firstColor, Is.EqualTo(secondColor).Using(ColorEqualityComparer.Instance)); Assert.That(firstColor, Is.EqualTo(secondColor).Using(ColorEqualityComparer.Instance));
// Allowed error 10e-5f // Allowed error 10e-5f
var comparer = new ColorEqualityComparer(10e-5f); var comparer = new ColorEqualityComparer(10e-5f);
firstColor = new Color(0f, 0f, 0f, 1f); firstColor = new Color(0f, 0f, 0f, 1f);
secondColor = new Color(10e-6f, 0f, 0f, 1f); secondColor = new Color(10e-6f, 0f, 0f, 1f);
Assert.That(firstColor, Is.EqualTo(secondColor).Using(comparer)); Assert.That(firstColor, Is.EqualTo(secondColor).Using(comparer));
} }
} }
``` ```
# Custom equality comparers with equals operator # Custom equality comparers with equals operator
If you need to compare Vectors using the overloaded operator == (see [Vector2.operator ==](https://docs.unity3d.com/ScriptReference/Vector2-operator_eq.html), [Vector3.operator ==](https://docs.unity3d.com/ScriptReference/Vector3-operator_eq.html), and [Vector4.operator ==](https://docs.unity3d.com/ScriptReference/Vector4-operator_eq.html)) you should use the respective comparer implementations: If you need to compare Vectors using the overloaded operator == (see [Vector2.operator ==](https://docs.unity3d.com/ScriptReference/Vector2-operator_eq.html), [Vector3.operator ==](https://docs.unity3d.com/ScriptReference/Vector3-operator_eq.html), and [Vector4.operator ==](https://docs.unity3d.com/ScriptReference/Vector4-operator_eq.html)) you should use the respective comparer implementations:
- Vector2ComparerWithEqualsOperator - Vector2ComparerWithEqualsOperator
- Vector3ComparerWithEqualsOperator - Vector3ComparerWithEqualsOperator
- Vector4ComparerWithEqualsOperator - Vector4ComparerWithEqualsOperator
The interface is the same as for other [equality comparers](./reference-custom-equality-comparers.md) except the public [constructor](./reference-custom-equality-comparers.md#constructors) `error` parameter is inapplicable in this case. The interface is the same as for other [equality comparers](./reference-custom-equality-comparers.md) except the public [constructor](./reference-custom-equality-comparers.md#constructors) `error` parameter is inapplicable in this case.
## Example ## Example
```c# ```c#
[TestFixture] [TestFixture]
public class Vector3Test public class Vector3Test
{ {
[Test] [Test]
public void VerifyThat_TwoVector3ObjectsAreEqual() public void VerifyThat_TwoVector3ObjectsAreEqual()
{ {
var actual = new Vector3(10e-7f, 10e-7f, 10e-7f); var actual = new Vector3(10e-7f, 10e-7f, 10e-7f);
var expected = new Vector3(0f, 0f, 0f); var expected = new Vector3(0f, 0f, 0f);
Assert.That(actual, Is.EqualTo(expected).Using(Vector3ComparerWithEqualsOperator.Instance)); Assert.That(actual, Is.EqualTo(expected).Using(Vector3ComparerWithEqualsOperator.Instance));
} }
} }
``` ```
# FloatEqualityComparer # FloatEqualityComparer
Use this class to compare two float values for equality with [NUnit](http://www.nunit.org/) constraints. Use `FloatEqualityComparer.Instance` comparer to have the default error value set to 0.0001f. For any other error, use the [one argument constructor](#constructors) to create a comparer. Use this class to compare two float values for equality with [NUnit](http://www.nunit.org/) constraints. Use `FloatEqualityComparer.Instance` comparer to have the default error value set to 0.0001f. For any other error, use the [one argument constructor](#constructors) to create a comparer.
## Static Properties ## Static Properties
| Syntax | Description | | Syntax | Description |
| ---------- | ------------------------------------------------------------ | | ---------- | ------------------------------------------------------------ |
| `Instance` | A singleton instance of the comparer with a default error value set to 0.0001f. | | `Instance` | A singleton instance of the comparer with a default error value set to 0.0001f. |
## Constructors ## Constructors
| Syntax | Description | | Syntax | Description |
| ------------------------------------------- | ------------------------------------------------------------ | | ------------------------------------------- | ------------------------------------------------------------ |
| `FloatEqualityComparer(float allowedError)` | Creates an instance of the comparer with a custom error value. | | `FloatEqualityComparer(float allowedError)` | Creates an instance of the comparer with a custom error value. |
## Public methods ## Public methods
| Syntax | Description | | Syntax | Description |
| -------------------------------------------- | ------------------------------------------------------------ | | -------------------------------------------- | ------------------------------------------------------------ |
| `bool Equals(float expected, float actual);` | Compares the `actual` and `expected` float values for equality using `Utils.AreFloatsEqual`. | | `bool Equals(float expected, float actual);` | Compares the `actual` and `expected` float values for equality using `Utils.AreFloatsEqual`. |
## Example ## Example
```c# ```c#
[TestFixture] [TestFixture]
public class FloatsTest public class FloatsTest
{ {
[Test] [Test]
public void VerifyThat_TwoFloatsAreEqual() public void VerifyThat_TwoFloatsAreEqual()
{ {
var comparer = new FloatEqualityComparer(10e-6f); var comparer = new FloatEqualityComparer(10e-6f);
var actual = -0.00009f; var actual = -0.00009f;
var expected = 0.00009f; var expected = 0.00009f;
Assert.That(actual, Is.EqualTo(expected).Using(comparer)); Assert.That(actual, Is.EqualTo(expected).Using(comparer));
// Default relative error 0.0001f // Default relative error 0.0001f
actual = 10e-8f; actual = 10e-8f;
expected = 0f; expected = 0f;
Assert.That(actual, Is.EqualTo(expected).Using(FloatEqualityComparer.Instance)); Assert.That(actual, Is.EqualTo(expected).Using(FloatEqualityComparer.Instance));
} }
} }
``` ```
# QuaternionEqualityComparer # QuaternionEqualityComparer
Use this utility to compare two [Quaternion](https://docs.unity3d.com/ScriptReference/Quaternion.html) objects for equality with [NUnit](http://www.nunit.org/) assertion constraints. Use the static instance `QuaternionEqualityComparer.Instance` to have the default calculation error value set to 0.00001f. For any other custom error value, use the [one argument constructor](#constructors). Use this utility to compare two [Quaternion](https://docs.unity3d.com/ScriptReference/Quaternion.html) objects for equality with [NUnit](http://www.nunit.org/) assertion constraints. Use the static instance `QuaternionEqualityComparer.Instance` to have the default calculation error value set to 0.00001f. For any other custom error value, use the [one argument constructor](#constructors).
## Static properties ## Static properties
| Syntax | Description | | Syntax | Description |
| ---------- | ---------------------------------------------------------- | | ---------- | ---------------------------------------------------------- |
| `Instance` | A comparer instance with the default error value 0.00001f. | | `Instance` | A comparer instance with the default error value 0.00001f. |
## Constructors ## Constructors
| Syntax | Description | | Syntax | Description |
| ------------------------------------------------ | ------------------------------------------------------------ | | ------------------------------------------------ | ------------------------------------------------------------ |
| `QuaternionEqualityComparer(float allowedError)` | Creates an instance of the comparer with a custom allowed error value. | | `QuaternionEqualityComparer(float allowedError)` | Creates an instance of the comparer with a custom allowed error value. |
## Public methods ## Public methods
| Syntax | Description | | Syntax | Description |
| ----------------------------------------------------- | ------------------------------------------------------------ | | ----------------------------------------------------- | ------------------------------------------------------------ |
| `bool Equals(Quaternion expected, Quaternion actual)` | Compares the `actual` and `expected` `Quaternion` objects for equality using the [Quaternion.Dot](https://docs.unity3d.com/ScriptReference/Quaternion.Dot.html) method. | | `bool Equals(Quaternion expected, Quaternion actual)` | Compares the `actual` and `expected` `Quaternion` objects for equality using the [Quaternion.Dot](https://docs.unity3d.com/ScriptReference/Quaternion.Dot.html) method. |
## Example ## Example
```c# ```c#
[TestFixture] [TestFixture]
public class QuaternionTest public class QuaternionTest
{ {
[Test] [Test]
public void VerifyThat_TwoQuaternionsAreEqual() public void VerifyThat_TwoQuaternionsAreEqual()
{ {
var actual = new Quaternion(10f, 0f, 0f, 0f); var actual = new Quaternion(10f, 0f, 0f, 0f);
var expected = new Quaternion(1f, 10f, 0f, 0f); var expected = new Quaternion(1f, 10f, 0f, 0f);
var comparer = new QuaternionEqualityComparer(10e-6f); var comparer = new QuaternionEqualityComparer(10e-6f);
Assert.That(actual, Is.EqualTo(expected).Using(comparer)); Assert.That(actual, Is.EqualTo(expected).Using(comparer));
//Using default error 0.00001f //Using default error 0.00001f
actual = new Quaternion(10f, 0f, 0.1f, 0f); actual = new Quaternion(10f, 0f, 0.1f, 0f);
expected = new Quaternion(1f, 10f, 0.1f, 0f); expected = new Quaternion(1f, 10f, 0.1f, 0f);
Assert.That(actual, Is.EqualTo(expected).Using(QuaternionEqualityComparer.Instance)); Assert.That(actual, Is.EqualTo(expected).Using(QuaternionEqualityComparer.Instance));
} }
} }
``` ```
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment