From a07bc82edecd102b6e72c4233b1b8eeb859399ce Mon Sep 17 00:00:00 2001 From: Koji Hasegawa Date: Sun, 5 Jan 2025 20:37:09 +0900 Subject: [PATCH 1/5] Add unloadOthers option into CreateSceneAttribute --- README.md | 5 ++- Runtime/Attributes/CreateSceneAttribute.cs | 30 +++++++++++++++--- .../Attributes/CreateSceneAttributeTest.cs | 31 +++++++++++++++++++ 3 files changed, 60 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index d0c0750..fb9f12d 100644 --- a/README.md +++ b/README.md @@ -180,7 +180,7 @@ public class MyTestClass #### CreateScene -`CreateSceneAttribute` is an NUnit test attribute class to create a new scene before running the test. +`CreateSceneAttribute` is an NUnit test attribute class to create a new scene and activate it before running the test. It has the following benefits: @@ -208,6 +208,9 @@ public class MyTestClass } ``` +> [!TIP] +> If you want to unload other scenes, specify the `unloadOthers` option. + > [!NOTE] > This process runs after `OneTimeSetUp` and before `SetUp` diff --git a/Runtime/Attributes/CreateSceneAttribute.cs b/Runtime/Attributes/CreateSceneAttribute.cs index a5ff1ee..2edf2da 100644 --- a/Runtime/Attributes/CreateSceneAttribute.cs +++ b/Runtime/Attributes/CreateSceneAttribute.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2023 Koji Hasegawa. +// Copyright (c) 2023-2025 Koji Hasegawa. // This software is released under the MIT License. using System; @@ -22,22 +22,25 @@ public class CreateSceneAttribute : NUnitAttribute, IOuterUnityTestAction { private readonly bool _camera; private readonly bool _light; + private readonly bool _unloadOthers; private string _newSceneName; /// /// Create a new scene before running this test. - /// + /// /// This process runs after OneTimeSetUp and before SetUp. - /// + /// /// This attribute has the following benefits: /// - Can be use same code for running Edit Mode tests, Play Mode tests in Editor, and on Player /// /// true: create main camera object in new scene - /// true: create directional light object in new scene - public CreateSceneAttribute(bool camera = false, bool light = false) + /// true: create directional light object in new scene + /// true: unload other scenes before creating a new scene + public CreateSceneAttribute(bool camera = false, bool light = false, bool unloadOthers = false) { _camera = camera; _light = light; + _unloadOthers = unloadOthers; } /// @@ -45,6 +48,11 @@ public IEnumerator BeforeTest(ITest test) { _newSceneName = $"Scene of {TestContext.CurrentContext.Test.FullName}"; + if (_unloadOthers) + { + UnloadOtherScenes(); + } + if (Application.isPlaying) { // Play Mode tests @@ -87,5 +95,17 @@ public IEnumerator AfterTest(ITest test) yield return SceneManager.UnloadSceneAsync(_newSceneName); } } + + private static void UnloadOtherScenes() + { + for (var i = 0; i < SceneManager.sceneCount; i++) + { + var scene = SceneManager.GetSceneAt(i); + if (!scene.name.StartsWith("InitTestScene")) + { + SceneManager.UnloadSceneAsync(scene); + } + } + } } } diff --git a/Tests/Runtime/Attributes/CreateSceneAttributeTest.cs b/Tests/Runtime/Attributes/CreateSceneAttributeTest.cs index 87fbdb1..38fcb03 100644 --- a/Tests/Runtime/Attributes/CreateSceneAttributeTest.cs +++ b/Tests/Runtime/Attributes/CreateSceneAttributeTest.cs @@ -80,5 +80,36 @@ public IEnumerator AttachToUnityTest_CreateNewScene() yield return null; } + + [TestFixture] + public class UnloadOthersOptionTest + { + private const string TestSceneName = "UnloadOthersOptionTestScene"; + + [Test] + [Order(0)] + public void UnloadOthersOption_BeforeTest() + { + SceneManager.CreateScene(TestSceneName); // create dummy scene, not activate. + } + + [Test] + [Order(1)] + [CreateScene(unloadOthers: false)] + public void UnloadOthersOption_False_NotUnloadOtherScenes() + { + var scene = SceneManager.GetSceneByName(TestSceneName); + Assert.That(scene.isLoaded, Is.True); + } + + [Test] + [Order(2)] + [CreateScene(unloadOthers: true)] + public void UnloadOthersOption_True_UnloadOtherScenes() + { + var scene = SceneManager.GetSceneByName(TestSceneName); + Assert.That(scene.isLoaded, Is.False); + } + } } } From 3eec7e7e5a29a9f2fb9c78f097a2b449b9bcb848 Mon Sep 17 00:00:00 2001 From: Koji Hasegawa Date: Sun, 5 Jan 2025 20:50:41 +0900 Subject: [PATCH 2/5] Move Edit Mode tests for Attributes --- Tests/Editor/Attributes.meta | 3 +++ Tests/Editor/{ => Attributes}/CreateSceneAttributeTest.cs | 4 ++-- .../Editor/{ => Attributes}/CreateSceneAttributeTest.cs.meta | 0 Tests/Editor/{ => Attributes}/LoadSceneAttributeTest.cs | 2 +- Tests/Editor/{ => Attributes}/LoadSceneAttributeTest.cs.meta | 0 5 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 Tests/Editor/Attributes.meta rename Tests/Editor/{ => Attributes}/CreateSceneAttributeTest.cs (81%) rename Tests/Editor/{ => Attributes}/CreateSceneAttributeTest.cs.meta (100%) rename Tests/Editor/{ => Attributes}/LoadSceneAttributeTest.cs (94%) rename Tests/Editor/{ => Attributes}/LoadSceneAttributeTest.cs.meta (100%) diff --git a/Tests/Editor/Attributes.meta b/Tests/Editor/Attributes.meta new file mode 100644 index 0000000..d17e107 --- /dev/null +++ b/Tests/Editor/Attributes.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 912055310dc64f9daa2580b98c5dec62 +timeCreated: 1736077667 \ No newline at end of file diff --git a/Tests/Editor/CreateSceneAttributeTest.cs b/Tests/Editor/Attributes/CreateSceneAttributeTest.cs similarity index 81% rename from Tests/Editor/CreateSceneAttributeTest.cs rename to Tests/Editor/Attributes/CreateSceneAttributeTest.cs index b50e956..0728e04 100644 --- a/Tests/Editor/CreateSceneAttributeTest.cs +++ b/Tests/Editor/Attributes/CreateSceneAttributeTest.cs @@ -6,7 +6,7 @@ using UnityEngine; using UnityEngine.SceneManagement; -namespace TestHelper.Editor +namespace TestHelper.Editor.Attributes { [TestFixture] public class CreateSceneAttributeTest @@ -17,7 +17,7 @@ public void Attach_CreateNewSceneWithCameraAndLight() { var scene = SceneManager.GetActiveScene(); Assert.That(scene.name, Is.EqualTo( - "Scene of TestHelper.Editor.CreateSceneAttributeTest.Attach_CreateNewSceneWithCameraAndLight")); + "Scene of TestHelper.Editor.Attributes.CreateSceneAttributeTest.Attach_CreateNewSceneWithCameraAndLight")); var camera = GameObject.Find("Main Camera"); Assert.That(camera, Is.Not.Null); diff --git a/Tests/Editor/CreateSceneAttributeTest.cs.meta b/Tests/Editor/Attributes/CreateSceneAttributeTest.cs.meta similarity index 100% rename from Tests/Editor/CreateSceneAttributeTest.cs.meta rename to Tests/Editor/Attributes/CreateSceneAttributeTest.cs.meta diff --git a/Tests/Editor/LoadSceneAttributeTest.cs b/Tests/Editor/Attributes/LoadSceneAttributeTest.cs similarity index 94% rename from Tests/Editor/LoadSceneAttributeTest.cs rename to Tests/Editor/Attributes/LoadSceneAttributeTest.cs index a9b3dcc..4564bdd 100644 --- a/Tests/Editor/LoadSceneAttributeTest.cs +++ b/Tests/Editor/Attributes/LoadSceneAttributeTest.cs @@ -5,7 +5,7 @@ using TestHelper.Attributes; using UnityEngine; -namespace TestHelper.Editor +namespace TestHelper.Editor.Attributes { [TestFixture] public class LoadSceneAttributeTest diff --git a/Tests/Editor/LoadSceneAttributeTest.cs.meta b/Tests/Editor/Attributes/LoadSceneAttributeTest.cs.meta similarity index 100% rename from Tests/Editor/LoadSceneAttributeTest.cs.meta rename to Tests/Editor/Attributes/LoadSceneAttributeTest.cs.meta From 2ec939b8800d203e5ad2c2226b0c9e4bdee3014b Mon Sep 17 00:00:00 2001 From: Koji Hasegawa Date: Sun, 5 Jan 2025 21:03:34 +0900 Subject: [PATCH 3/5] Refactor --- Runtime/Attributes/CreateSceneAttribute.cs | 49 ++++++++++++++-------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/Runtime/Attributes/CreateSceneAttribute.cs b/Runtime/Attributes/CreateSceneAttribute.cs index 2edf2da..be14c9a 100644 --- a/Runtime/Attributes/CreateSceneAttribute.cs +++ b/Runtime/Attributes/CreateSceneAttribute.cs @@ -23,7 +23,8 @@ public class CreateSceneAttribute : NUnitAttribute, IOuterUnityTestAction private readonly bool _camera; private readonly bool _light; private readonly bool _unloadOthers; - private string _newSceneName; + private Scene _beforeActiveScene; + private Scene _newScene; /// /// Create a new scene before running this test. @@ -46,25 +47,27 @@ public CreateSceneAttribute(bool camera = false, bool light = false, bool unload /// public IEnumerator BeforeTest(ITest test) { - _newSceneName = $"Scene of {TestContext.CurrentContext.Test.FullName}"; + var newSceneName = $"Scene of {TestContext.CurrentContext.Test.FullName}"; if (_unloadOthers) { - UnloadOtherScenes(); + yield return UnloadOtherScenes(); } + _beforeActiveScene = SceneManager.GetActiveScene(); + if (Application.isPlaying) { // Play Mode tests - var scene = SceneManager.CreateScene(_newSceneName); - SceneManager.SetActiveScene(scene); + _newScene = SceneManager.CreateScene(newSceneName); + SceneManager.SetActiveScene(_newScene); } else { #if UNITY_EDITOR // Edit Mode tests - var scene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene); - scene.name = _newSceneName; + _newScene = EditorSceneManager.NewScene(NewSceneSetup.EmptyScene); + _newScene.name = newSceneName; #endif } @@ -87,25 +90,35 @@ public IEnumerator BeforeTest(ITest test) yield return null; } - /// - public IEnumerator AfterTest(ITest test) - { - if (Application.isPlaying && SceneManager.GetActiveScene().name == _newSceneName) - { - yield return SceneManager.UnloadSceneAsync(_newSceneName); - } - } - - private static void UnloadOtherScenes() + private static IEnumerator UnloadOtherScenes() { for (var i = 0; i < SceneManager.sceneCount; i++) { var scene = SceneManager.GetSceneAt(i); if (!scene.name.StartsWith("InitTestScene")) { - SceneManager.UnloadSceneAsync(scene); + yield return SceneManager.UnloadSceneAsync(scene); } } } + + /// + public IEnumerator AfterTest(ITest test) + { + if (!Application.isPlaying) + { + yield break; + } + + if (_beforeActiveScene.isLoaded) + { + SceneManager.SetActiveScene(_beforeActiveScene); + } + + if (SceneManager.GetActiveScene() != _newScene) + { + yield return SceneManager.UnloadSceneAsync(_newScene); + } + } } } From b00b170a6c189540d2ecafc89ab5bbd118d84261 Mon Sep 17 00:00:00 2001 From: Koji Hasegawa Date: Sun, 5 Jan 2025 22:55:01 +0900 Subject: [PATCH 4/5] Fix unload scenes --- Runtime/Attributes/CreateSceneAttribute.cs | 33 +++++++++++-------- .../Attributes/CreateSceneAttributeTest.cs | 2 +- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/Runtime/Attributes/CreateSceneAttribute.cs b/Runtime/Attributes/CreateSceneAttribute.cs index be14c9a..8864e0a 100644 --- a/Runtime/Attributes/CreateSceneAttribute.cs +++ b/Runtime/Attributes/CreateSceneAttribute.cs @@ -3,6 +3,7 @@ using System; using System.Collections; +using System.Collections.Generic; using NUnit.Framework; using NUnit.Framework.Interfaces; using UnityEngine; @@ -49,11 +50,6 @@ public IEnumerator BeforeTest(ITest test) { var newSceneName = $"Scene of {TestContext.CurrentContext.Test.FullName}"; - if (_unloadOthers) - { - yield return UnloadOtherScenes(); - } - _beforeActiveScene = SceneManager.GetActiveScene(); if (Application.isPlaying) @@ -87,17 +83,31 @@ public IEnumerator BeforeTest(ITest test) light.color = new Color(0xff, 0xf4, 0xd6); } - yield return null; + if (_unloadOthers) + { + yield return UnloadOtherScenes(); + } } - private static IEnumerator UnloadOtherScenes() + private IEnumerator UnloadOtherScenes() { + var scenes = new List(); + for (var i = 0; i < SceneManager.sceneCount; i++) { var scene = SceneManager.GetSceneAt(i); - if (!scene.name.StartsWith("InitTestScene")) + if (scene != _newScene && !scene.name.StartsWith("InitTestScene")) { - yield return SceneManager.UnloadSceneAsync(scene); + scenes.Add(scene); + } + } + + foreach (var scene in scenes) + { + var asyncOperation = SceneManager.UnloadSceneAsync(scene); + while (asyncOperation != null && !asyncOperation.isDone) + { + yield return null; } } } @@ -105,11 +115,6 @@ private static IEnumerator UnloadOtherScenes() /// public IEnumerator AfterTest(ITest test) { - if (!Application.isPlaying) - { - yield break; - } - if (_beforeActiveScene.isLoaded) { SceneManager.SetActiveScene(_beforeActiveScene); diff --git a/Tests/Runtime/Attributes/CreateSceneAttributeTest.cs b/Tests/Runtime/Attributes/CreateSceneAttributeTest.cs index 38fcb03..e50b6a1 100644 --- a/Tests/Runtime/Attributes/CreateSceneAttributeTest.cs +++ b/Tests/Runtime/Attributes/CreateSceneAttributeTest.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2023 Koji Hasegawa. +// Copyright (c) 2023-2025 Koji Hasegawa. // This software is released under the MIT License. using System.Collections; From debbc854b34792b47a1e7149622e645fb2f368f2 Mon Sep 17 00:00:00 2001 From: Koji Hasegawa Date: Mon, 6 Jan 2025 02:51:58 +0900 Subject: [PATCH 5/5] Fix test threshold --- Tests/RuntimeInternals/ScreenshotHelperTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/RuntimeInternals/ScreenshotHelperTest.cs b/Tests/RuntimeInternals/ScreenshotHelperTest.cs index a00762c..5ae4ddf 100644 --- a/Tests/RuntimeInternals/ScreenshotHelperTest.cs +++ b/Tests/RuntimeInternals/ScreenshotHelperTest.cs @@ -46,7 +46,7 @@ public IEnumerator TakeScreenshot_SaveToDefaultPath() yield return ScreenshotHelper.TakeScreenshot(); // default filename is member name when internal - Assert.That(new FileInfo(path), Has.Length.GreaterThan(FileSizeThreshold)); + Assert.That(new FileInfo(path), Has.Length.GreaterThanOrEqualTo(FileSizeThreshold)); } [UnityTest]