Skip to content

Commit

Permalink
Merge pull request #113 from nowsprinting/feature/unload_other_scenes…
Browse files Browse the repository at this point in the history
…_option

Add unloadOthers option into CreateSceneAttribute
  • Loading branch information
nowsprinting authored Jan 5, 2025
2 parents 9f02cb0 + debbc85 commit 4f00648
Show file tree
Hide file tree
Showing 9 changed files with 95 additions and 20 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:

Expand Down Expand Up @@ -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`
Expand Down
66 changes: 52 additions & 14 deletions Runtime/Attributes/CreateSceneAttribute.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
// Copyright (c) 2023 Koji Hasegawa.
// Copyright (c) 2023-2025 Koji Hasegawa.
// This software is released under the MIT License.

using System;
using System.Collections;
using System.Collections.Generic;
using NUnit.Framework;
using NUnit.Framework.Interfaces;
using UnityEngine;
Expand All @@ -22,41 +23,47 @@ public class CreateSceneAttribute : NUnitAttribute, IOuterUnityTestAction
{
private readonly bool _camera;
private readonly bool _light;
private string _newSceneName;
private readonly bool _unloadOthers;
private Scene _beforeActiveScene;
private Scene _newScene;

/// <summary>
/// Create a new scene before running this test.
///
///
/// This process runs after <c>OneTimeSetUp</c> and before <c>SetUp</c>.
///
///
/// This attribute has the following benefits:
/// - Can be use same code for running Edit Mode tests, Play Mode tests in Editor, and on Player
/// </summary>
/// <param name="camera">true: create main camera object in new scene</param>
/// <param name="light">true: create directional light object in new scene</param>
public CreateSceneAttribute(bool camera = false, bool light = false)
/// <param name="light">true: create directional light object in new scene</param>
/// <param name="unloadOthers">true: unload other scenes before creating a new scene</param>
public CreateSceneAttribute(bool camera = false, bool light = false, bool unloadOthers = false)
{
_camera = camera;
_light = light;
_unloadOthers = unloadOthers;
}

/// <inheritdoc />
public IEnumerator BeforeTest(ITest test)
{
_newSceneName = $"Scene of {TestContext.CurrentContext.Test.FullName}";
var newSceneName = $"Scene of {TestContext.CurrentContext.Test.FullName}";

_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
}

Expand All @@ -76,15 +83,46 @@ public IEnumerator BeforeTest(ITest test)
light.color = new Color(0xff, 0xf4, 0xd6);
}

yield return null;
if (_unloadOthers)
{
yield return UnloadOtherScenes();
}
}

private IEnumerator UnloadOtherScenes()
{
var scenes = new List<Scene>();

for (var i = 0; i < SceneManager.sceneCount; i++)
{
var scene = SceneManager.GetSceneAt(i);
if (scene != _newScene && !scene.name.StartsWith("InitTestScene"))
{
scenes.Add(scene);
}
}

foreach (var scene in scenes)
{
var asyncOperation = SceneManager.UnloadSceneAsync(scene);
while (asyncOperation != null && !asyncOperation.isDone)
{
yield return null;
}
}
}

/// <inheritdoc />
public IEnumerator AfterTest(ITest test)
{
if (Application.isPlaying && SceneManager.GetActiveScene().name == _newSceneName)
if (_beforeActiveScene.isLoaded)
{
SceneManager.SetActiveScene(_beforeActiveScene);
}

if (SceneManager.GetActiveScene() != _newScene)
{
yield return SceneManager.UnloadSceneAsync(_newSceneName);
yield return SceneManager.UnloadSceneAsync(_newScene);
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions Tests/Editor/Attributes.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using UnityEngine;
using UnityEngine.SceneManagement;

namespace TestHelper.Editor
namespace TestHelper.Editor.Attributes
{
[TestFixture]
public class CreateSceneAttributeTest
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using TestHelper.Attributes;
using UnityEngine;

namespace TestHelper.Editor
namespace TestHelper.Editor.Attributes
{
[TestFixture]
public class LoadSceneAttributeTest
Expand Down
File renamed without changes.
33 changes: 32 additions & 1 deletion Tests/Runtime/Attributes/CreateSceneAttributeTest.cs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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);
}
}
}
}
2 changes: 1 addition & 1 deletion Tests/RuntimeInternals/ScreenshotHelperTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down

0 comments on commit 4f00648

Please sign in to comment.