{"id":46503042,"url":"https://github.com/nowsprinting/test-helper","last_synced_at":"2026-03-06T14:02:07.197Z","repository":{"id":167579252,"uuid":"643198745","full_name":"nowsprinting/test-helper","owner":"nowsprinting","description":"Custom attributes, constraints, and comparers for writing more expressive tests in Unity Test Framework","archived":false,"fork":false,"pushed_at":"2026-03-01T03:33:12.000Z","size":2775,"stargazers_count":29,"open_issues_count":3,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-03-01T05:30:24.116Z","etag":null,"topics":["testing","unity","unity3d"],"latest_commit_sha":null,"homepage":"https://nowsprinting.github.io/test-helper/","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nowsprinting.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["nowsprinting"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":["https://ofuse.me/nowsprinting"]}},"created_at":"2023-05-20T12:08:04.000Z","updated_at":"2026-03-01T03:32:56.000Z","dependencies_parsed_at":"2023-10-27T00:29:18.894Z","dependency_job_id":"250bd091-8e92-4ef9-9fbf-2af7ba9199b2","html_url":"https://github.com/nowsprinting/test-helper","commit_stats":null,"previous_names":["nowsprinting/test-helper"],"tags_count":26,"template":false,"template_full_name":null,"purl":"pkg:github/nowsprinting/test-helper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nowsprinting%2Ftest-helper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nowsprinting%2Ftest-helper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nowsprinting%2Ftest-helper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nowsprinting%2Ftest-helper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nowsprinting","download_url":"https://codeload.github.com/nowsprinting/test-helper/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nowsprinting%2Ftest-helper/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30180638,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-06T12:39:21.703Z","status":"ssl_error","status_checked_at":"2026-03-06T12:36:09.819Z","response_time":250,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["testing","unity","unity3d"],"created_at":"2026-03-06T14:02:06.217Z","updated_at":"2026-03-06T14:02:07.145Z","avatar_url":"https://github.com/nowsprinting.png","language":"C#","funding_links":["https://github.com/sponsors/nowsprinting","https://ofuse.me/nowsprinting"],"categories":[],"sub_categories":[],"readme":"# Test helper library for Unity Test Framework\n\n[![Meta file check](https://github.com/nowsprinting/test-helper/actions/workflows/metacheck.yml/badge.svg)](https://github.com/nowsprinting/test-helper/actions/workflows/metacheck.yml)\n[![Test](https://github.com/nowsprinting/test-helper/actions/workflows/test.yml/badge.svg)](https://github.com/nowsprinting/test-helper/actions/workflows/test.yml)\n[![openupm](https://img.shields.io/npm/v/com.nowsprinting.test-helper?label=openupm\u0026registry_uri=https://package.openupm.com)](https://openupm.com/packages/com.nowsprinting.test-helper/)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/nowsprinting/test-helper)\n\nCustom attributes, constraints, and comparers for writing more expressive tests in [Unity Test Framework](https://docs.unity3d.com/Packages/com.unity.test-framework@latest).  \nRequired Unity 2019 LTS or later.\n\n\n\n## Features\n\n### Attributes\n\n#### BuildScene\n\n`BuildSceneAttribute` is a NUnit test attribute class that build a scene before running the test on player.\n\nThis attribute has the following benefits:\n\n- Scenes that are **NOT** in \"Scenes in Build\" can be specified.\n- The scene file path can be specified as a relative path from the test class file.\n\nThis attribute can be placed on the test method, the test class (`TestFixture`), and the test assembly.\nCan be used with sync `Test`, async `Test`, and `UnityTest`.\n\nUsage:\n\n```csharp\n[TestFixture]\npublic class MyTestClass\n{\n    [Test]\n    [BuildScene(\"Assets/Path/To/Tests/Scenes/TestScene.unity\")]\n    public void MyTestMethod()\n    {\n        // Setup before load scene\n\n        // Load scene\n        await SceneManagerHelper.LoadSceneAsync(\"Assets/Path/To/Tests/Scenes/TestScene.unity\");\n\n        // Excercise the test\n    }\n\n    [Test]\n    [BuildScene(\"../../Scenes/SampleScene.unity\")]\n    public void UsingRelativePath()\n    {\n        // snip\n    }\n}\n```\n\n\u003e [!NOTE]  \n\u003e If you want to load the scene before the test, use [LoadSceneAttribute](#loadscene) instead.\n\n\n#### CreateScene\n\n`CreateSceneAttribute` is an NUnit test attribute class to create a new scene and activate it before running the test.\n\nThis attribute has the following benefits:\n\n- Can use the same code for running Edit Mode tests, Play Mode tests in Editor, and on Player\n\nThis attribute can be placed on the test method only.\nCan be used with sync `Test`, async `Test`, and `UnityTest`.\n\nUsage:\n\n```csharp\n[TestFixture]\npublic class MyTestClass\n{\n    [Test]\n    [CreateScene(camera: true, light: true)]\n    public void MyTestMethod()\n    {\n        var camera = GameObject.Find(\"Main Camera\");\n        Assert.That(camera, Is.Not.Null);\n\n        var light = GameObject.Find(\"Directional Light\");\n        Assert.That(light, Is.Not.Null);\n    }\n}\n```\n\n\u003e [!TIP]  \n\u003e If you want to unload other scenes, specify the `unloadOthers` option.\n\n\u003e [!NOTE]  \n\u003e This process runs after `OneTimeSetUp` and before `SetUp`\n\n\u003e [!NOTE]  \n\u003e Create or not `Main Camera` and `Directional Light` can be specified with parameters (default is not create)\n\n\n#### FocusGameView\n\n`FocusGameViewAttribute` is an NUnit test attribute class to focus `GameView` or `SimulatorWindow` before running the test.\n\nThis attribute can be placed on the test method, the test class (`TestFixture`), and the test assembly.\nCan be used with sync `Test`, async `Test`, and `UnityTest`.\n\nUsage:\n\n```csharp\n[TestFixture]\npublic class MyTestClass\n{\n    [Test]\n    [FocusGameView]\n    public void MyTestMethod()\n    {\n        // e.g., Test using InputEventTrace of Input System package.\n    }\n}\n```\n\n\u003e [!NOTE]  \n\u003e In batchmode, open `GameView` window.\n\n\n#### GameViewResolution\n\n`GameViewResolutionAttribute` is an NUnit test attribute class to set custom resolution to `GameView` before running the test.\n\nThis attribute can be placed on the test method, the test class (`TestFixture`), and the test assembly.\nCan be used with async `Test` and `UnityTest`.\n\nUsage:\n\n```csharp\n[TestFixture]\npublic class MyTestClass\n{\n    [UnityTest]\n    [GameViewResolution(640, 480, \"VGA\")]\n    public IEnumerator MyTestMethod()\n    {\n        yield return null; // Wait for one frame to apply resolution.\n\n        // e.g., Test using GraphicRaycaster.\n    }\n}\n```\n\n\u003e [!IMPORTANT]  \n\u003e Wait for one frame to apply resolution.\n\u003e However, if used with [CreateSceneAttribute](#createscene) or [LoadSceneAttribute](#loadscene), wait is not necessary.\n\n\u003e [!NOTE]  \n\u003e In batchmode, open `GameView` window.\n\n\n#### GizmosShowOnGameView\n\n`GizmosShowOnGameViewAttribute` is an NUnit test attribute class to show/hide Gizmos on `GameView` during the test running.\n\nThis attribute can be placed on the test method only.\nCan be used with sync `Test`, async `Test`, and `UnityTest`.\n\nUsage:\n\n```csharp\n[TestFixture]\npublic class MyTestClass\n{\n    [Test]\n    [GizmosShowOnGameView(true)]\n    public void MyTestMethod()\n    {\n        // Show Gizmos on GameView during the test running.\n    }\n}\n```\n\n\u003e [!NOTE]  \n\u003e In batchmode, open `GameView` window.\n\n\n#### IgnoreBatchMode\n\n`IgnoreBatchModeAttribute` is an NUnit test attribute class to skip the test execution when run tests with `-batchmode` from the commandline.\n\nThis attribute can be placed on the test method, the test class (`TestFixture`), and the test assembly.\nCan be used with sync `Test`, async `Test`, and `UnityTest`.\n\nUsage:\n\n```csharp\n[TestFixture]\npublic class MyTestClass\n{\n    [UnityTest]\n    [IgnoreBatchMode(\"Using WaitForEndOfFrame.\")]\n    public IEnumerator MyTestMethod()\n    {\n        // e.g., Test needs to take a screenshot.\n\n        yield return new WaitForEndOfFrame();\n        ImageAssert.AreEqual(expectedTexture, Camera.main, settings);\n    }\n}\n```\n\n\n#### IgnoreWindowMode\n\n`IgnoreWindowModeAttribute` is an NUnit test attribute class to skip the test execution when run tests on Unity editor window.\n\nThis attribute can be placed on the test method, the test class (`TestFixture`), and the test assembly.\nCan be used with sync `Test`, async `Test`, and `UnityTest`.\n\nUsage:\n\n```csharp\n[TestFixture]\npublic class MyTestClass\n{\n    [Test]\n    [IgnoreWindowMode(\"Requires command line arguments\")]\n    public void MyTestMethod()\n    {\n        var args = Environment.GetCommandLineArgs();\n        Assert.That(args, Does.Contain(\"-arg1\"));\n    }\n}\n```\n\n\n#### LoadAsset\n\n`LoadAssetAttribute` is a NUnit test attribute class that loads an asset file at the specified path into the field before running the test.\n\nThis attribute has the following benefits:\n\n- The same code can be used for Edit Mode tests and Play Mode tests in Editor and on Player.\n- The asset file path can be specified as a relative path from the test class file.\n\nThis attribute can be placed on the field only.\n\nUsage:\n\n```csharp\n[TestFixture]\npublic class MyTestClass\n{\n    [LoadAsset(\"Assets/Path/To/Tests/Prefabs/Cube.prefab\")]\n    private GameObject _prefab;\n\n    [LoadAsset(\"../../Prefabs/Sphere.prefab\")]\n    private GameObject _relative;\n\n    [OneTimeSetUp]\n    public void OneTimeSetUp()\n    {\n        LoadAssetAttribute.LoadAssets(this);    // Must call this method to load assets.\n    }\n\n    [Test]\n    public void MyTestMethod()\n    {\n        Assume.That(_prefab, Is.Not.Null);  // Already loaded and set to the field.\n    }\n}\n```\n\n\u003e [!IMPORTANT]  \n\u003e Tests that use this attribute must call the `LoadAssets` static method from the `OneTimeSetUp`.\n\n\u003e [!NOTE]  \n\u003e Properties are not supported. You can place attributes in fields by specifying `[field: LoadAsset]`.\n\n\u003e [!NOTE]  \n\u003e The Resources folder copied to run tests on the player is deleted after the run finishes.\n\u003e However, if post-processing is not performed, such as if the Unity editor crashes, the \"Assets/com.nowsprinting.test-helper/Resources\" folder will remain.\n\u003e Recommend adding \"/Assets/com.nowsprinting.test-helper*\" to your project .gitignore file.\n\n\u003e [!NOTE]  \n\u003e Loads asset with `AssetDatabase.LoadAssetAtPath(string,Type)` in the editor, and `Resources.Load(string,Type)` on the player.\n\u003e Asset settings such as image format will conform to the .meta file.\n\n\n#### LoadScene\n\n`LoadSceneAttribute` is a NUnit test attribute class that loads a scene before running the test.\n\nThis attribute has the following benefits:\n\n- The same code can be used for Edit Mode tests and Play Mode tests in Editor and on Player.\n- Scenes that are **NOT** in \"Scenes in Build\" can be specified.\n- The scene file path can be specified as a relative path from the test class file.\n\nThis attribute can be placed on the test method only.\nCan be used with sync `Test`, async `Test`, and `UnityTest`.\n\nUsage:\n\n```csharp\n[TestFixture]\npublic class MyTestClass\n{\n    [Test]\n    [LoadScene(\"Assets/Path/To/Tests/Scenes/TestScene.unity\")]\n    public void MyTestMethod()\n    {\n        var cube = GameObject.Find(\"Cube in TestScene\");\n        Assert.That(cube, Is.Not.Null);\n    }\n\n    [Test]\n    [LoadScene(\"../../Scenes/SampleScene.unity\")]\n    public void UsingRelativePath()\n    {\n        // snip\n    }\n}\n```\n\n\u003e [!NOTE]  \n\u003e This process runs after `OneTimeSetUp` and before `SetUp`.\n\u003e If you want to load during `SetUp` and testing, use [BuildSceneAttribute](#buildscene) and [SceneManagerHelper](#scenemanagerhelper) method instead.\n\n\u003e [!NOTE]  \n\u003e If you use the Raycaster in your tests, you must delay one frame after loading the scene.\n\n\n#### RecordVideo (optional)\n\n`RecordVideoAttribute` is an NUnit test attribute class for recording a video while running the test.\n\nDefault save path is \"`Application.persistentDataPath`/TestHelper/Screenshots/`TestContext.Test.Name`.mp4\".\nYou can specify the save directory by arguments.\nDirectory can also be specified by command line argument `-testHelperScreenshotDirectory`.\n\nThis attribute can be placed on the test method only.\nCan be used with sync `Test`, async `Test`, and `UnityTest`.\n\nUsage:\n\n```csharp\n[TestFixture]\npublic class MyTestClass\n{\n    [Test]\n    [RecordVideo]\n    public void MyTestMethod()\n    {\n        // Recording a video while running the test.\n    }\n}\n```\n\n\u003e [!IMPORTANT]  \n\u003e `RecordVideoAttribute` is an optional functionality. To use it, you need to install the [Instant Replay for Unity](https://github.com/CyberAgentGameEntertainment/InstantReplay) package v1.0.0 or newer separately via the Package Manager window.\n\n\u003e [!IMPORTANT]  \n\u003e `GameView` must be visible. Use [FocusGameViewAttribute](#focusgameview) or [GameViewResolutionAttribute](#gameviewresolution) if running on batchmode.\n\n\u003e [!IMPORTANT]  \n\u003e Do not place on Edit Mode tests.\n\n\n#### TakeScreenshot\n\n`TakeScreenshotAttribute` is an NUnit test attribute class to take a screenshot and save it to a file after running the test.\n\nDefault save path is \"`Application.persistentDataPath`/TestHelper/Screenshots/`TestContext.Test.Name`.png\".\nYou can specify the save directory and/or filename by arguments.\nDirectory can also be specified by command line argument `-testHelperScreenshotDirectory`.\n\nThis attribute can be placed on the test method only.\nCan be used with sync `Test`, async `Test`, and `UnityTest`.\n\nUsage:\n    \n```csharp\n[TestFixture]\npublic class MyTestClass\n{\n    [Test]\n    [TakeScreenshot]\n    public void MyTestMethod()\n    {\n        // Take screenshot after running the test.\n    }\n}\n```\n\n\u003e [!IMPORTANT]  \n\u003e `GameView` must be visible. Use [FocusGameViewAttribute](#focusgameview) or [GameViewResolutionAttribute](#gameviewresolution) if running on batchmode.\n\n\u003e [!IMPORTANT]  \n\u003e Do not place on Edit Mode tests.\n\n\u003e [!NOTE]  \n\u003e If you want to take screenshots at any time, use the [ScreenshotHelper](#screenshothelper) class.\n\n\u003e [!NOTE]  \n\u003e When using MacOS with Metal Graphics API, the following warning appears at runtime. It seems that we should just ignore it.\n\u003e see: https://stackoverflow.com/questions/66062201/unity-warning-ignoring-depth-surface-load-action-as-it-is-memoryless\n\u003e - Ignoring depth surface load action as it is memoryless\n\u003e - Ignoring depth surface store action as it is memoryless\n\n\n#### TimeScale\n\n`TimeScaleAttribute` is an NUnit test attribute class to change the [Time.timeScale](https://docs.unity3d.com/ScriptReference/Time-timeScale.html) during the test running.\n\nThis attribute can be placed on the test method only.\nCan be used with sync `Test`, async `Test`, and `UnityTest`.\n\nUsage:\n\n```csharp\n[TestFixture]\npublic class MyTestClass\n{\n    [Test]\n    [TimeScale(2.0f)]\n    public void MyTestMethod()\n    {\n        // Running at 2x speed.\n    }\n}\n```\n\n\n#### UnityVersion\n\n`UnityVersionAttribute` is an NUnit test attribute class to skip the test run if Unity version is older and/or newer than specified.\n\nThis attribute can be placed on the test method, the test class (`TestFixture`), and the test assembly.\nCan be used with sync `Test`, async `Test`, and `UnityTest`.\n\nUsage:\n\n```csharp\n[TestFixture]\npublic class MyTestClass\n{\n    [Test]\n    [UnityVersion(newerThanOrEqual: \"2022\")]\n    public void MyTestMethod()\n    {\n        // Test run only for Unity 2022.1.0f1 or newer (include specified version).\n    }\n\n    [Test]\n    [UnityVersion(olderThan: \"2019.4.0f1\")]\n    public void MyTestMethod()\n    {\n        // Test run only for Unity older than 2019.4.0f1 (exclude specified version).\n    }\n}\n```\n\n\n\n### Constraints\n\n#### Destroyed\n\n`DestroyedConstraint` tests that a `UnityEngine.Object` is destroyed.\n\nUsage:\n\n```csharp\nusing Is = TestHelper.Constraints.Is;\n\n[TestFixture]\npublic class MyTestClass\n{\n    [Test]\n    public void MyTestMethod()\n    {\n        var actual = GameObject.Find(\"Cube\");\n        GameObject.DestroyImmediate(actual);\n\n        Assert.That(actual, Is.Destroyed);\n    }\n}\n```\n\n\u003e [!NOTE]  \n\u003e When used with operators, use it in method style. e.g., `Is.Not.Destroyed()`\n\n\n\n### Comparers\n\n#### FlipTexture2dEqualityComparer (optional)\n\n`FlipTexture2dEqualityComparer` is a NUnit test comparer class that compares two `Texture2D` using [FLIP](https://github.com/NVlabs/flip).\n\nOutput error map image file if assertion fails.\nDefault output path is \"`Application.persistentDataPath`/TestHelper/Screenshots/`TestContext.Test.Name`.diff.png\".\nYou can specify the output directory and/or filename by constructor arguments.\nDirectory can also be specified by command line argument `-testHelperScreenshotDirectory`.\n\nUsage:\n\n```csharp\n[TestFixture]\npublic class MyTestClass\n{\n    [Test]\n    public async Task MyTestMethod()\n    {\n        await Awaitable.EndOfFrameAsync();\n        var actual = ScreenCapture.CaptureScreenshotAsTexture();\n        var expected = AssetDatabase.LoadAssetAtPath\u003cTexture2D\u003e(ExpectedImagePath);\n\n        var comparer = new FlipTexture2dEqualityComparer(meanErrorTolerance: 0.01f);\n        Assert.That(actual, Is.EqualTo(expected).Using(comparer));\n    }\n}\n```\n\n\u003e [!IMPORTANT]  \n\u003e `FlipTexture2dEqualityComparer` is an optional functionality. To use it, you need to install the [FlipBinding.CSharp](https://www.nuget.org/packages/FlipBinding.CSharp) NuGet package v1.0.0 or newer.\n\u003e Also, add scripting define symbol `ENABLE_FLIP_BINDING` if not installed via OpenUPM (UnityNuGet).\n\n#### XmlComparer\n\n`XmlComparer` is a NUnit test comparer class that compares two `string` as an XML document.\n\nIt only compares the attributes and values of each element in the document unordered.\nXML declarations and comments are ignored, and white spaces, tabs, and newlines before and after the value are ignored.\n\nUsage:\n\n```csharp\n[TestFixture]\npublic class MyTestClass\n{\n    [Test]\n    public void MyTestMethod()\n    {\n        var actual = @\"\u003croot\u003e\u003cchild\u003evalue1\u003c/child\u003e\u003cchild attribute=\"\"attr\"\"\u003evalue2\u003c/child\u003e\u003c/root\u003e\";\n        var expected = @\"\u003c?xml version=\"\"1.0\"\" encoding=\"\"utf-8\"\"?\u003e\n\u003croot\u003e\n  \u003c!-- comment --\u003e\n  \u003cchild attribute=\"\"attr\"\"\u003e\n    value2\n  \u003c/child\u003e\n  \u003c!-- comment --\u003e\n  \u003cchild\u003e\n    value1\n  \u003c/child\u003e\n\u003c/root\u003e\";\n\n        Assert.That(actual, Is.EqualTo(expected).Using(new XmlComparer()));\n    }\n}\n```\n\n\n\n### Statistics APIs\n\n`TestHelper.Statistics` namespace provides utilities for statistical testing, including assertions for pseudo-random number generators (PRNG) and statistical summary tools.\n\n\u003e [!IMPORTANT]  \n\u003e This feature is experimental.\n\u003e It is possible to make breaking changes without respecting SemVer.\n\n\u003e [!NOTE]  \n\u003e This feature is **NOT** statistical hypothesis testing tool.\n\n\n#### Experiment\n\n`Experiment` is a class for running experiments of PRNG.\n\nUsage:\n\n```csharp\n[TestFixture]\npublic class MyStatisticsTest\n{\n    [Test]\n    public void Experiment_2D6()\n    {\n        var sampleSpace = Experiment.Run(\n            () =\u003e DiceGenerator.Roll(2, 6), // 2D6\n            1 \u003c\u003c 20); // 1,048,576 times\n\n        Assert.That(sampleSpace.Max, Is.EqualTo(12));\n        Assert.That(sampleSpace.Min, Is.EqualTo(2));\n    }\n}\n```\n\n\n#### DescriptiveStatistics\n\n`DescriptiveStatistics` is a class for calculate statistical summaries and plotting a histogram.\n\nUsage:\n\n```csharp\n[TestFixture]\npublic class MyStatisticsTest\n{\n    [Test]\n    public void DescriptiveStatistics_2D6()\n    {\n        const int TrialCount = 1 \u003c\u003c 20; // 1,048,576 times\n        const double Tolerance = TrialCount * 0.001d;\n\n        var sampleSpace = Experiment.Run(\n            () =\u003e DiceGenerator.Roll(2, 6), // 2D6\n            TrialCount);\n\n        var statistics = new DescriptiveStatistics\u003cint\u003e();\n        statistics.Calculate(sampleSpace);\n        Debug.Log(statistics.GetSummary()); // Write to console\n\n        Assert.That(statistics.PeakFrequency, Is.EqualTo(TrialCount / 6).Within(Tolerance));\n        Assert.That(statistics.ValleyFrequency, Is.EqualTo(TrialCount / 36).Within(Tolerance));\n        Assert.That(statistics.MedianFrequency, Is.EqualTo(TrialCount / 12).Within(Tolerance));\n        Assert.That(statistics.MeanFrequency, Is.EqualTo(TrialCount / 11).Within(Tolerance));\n    }\n}\n```\n\nConsole output example:\n\n```\nExperimental and Statistical Summary:\n  Sample size: 1,048,576\n  Maximum: 12\n  Minimum: 2\n  Peak frequency: 174,554\n  Valley frequency: 29,070\n  Median frequency: 87,490\n  Mean frequency: 95,325.09\n  Histogram: ▁▂▃▅▆█▆▅▃▂▁\n  (Each bar represents the frequency of values in equally spaced bins.)\n```\n\n\n#### PixelPlot\n\n`PixelPlot` is class that outputs a pixel plot image file.\n\nDefault save path is \"`Application.persistentDataPath`/TestHelper/Statistics/`TestContext.Test.Name`.png\".\nYou can specify the save directory and/or filename by arguments.\nDirectory can also be specified by command line argument `-testHelperStatisticsDirectory`.\n\nUsage:\n\n```csharp\n[TestFixture]\npublic class MyStatisticsTest\n{\n    [Test]\n    public void PixelPlot()\n    {\n        var sampleSpace = Experiment.Run(\n            () =\u003e UnityEngine.Random.value,\n            1 \u003c\u003c 16); // 256x256\n\n        var pixelPlot = new PixelPlot\u003cfloat\u003e();\n        pixelPlot.Plot(sampleSpace);\n        pixelPlot.WriteToFile(\"Path/To/Directory\", \"PixelPlot.png\");\n    }\n}\n```\n\nImage output example;\nLeft: generated by strong PRNG,\nRight: generated by weak (short period) PRNG:\n\n\u003cp\u003e\n\u003cimg src=\"Documentation~/PixelPlot.png\" alt=\"LCG\" width=\"256\" style=\"background-color:white;\"/\u003e\n\u003cimg src=\"Documentation~/PixelPlotShortPeriod.png\" alt=\"Short period LCG\" width=\"256\" style=\"background-color:white;\"/\u003e\n\u003c/p\u003e\n\n\u003e [!IMPORTANT]  \n\u003e Can plot only for samples with value type.\n\n\n\n### Runtime APIs\n\nThe classes in the `TestHelper.RuntimeInternals` assembly can be used from the runtime code because it does not depend on `com.unity.test-framework`.\n\n\u003e [!TIP]  \n\u003e The \"Define Constraints\" is set to `UNITY_INCLUDE_TESTS || INCLUDE_COM_NOWSPRINTING_TEST_HELPER` in this assembly definition files, so it is generally excluded from release builds.\n\u003e To use the feature in release builds, add `INCLUDE_COM_NOWSPRINTING_TEST_HELPER` to the \"Define Symbols\" at build time.  \n\u003e How to set custom scripting symbols, see below:  \n\u003e [Manual: Custom scripting symbols](https://docs.unity3d.com/Manual/custom-scripting-symbols.html)\n\n\n#### SceneManagerHelper\n\n`SceneManagerHelper` is a utility class to load the scene file.\n\nThis method has the following benefits:\n\n- The same code can be used for Edit Mode tests and Play Mode tests in Editor and on Player.\n- The scene file path can be specified as a relative path from the test class file.\n\nUsage:\n\n```csharp\n[TestFixture]\npublic class MyTestClass\n{\n    [Test]\n    public void MyTestMethod()\n    {\n        // Setup before load scene\n\n        // Load scene\n        await SceneManagerHelper.LoadSceneAsync(\"Assets/Path/To/Tests/Scenes/TestScene.unity\");\n\n        // Excercise the test\n    }\n\n    [Test]\n    public void UsingRelativePath()\n    {\n        // Setup before load scene\n\n        // Load scene\n        await SceneManagerHelper.LoadSceneAsync(\"../../Scenes/SampleScene.unity\");\n\n        // Excercise the test\n    }\n}\n```\n\n\u003e [!TIP]  \n\u003e When loading the scene that is not in \"Scenes in Build\", use [BuildSceneAttribute](#buildscene).\n\n\n#### ScreenshotHelper\n\n`ScreenshotHelper` is a utility class to take a screenshot and save it to a file.\n\nDefault save path is \"`Application.persistentDataPath`/TestHelper/Screenshots/`TestContext.Test.Name`.png\".\n(Replace `TestContext.Test.Name` to caller method name when called outside a test context.)\nYou can specify the save directory and/or filename by arguments.\nDirectory can also be specified by command line argument `-testHelperScreenshotDirectory`.\n\nUsage:\n\n```csharp\n[TestFixture]\npublic class MyTestClass\n{\n    [UnityTest]\n    public IEnumerator MyTestMethod()\n    {\n        yield return ScreenshotHelper.TakeScreenshot();\n    }\n\n    [Test]\n    public async Task MyTestMethodAsync()\n    {\n        await ScreenshotHelper.TakeScreenshotAsync();   // Required Unity 2023.3 or newer\n    }\n\n    [Test]\n    public async Task MyTestMethodAsync()\n    {\n        var coroutineRunner = new GameObject().AddComponent\u003cCoroutineRunner\u003e();\n        await ScreenshotHelper.TakeScreenshot().ToUniTask(coroutineRunner); // Required UniTask package\n    }\n\n    private class CoroutineRunner : MonoBehaviour { }\n}\n```\n\n\u003e [!IMPORTANT]  \n\u003e `GameView` must be visible. Use [FocusGameViewAttribute](#focusgameview) or [GameViewResolutionAttribute](#gameviewresolution) if running on batchmode.\n\n\u003e [!IMPORTANT]  \n\u003e Do not place on Edit Mode tests.\n\u003e And must be called from main thread.\n\n\u003e [!TIP]  \n\u003e When using [UniTask](https://github.com/Cysharp/UniTask), you also need a coroutine-runner (any `MonoBehaviour` instance) because the `TakeScreenshot` method uses `WaitForEndOfFrame` internally.\n\u003e See more information: https://github.com/Cysharp/UniTask#ienumeratortounitask-limitation\n\n\u003e [!NOTE]  \n\u003e If you take multiple screenshots in one method, a counter is inserted to prevent overwriting.\n\n\u003e [!NOTE]  \n\u003e When using `TakeScreenshot` method on MacOS with Metal Graphics API, the following warning appears at runtime. It seems that we should just ignore it.\n\u003e see: https://stackoverflow.com/questions/66062201/unity-warning-ignoring-depth-surface-load-action-as-it-is-memoryless\n\u003e - Ignoring depth surface load action as it is memoryless\n\u003e - Ignoring depth surface store action as it is memoryless\n\n\n#### PathHelper\n\nThe `PathHelper.CreateTemporaryFilePath` method provides utilities for creating a temporary file path in running tests.  \nBy default, the path is named by the test name in the directory pointed to by [Application.temporaryCachePath](https://docs.unity3d.com/ScriptReference/Application-temporaryCachePath.html).\n\nUsage:\n\n```csharp\nnamespace MyNamespace\n{\n  [TestFixture]\n  public class MyTestClass\n  {\n    [Test]\n    public void MyTestMethod()\n    {\n      var path = PathHelper.CreateTemporaryFilePath(extension: \"txt\");\n      File.WriteAllText(path, \"test file\");\n      // write to {Application.temporaryCachePath}/MyTestMethod.txt\n\n      var path2 = PathHelper.CreateTemporaryFilePath(extension: \"txt\");\n      File.WriteAllText(path2, \"test file\");\n      // write to {Application.temporaryCachePath}/MyTestMethod_1.txt\n    }\n\n    [Test]\n    public void MyTestMethod2()\n    {\n      var path = PathHelper.CreateTemporaryFilePath(namespaceToDirectory: true);\n      File.WriteAllText(path, \"test file\");\n      // write to {Application.temporaryCachePath}/MyNamespace/MyTestClass/MyTestMethod2\n    }\n  }\n}\n```\n\n\n\n### Editor Extensions\n\n#### Open Persistent Data Directory\n\nSelect menu item **Window \u003e Test Helper \u003e Open Persistent Data Directory**, which opens the directory pointed to by [Application.persistentDataPath](https://docs.unity3d.com/ScriptReference/Application-persistentDataPath.html) in the Finder/ File Explorer.\n\n\n#### Open Temporary Cache Directory\n\nSelect menu item **Window \u003e Test Helper \u003e Open Temporary Cache Directory**, which opens the directory pointed to by [Application.temporaryCachePath](https://docs.unity3d.com/ScriptReference/Application-temporaryCachePath.html) in the Finder/ File Explorer.\n\n\n\n### Commandline Arguments\n\n#### JUnit XML format report\n\nIf you specify path with `-testHelperJUnitResults` command line option, the test result will be written in JUnit XML format when the tests are finished.\n\n\u003e [!NOTE]  \n\u003e The JUnit XML format is the so-called \"Legacy.\" It does not support the \"Open Test Reporting format\" introduced in JUnit 5.\n\n#### GameView resolution\n\nIf you specify display resolution standards (e.g., `VGA`) with the `-testHelperGameViewResolution` command line option, the GameView resolution is set to the specified size when starting the tests.\n\nOr, you can specify width and height with `-testHelperGameViewWidth` and `-testHelperGameViewHeight` command line options.\n\n\n\n## Installation\n\n### 1. Install via Package Manager window\n\n1. Open the Project Settings window (**Editor \u003e Project Settings**) and select **Package Manager** tab (figure 1.)\n2. Click **+** button under the **Scoped Registries** and enter the following settings:\n    1. **Name:** `package.openupm.com`\n    2. **URL:** `https://package.openupm.com`\n    3. **Scope(s):** `com.nowsprinting`\n3. Open the Package Manager window (**Window \u003e Package Manager**) and select **My Registries** tab (figure 2.)\n4. Select **Test Helper** and click the **Install** button\n\n**Figure 1.** Scoped Registries setting in Project Settings window\n\n![](Documentation~/ScopedRegistries_Dark.png#gh-dark-mode-only)\n![](Documentation~/ScopedRegistries_Light.png#gh-light-mode-only)\n\n**Figure 2.** My Registries in Package Manager window\n\n![](Documentation~/PackageManager_Dark.png#gh-dark-mode-only)\n![](Documentation~/PackageManager_Light.png#gh-light-mode-only)\n\n\n### 2. Add assembly reference\n\n1. Open your test assembly definition file (.asmdef) in the Inspector window\n2. Add **TestHelper** into **Assembly Definition References**\n\n\u003e [!NOTE]  \n\u003e Add **TestHelper.RuntimeInternals** into **Assembly Definition References** if you use the [Runtime APIs](#runtime apis).\n\n\n\n## License\n\nMIT License\n\n\n\n## How to contribute\n\nOpen an issue or create a pull request.\n\nBe grateful if you could label the PR as `enhancement`, `bug`, `chore`, and `documentation`.\nSee [PR Labeler settings](.github/pr-labeler.yml) for automatically labeling from the branch name.\n\n\n\n## How to development\n\n### Clone repo as a embedded package\n\nClone this repository as a submodule under the Packages/ directory in your project.\n\n```bash\ngit submodule add git@github.com:nowsprinting/test-helper.git Packages/com.nowsprinting.test-helper\n```\n\n\n### Run tests\n\nGenerate a temporary project and run tests on each Unity version from the command line.\n\n```bash\nmake create_project\nUNITY_VERSION=2019.4.40f1 make -k test\n```\n\n\u003e [!IMPORTANT]  \n\u003e You must select \"Input Manager (Old)\" or \"Both\" in the **Project Settings \u003e Player \u003e Active Input Handling** for running tests.\n\n\u003e [!TIP]  \n\u003e To run all tests, you need to install the following packages in your project:\n\u003e - [UniTask](https://github.com/Cysharp/UniTask) package v2.3.3 or newer.\n\u003e - [FlipBinding.CSharp](https://www.nuget.org/packages/FlipBinding.CSharp) NuGet package v1.0.0 or newer.\n\u003e - [Instant Replay for Unity](https://github.com/CyberAgentGameEntertainment/InstantReplay) package v1.0.0 or newer\n\n\n### Release workflow\n\nThe release process is as follows:\n\n1. Run **Actions \u003e Create release pull request \u003e Run workflow**\n2. Merge created pull request\n\nThen, will do the release process automatically by [Release](.github/workflows/release.yml) workflow.\nAfter tagging, [OpenUPM](https://openupm.com/) retrieves the tag and updates it.\n\n\u003e [!CAUTION]  \n\u003e Do **NOT** manually operation the following operations:\n\u003e - Create a release tag\n\u003e - Publish draft releases\n\n\u003e [!CAUTION]  \n\u003e You must modify the package name to publish a forked package.\n\n\u003e [!TIP]  \n\u003e If you want to specify the version number to be released, change the version number of the draft release before running the \"Create release pull request\" workflow.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnowsprinting%2Ftest-helper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnowsprinting%2Ftest-helper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnowsprinting%2Ftest-helper/lists"}