diff --git a/.editorconfig b/.editorconfig index f283fbd..a50a818 100644 --- a/.editorconfig +++ b/.editorconfig @@ -275,7 +275,7 @@ resharper_merge_into_logical_pattern_highlighting = none resharper_use_negated_pattern_in_is_expression_highlighting = none # Test codes for Unity Test Framework -[Tests/**/*.cs] +[**/Tests/**/*.cs] # Access to a static member of a type via a derived type (e.g., NUnit.Framework.Is) resharper_access_to_static_member_via_derived_type_highlighting = none diff --git a/.github/workflows/test-integration.yml b/.github/workflows/test-integration.yml index a506005..e0ef525 100644 --- a/.github/workflows/test-integration.yml +++ b/.github/workflows/test-integration.yml @@ -22,7 +22,7 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event.inputs.runner }} cancel-in-progress: true -permissions: {} +permissions: { } defaults: run: @@ -41,15 +41,17 @@ jobs: matrix: unityVersion: # Available versions see: https://game.ci/docs/docker/versions - 2019.4.40f1 - - 2020.3.48f1 + - 2020.3.49f1 - 2021.3.45f1 - - 2022.3.59f1 - - 2023.2.20f1 - - 6000.0.41f1 + - 2022.3.62f1 + - 6000.0.43f1 + - 6000.0.44f1 # pin test-framework v1.5.1 + - 6000.0.59f2 # pin test-framework v1.6.0 + - 6000.3.1f1 testMode: - All # run tests in editor include: - - unityVersion: 6000.0.41f1 + - unityVersion: 6000.3.1f1 testMode: Standalone # run tests on player steps: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index c08470f..8a5ce34 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,7 +22,7 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true -permissions: {} +permissions: { } defaults: run: @@ -42,17 +42,21 @@ jobs: matrix: unityVersion: # Available versions see: https://game.ci/docs/docker/versions - 2019.4.40f1 - - 2020.3.48f1 + - 2020.3.49f1 - 2021.3.45f1 - - 2022.3.59f1 - - 2023.2.20f1 - - 6000.0.41f1 + - 2022.3.62f1 + - 6000.0.43f1 + - 6000.0.44f1 # pin test-framework v1.5.1 + - 6000.0.59f2 # pin test-framework v1.6.0 + - 6000.2.5f1 # pin test-framework v1.5.1 + - 6000.2.6f1 # pin test-framework v1.6.0 + - 6000.3.1f1 testMode: - All # run tests in editor include: - - unityVersion: 6000.0.41f1 + - unityVersion: 6000.3.1f1 octocov: true - - unityVersion: 6000.0.41f1 + - unityVersion: 6000.3.1f1 testMode: Standalone # run tests on player steps: diff --git a/Assets/APIExamples/Scripts/Editor/AssemblyInfo.cs b/Assets/APIExamples/Scripts/Editor/AssemblyInfo.cs new file mode 100644 index 0000000..9298f68 --- /dev/null +++ b/Assets/APIExamples/Scripts/Editor/AssemblyInfo.cs @@ -0,0 +1,6 @@ +// Copyright (c) 2021-2025 Koji Hasegawa. +// This software is released under the MIT License. + +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("APIExample.Editor.Tests")] diff --git a/Assets/APIExamples/Scripts/Editor/AssemblyInfo.cs.meta b/Assets/APIExamples/Scripts/Editor/AssemblyInfo.cs.meta new file mode 100644 index 0000000..4fe5608 --- /dev/null +++ b/Assets/APIExamples/Scripts/Editor/AssemblyInfo.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: bc037e1c350f40a3a59332c04c1d04db +timeCreated: 1754943039 \ No newline at end of file diff --git a/Assets/APIExamples/Scripts/Editor/UnityTestFramework/CallbacksExample.cs b/Assets/APIExamples/Scripts/Editor/UnityTestFramework/ICallbacksExample.cs similarity index 83% rename from Assets/APIExamples/Scripts/Editor/UnityTestFramework/CallbacksExample.cs rename to Assets/APIExamples/Scripts/Editor/UnityTestFramework/ICallbacksExample.cs index ab2a276..92c338f 100644 --- a/Assets/APIExamples/Scripts/Editor/UnityTestFramework/CallbacksExample.cs +++ b/Assets/APIExamples/Scripts/Editor/UnityTestFramework/ICallbacksExample.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. using UnityEditor; @@ -8,21 +8,21 @@ namespace APIExamples.Editor.UnityTestFramework { /// - /// Test RunnerコールバックAPI使用例 - /// + /// Test RunnerコールバックAPI使用例. + /// /// /// /// `OnError()`を除いて、に定義されている /// `OnError()`は、にのみ定義されている /// - /// - public class CallbacksExample : IErrorCallbacks + /// + public class ICallbacksExample : IErrorCallbacks { [InitializeOnLoadMethod] private static void SetupCallbacks() { var api = ScriptableObject.CreateInstance(); - api.RegisterCallbacks(new CallbacksExample()); + api.RegisterCallbacks(new ICallbacksExample()); } /// diff --git a/Assets/APIExamples/Scripts/Editor/UnityTestFramework/CallbacksExample.cs.meta b/Assets/APIExamples/Scripts/Editor/UnityTestFramework/ICallbacksExample.cs.meta similarity index 100% rename from Assets/APIExamples/Scripts/Editor/UnityTestFramework/CallbacksExample.cs.meta rename to Assets/APIExamples/Scripts/Editor/UnityTestFramework/ICallbacksExample.cs.meta diff --git a/Assets/APIExamples/Scripts/Editor/UnityTestFramework/ITestRunCallbackExample.cs b/Assets/APIExamples/Scripts/Editor/UnityTestFramework/ITestRunCallbackExample.cs new file mode 100644 index 0000000..122eb44 --- /dev/null +++ b/Assets/APIExamples/Scripts/Editor/UnityTestFramework/ITestRunCallbackExample.cs @@ -0,0 +1,43 @@ +// Copyright (c) 2021-2025 Koji Hasegawa. +// This software is released under the MIT License. + +using APIExamples.Editor.UnityTestFramework; +using NUnit.Framework.Interfaces; +using UnityEngine.TestRunner; + +[assembly: TestRunCallback(typeof(ITestRunCallbackExample))] + +namespace APIExamples.Editor.UnityTestFramework +{ + /// + /// Test RunnerコールバックAPI使用例. + /// + /// + /// + public class ITestRunCallbackExample : ITestRunCallback + { + /// + public void RunStarted(ITest testsToRun) + { + // テスト実行が開始されるときに呼ばれます + } + + /// + public void RunFinished(ITestResult testResults) + { + // テスト実行が終了したときに呼ばれます + } + + /// + public void TestStarted(ITest test) + { + // 個々の(Test Runnerウィンドウにおける)ツリーノードが開始されるときに呼ばれます + } + + /// + public void TestFinished(ITestResult result) + { + // 個々の(Test Runnerウィンドウにおける)ツリーノードが終了したときに呼ばれます + } + } +} diff --git a/Assets/APIExamples/Scripts/Editor/UnityTestFramework/ITestRunCallbackExample.cs.meta b/Assets/APIExamples/Scripts/Editor/UnityTestFramework/ITestRunCallbackExample.cs.meta new file mode 100644 index 0000000..40a8f5b --- /dev/null +++ b/Assets/APIExamples/Scripts/Editor/UnityTestFramework/ITestRunCallbackExample.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 65e817edd8514eebae87af7db8265bf2 +timeCreated: 1764020943 \ No newline at end of file diff --git a/Assets/APIExamples/Scripts/Runtime/AssemblyInfo.cs b/Assets/APIExamples/Scripts/Runtime/AssemblyInfo.cs new file mode 100644 index 0000000..11d7d2d --- /dev/null +++ b/Assets/APIExamples/Scripts/Runtime/AssemblyInfo.cs @@ -0,0 +1,8 @@ +// Copyright (c) 2021-2025 Koji Hasegawa. +// This software is released under the MIT License. + +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("APIExample.Editor")] +[assembly: InternalsVisibleTo("APIExample.Editor.Tests")] +[assembly: InternalsVisibleTo("APIExample.Tests")] diff --git a/Assets/APIExamples/Scripts/Runtime/AssemblyInfo.cs.meta b/Assets/APIExamples/Scripts/Runtime/AssemblyInfo.cs.meta new file mode 100644 index 0000000..ede76e1 --- /dev/null +++ b/Assets/APIExamples/Scripts/Runtime/AssemblyInfo.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: e2cc40258a6e456581745f8d7b639e68 +timeCreated: 1754943055 \ No newline at end of file diff --git a/Assets/APIExamples/Scripts/Runtime/Element.cs b/Assets/APIExamples/Scripts/Runtime/Element.cs index e2fb6fc..8ff1d70 100644 --- a/Assets/APIExamples/Scripts/Runtime/Element.cs +++ b/Assets/APIExamples/Scripts/Runtime/Element.cs @@ -6,11 +6,8 @@ namespace APIExamples { /// - /// 元素的な属性. + /// 元素的な属性 /// - /// - /// このenumは BasicExample.Entities.Enums.Element とは異なります(仕様を簡略化しました) - /// public enum Element { None, @@ -22,7 +19,7 @@ public enum Element public static class ElementExtensions { /// - /// 属性名を返す. + /// 属性名を返す /// /// /// @@ -44,7 +41,7 @@ public static string GetName(this Element self) } /// - /// 属性攻撃を受けたときの被ダメージ倍率を返す. + /// 属性攻撃を受けたときの被ダメージ倍率を返す /// /// /// 攻撃側の属性 diff --git a/Assets/APIExamples/Scripts/Runtime/MyMonoBehaviour.cs b/Assets/APIExamples/Scripts/Runtime/MyMonoBehaviour.cs new file mode 100644 index 0000000..28cd9dd --- /dev/null +++ b/Assets/APIExamples/Scripts/Runtime/MyMonoBehaviour.cs @@ -0,0 +1,44 @@ +// Copyright (c) 2021-2025 Koji Hasegawa. +// This software is released under the MIT License. + +using System.Diagnostics.CodeAnalysis; +using UnityEngine; + +namespace APIExamples +{ + /// + /// のテスト対象. + /// 生成されて5フレームで破棄されます + /// + [SuppressMessage("ReSharper", "InvalidXmlDocComment")] + public class MyMonoBehaviour : MonoBehaviour + { + protected bool _wasAwake; + protected bool _wasStart; + protected bool _wasDestroy; + private int _frameCount; + + private void Awake() + { + _wasAwake = true; + } + + private void Start() + { + _wasStart = true; + } + + private void Update() + { + if (++_frameCount > 4) + { + Destroy(this.gameObject); + } + } + + private void OnDestroy() + { + _wasDestroy = true; + } + } +} diff --git a/Assets/APIExamples/Scripts/Runtime/MyMonoBehaviour.cs.meta b/Assets/APIExamples/Scripts/Runtime/MyMonoBehaviour.cs.meta new file mode 100644 index 0000000..5e2462c --- /dev/null +++ b/Assets/APIExamples/Scripts/Runtime/MyMonoBehaviour.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 254a3dc3653f487ea6edbec0ecb636e2 +timeCreated: 1765029284 \ No newline at end of file diff --git a/Assets/APIExamples/Tests/Editor/APIExamples.Editor.Tests.asmdef b/Assets/APIExamples/Tests/Editor/APIExamples.Editor.Tests.asmdef index bc9c284..3e283a5 100644 --- a/Assets/APIExamples/Tests/Editor/APIExamples.Editor.Tests.asmdef +++ b/Assets/APIExamples/Tests/Editor/APIExamples.Editor.Tests.asmdef @@ -4,7 +4,10 @@ "references": [ "UnityEngine.TestRunner", "UnityEditor.TestRunner", - "UniTask" + "NUnit.Analyzers_Unity", + "APIExamples.Tests", + "UniTask", + "TestHelper" ], "includePlatforms": [ "Editor" diff --git a/Assets/APIExamples/Tests/Editor/AssemblyInfo.cs b/Assets/APIExamples/Tests/Editor/AssemblyInfo.cs index 13b338d..d26dd20 100644 --- a/Assets/APIExamples/Tests/Editor/AssemblyInfo.cs +++ b/Assets/APIExamples/Tests/Editor/AssemblyInfo.cs @@ -1,6 +1,5 @@ -// Copyright (c) 2021-2022 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. -using NUnit.Framework; -[assembly: Category("APIExamples")] + diff --git a/Assets/APIExamples/Tests/Editor/NUnit/AsyncSetupAttributeExample.cs b/Assets/APIExamples/Tests/Editor/NUnit/AsyncSetupAttributeExample.cs index 02a2f6d..7cf8cfa 100644 --- a/Assets/APIExamples/Tests/Editor/NUnit/AsyncSetupAttributeExample.cs +++ b/Assets/APIExamples/Tests/Editor/NUnit/AsyncSetupAttributeExample.cs @@ -1,46 +1,57 @@ -// Copyright (c) 2021-2023 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. +using System.Collections; using System.Threading.Tasks; using NUnit.Framework; -using UnityEngine; - -#pragma warning disable CS1998 +using UnityEngine.TestTools; namespace APIExamples.Editor.NUnit { /// - /// 非同期のの例(Edit Modeテスト) - /// はasyncサポートされていない(UTF v1.3時点) + /// 非同期のの使用例(Edit Modeテスト) + /// はasyncサポートされていない(UTF v1.6.0時点) + ///

/// Async SetUp attribute example (in Edit Mode tests) - /// Async OneTimeSetUp attribute is not yet supported in UTF v1.3 + /// Async OneTimeSetUp attribute is not yet supported in UTF v1.6.0 ///

/// /// Required: Unity Test Framework v1.3 or later /// + /// [TestFixture] public class AsyncSetupAttributeExample { + private int _setupCount; + /// /// 各テストメソッドの前に実行されます /// [SetUp] - public async Task SetUp() + public async Task SetUpAsync() { - await Task.Delay(200); - Debug.Log($"SetUp, {Time.time}"); + await Task.Yield(); + _setupCount++; } - [Test] + [Test, Order(0)] public void TestMethod() { - Debug.Log($"TestMethod, {Time.time}"); + Assert.That(_setupCount, Is.EqualTo(1), "最初のテストなのでSetUpは1回実行されている"); + } + + [Test, Order(1)] + public async Task TestMethodAsync() + { + await Task.Yield(); + Assert.That(_setupCount, Is.EqualTo(2), "2番目のテストなのでSetUpは2回実行されている"); } - [Test] - public void TestMethod2() + [UnityTest, Order(2)] + public IEnumerator UnityTestMethod() { - Debug.Log($"TestMethod2, {Time.time}"); + yield return null; + Assert.That(_setupCount, Is.EqualTo(3), "3番目のテストなのでSetUpは3回実行されている"); } } } diff --git a/Assets/APIExamples/Tests/Editor/NUnit/AsyncTearDownAttributeExample.cs b/Assets/APIExamples/Tests/Editor/NUnit/AsyncTearDownAttributeExample.cs index 2464845..017c3a8 100644 --- a/Assets/APIExamples/Tests/Editor/NUnit/AsyncTearDownAttributeExample.cs +++ b/Assets/APIExamples/Tests/Editor/NUnit/AsyncTearDownAttributeExample.cs @@ -1,23 +1,25 @@ -// Copyright (c) 2021-2023 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. +using System.Collections; using System.Threading.Tasks; using NUnit.Framework; using UnityEngine; - -#pragma warning disable CS1998 +using UnityEngine.TestTools; namespace APIExamples.Editor.NUnit { /// - /// 非同期のの例(Edit Modeテスト) - /// はasyncサポートされていない(UTF v1.3時点) + /// 非同期のの使用例(Edit Modeテスト) + /// はasyncサポートされていない(UTF v1.6.0時点) + ///

/// Async TearDown attribute example (in Edit Mode tests) - /// Async OneTimeTearDown attribute is not yet supported in UTF v1.3 + /// Async OneTimeTearDown attribute is not yet supported in UTF v1.6.0 ///

/// /// Required: Unity Test Framework v1.3 or later /// + /// [TestFixture] public class AsyncTearDownAttributeExample { @@ -25,22 +27,30 @@ public class AsyncTearDownAttributeExample /// 各テストメソッドの後に実行されます /// [TearDown] - public async Task TearDown() + public async Task TearDownAsync() { - await Task.Delay(200); - Debug.Log($"TearDown, {Time.time}"); + await Task.Yield(); + Debug.Log($"TearDownAsync"); } [Test] public void TestMethod() { - Debug.Log($"TestMethod, {Time.time}"); + Debug.Log($"TestMethod"); } [Test] - public void TestMethod2() + public async Task TestMethodAsync() + { + await Task.Yield(); + Debug.Log($"TestMethodAsync"); + } + + [UnityTest] + public IEnumerator UnityTestMethod() { - Debug.Log($"TestMethod2, {Time.time}"); + yield return null; + Debug.Log($"UnityTestMethod"); } } } diff --git a/Assets/APIExamples/Tests/Editor/NUnit/AsyncTestExample.cs b/Assets/APIExamples/Tests/Editor/NUnit/AsyncTestExample.cs index f41e73c..f24bae7 100644 --- a/Assets/APIExamples/Tests/Editor/NUnit/AsyncTestExample.cs +++ b/Assets/APIExamples/Tests/Editor/NUnit/AsyncTestExample.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021-2023 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. using System; @@ -8,9 +8,6 @@ using NUnit.Framework; using UnityEngine; -#pragma warning disable CS1998 -// ReSharper disable AccessToStaticMemberViaDerivedType - namespace APIExamples.Editor.NUnit { /// @@ -35,13 +32,13 @@ public class AsyncTestExample private static async Task Foo(int id) { - await Task.Delay(200); + await Task.Yield(); Debug.Log($"Foo({id})"); } private static async Task Bar(int id) { - await Task.Delay(200); + await Task.Yield(); Debug.Log($"Bar({id})"); return id + 1; } @@ -58,13 +55,13 @@ private static async Task Bar(int id) private static async UniTask UniTaskFoo(int id) { - await UniTask.Delay(200); + await Task.Yield(); Debug.Log($"UniTaskFoo({id})"); } private static async UniTask UniTaskBar(int id) { - await UniTask.Delay(200); + await Task.Yield(); Debug.Log($"UniTaskBar({id})"); return id + 1; } diff --git a/Assets/APIExamples/Tests/Editor/UnityTestFramework/EditModeTestYieldInstructionExample.cs b/Assets/APIExamples/Tests/Editor/UnityTestFramework/EditModeTestYieldInstructionExample.cs index bfbbd72..f0f57ac 100644 --- a/Assets/APIExamples/Tests/Editor/UnityTestFramework/EditModeTestYieldInstructionExample.cs +++ b/Assets/APIExamples/Tests/Editor/UnityTestFramework/EditModeTestYieldInstructionExample.cs @@ -1,8 +1,9 @@ -// Copyright (c) 2021-2022 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. using System; using System.Collections; +using System.Diagnostics.CodeAnalysis; using System.IO; using System.Reflection; using System.Threading.Tasks; @@ -16,39 +17,59 @@ namespace APIExamples.Editor.UnityTestFramework /// /// の使用例 /// + [SuppressMessage("Structure", "NUnit1028:The non-test method is public")] public class EditModeTestYieldInstructionExample { + private static bool s_wasInitializeOnEnterPlayModeCalled; + private static bool s_wasRuntimeInitializeOnLoadMethodCalled; + private static bool s_wasOneTimeSetUpCalled; + private static bool s_wasUnitySetUpCalled; + private static bool s_wasSetUpCalled; + private static bool s_wasSetUpAsyncCalled; + private const string CsPath = "Assets/CreateFileExample.cs"; private const string DLLSrcPath = "TestData/NativePluginExample.dll"; private const string DLLDstPath = "Assets/NativePluginExample.dll"; + [InitializeOnEnterPlayMode] + public static void InitializeOnEnterPlayMode() + { + s_wasInitializeOnEnterPlayModeCalled = true; + } + + [RuntimeInitializeOnLoadMethod] + public static void RuntimeInitializeOnLoadMethod() + { + s_wasRuntimeInitializeOnLoadMethodCalled = true; + } + [OneTimeSetUp] public void OneTimeSetUp() { Assume.That(EditorSettings.enterPlayModeOptionsEnabled, Is.False, "Enter Play Mode Options enabled"); // Note: Edit | Project Settings... | Editor | Enter Play Mode Settings が変更されていないことが前提 - Debug.Log("OneTimeSetUpはドメインリロードで再実行されます"); + s_wasOneTimeSetUpCalled = true; } [UnitySetUp] public IEnumerator UnitySetUp() { - Debug.Log("UnitySetUpはドメインリロードで再実行されません"); + s_wasUnitySetUpCalled = true; yield break; } [SetUp] public void SetUp() { - Debug.Log("SetUpはドメインリロードで再実行されます"); + s_wasSetUpCalled = true; } [SetUp] public async Task SetUpAsync() { - Debug.Log("SetUpAsyncはドメインリロードで再実行されます"); - await Task.Delay(1); + s_wasSetUpAsyncCalled = true; + await Task.Yield(); } [TearDown] @@ -60,15 +81,34 @@ public void TearDown() } [UnityTest] - public IEnumerator EnterPlayModeの使用例() + public IEnumerator EnterPlayModeで再生モードに切り替える例() { yield return new EnterPlayMode(); + Assert.That(EditorApplication.isPlaying, Is.True); // Note: 特に後処理をしなくてもテスト終了後に編集モードに戻ります } [UnityTest] - public IEnumerator ExitPlayModeの使用例() + public IEnumerator EnterPlayModeで再生モードに切り替える例_InitializeOnEnterPlayModeが実行される() + { + yield return new EnterPlayMode(); + // Note: staticフィールドの値はドメインリロードで初期化されます + + Assert.That(s_wasInitializeOnEnterPlayModeCalled, Is.True); + } + + [UnityTest] + public IEnumerator EnterPlayModeで再生モードに切り替える例_RuntimeInitializeOnLoadMethodが実行される() + { + yield return new EnterPlayMode(); + // Note: staticフィールドの値はドメインリロードで初期化されます + + Assert.That(s_wasRuntimeInitializeOnLoadMethodCalled, Is.True); + } + + [UnityTest] + public IEnumerator ExitPlayModeで編集モードに切り替える例() { yield return new EnterPlayMode(); Assume.That(EditorApplication.isPlaying, Is.True); @@ -78,7 +118,7 @@ public void TearDown() } [UnityTest] - public IEnumerator RecompileScriptsでリコンパイルされたクラスのメソッドを呼び出す例() + public IEnumerator RecompileScriptsでリコンパイルを実行する例_リコンパイルされたクラスのメソッドを呼び出せる() { Assume.That(Path.GetFullPath(CsPath), Does.Not.Exist, "Destination file already exists. please remove and re-run this test."); @@ -102,7 +142,7 @@ public void TearDown() } [UnityTest] - public IEnumerator WaitForDomainReloadで追加されたアセンブリのメソッドを呼び出す例() + public IEnumerator WaitForDomainReloadでドメインリロードを待機する例_追加されたアセンブリのメソッドを呼び出せる() { Assume.That(Path.GetFullPath(DLLDstPath), Does.Not.Exist, "Destination file already exists. please remove and re-run this test."); @@ -120,5 +160,41 @@ public void TearDown() Assert.That(actual, Is.True); } + + [UnityTest] + public IEnumerator ドメインリロード発生時にOneTimeSetUpは再実行される() + { + yield return new EnterPlayMode(); + // Note: staticフィールドの値はドメインリロードで初期化されます + + Assert.That(s_wasOneTimeSetUpCalled, Is.True); + } + + [UnityTest] + public IEnumerator ドメインリロード発生時にUnitySetUpは再実行さない() + { + yield return new EnterPlayMode(); + // Note: staticフィールドの値はドメインリロードで初期化されます + + Assert.That(s_wasUnitySetUpCalled, Is.False); + } + + [UnityTest] + public IEnumerator ドメインリロード発生時にSetUpは再実行される() + { + yield return new EnterPlayMode(); + // Note: staticフィールドの値はドメインリロードで初期化されます + + Assert.That(s_wasSetUpCalled, Is.True); + } + + [UnityTest] + public IEnumerator ドメインリロード発生時にSetUpAsyncは再実行される() + { + yield return new EnterPlayMode(); + // Note: staticフィールドの値はドメインリロードで初期化されます + + Assert.That(s_wasSetUpAsyncCalled, Is.True); + } } } diff --git a/Assets/APIExamples/Tests/Editor/UnityTestFramework/RequirePlatformSupportAttributeExample.cs b/Assets/APIExamples/Tests/Editor/UnityTestFramework/RequirePlatformSupportAttributeExample.cs new file mode 100644 index 0000000..e5fd270 --- /dev/null +++ b/Assets/APIExamples/Tests/Editor/UnityTestFramework/RequirePlatformSupportAttributeExample.cs @@ -0,0 +1,49 @@ +// Copyright (c) 2021-2025 Koji Hasegawa. +// This software is released under the MIT License. + +using APIExamples.UnityTestFramework; +using NUnit.Framework; +using UnityEditor; +using UnityEditor.TestTools; + +namespace APIExamples.Editor.UnityTestFramework +{ + /// + /// Unityエディターに指定したプラットフォームモジュール(Build Support)がインストールされているときのみ実行されるテストの例. + /// + /// + [TestFixture] + public class RequirePlatformSupportAttributeExample + { + [Test] + [RequirePlatformSupport(BuildTarget.StandaloneOSX)] + public void macOSモジュールがインストールされているときのみ実行されるテスト() + { + } + + [Test] + [RequirePlatformSupport(BuildTarget.StandaloneWindows)] + public void Windowsモジュールがインストールされているときのみ実行されるテスト() + { + } + + [Test] + [RequirePlatformSupport(BuildTarget.StandaloneLinux64)] + public void Linuxモジュールがインストールされているときのみ実行されるテスト() + { + } + + [Test] + [RequirePlatformSupport(BuildTarget.StandaloneOSX, BuildTarget.StandaloneWindows, + BuildTarget.StandaloneLinux64)] // Note: And条件 + public void スタンドアロンモジュールが3種ともインストールされているときのみ実行されるテスト() + { + } + + [Test] + [RequirePlatformSupport(BuildTarget.WSAPlayer)] + public void WSAPlayerモジュールがインストールされているときのみ実行されるテスト() + { + } + } +} diff --git a/Assets/APIExamples/Tests/Editor/UnityTestFramework/RequirePlatformSupportAttributeExample.cs.meta b/Assets/APIExamples/Tests/Editor/UnityTestFramework/RequirePlatformSupportAttributeExample.cs.meta new file mode 100644 index 0000000..86d5be1 --- /dev/null +++ b/Assets/APIExamples/Tests/Editor/UnityTestFramework/RequirePlatformSupportAttributeExample.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f3ae0023457843a88e2a72759df2180c +timeCreated: 1764019546 \ No newline at end of file diff --git a/Assets/APIExamples/Tests/Editor/UnityTestFramework/UnitySetUpAttributeExample.cs b/Assets/APIExamples/Tests/Editor/UnityTestFramework/UnitySetUpAttributeExample.cs new file mode 100644 index 0000000..4d94027 --- /dev/null +++ b/Assets/APIExamples/Tests/Editor/UnityTestFramework/UnitySetUpAttributeExample.cs @@ -0,0 +1,51 @@ +// Copyright (c) 2021-2025 Koji Hasegawa. +// This software is released under the MIT License. + +using System.Collections; +using System.Threading.Tasks; +using NUnit.Framework; +using UnityEngine.TestTools; + +namespace APIExamples.Editor.UnityTestFramework +{ + /// + /// の使用例 + /// + /// + [TestFixture] + public class UnitySetUpAttributeExample + { + private int _setupCount; + + /// + /// SetUpをコルーチン書式で記述できます + /// 専用ではなく、通常のTest向けのSetUpとしても使用できます + /// + [UnitySetUp] + public IEnumerator SetUpCoroutine() + { + yield return null; + _setupCount++; + } + + [Test, Order(0)] + public void TestMethod() + { + Assert.That(_setupCount, Is.EqualTo(1), "最初のテストなのでSetUpは1回実行されている"); + } + + [Test, Order(1)] + public async Task TestMethodAsync() + { + await Task.Yield(); + Assert.That(_setupCount, Is.EqualTo(2), "2番目のテストなのでSetUpは2回実行されている"); + } + + [UnityTest, Order(2)] + public IEnumerator UnityTestMethod() + { + yield return null; + Assert.That(_setupCount, Is.EqualTo(3), "3番目のテストなのでSetUpは3回実行されている"); + } + } +} diff --git a/Assets/APIExamples/Tests/Editor/UnityTestFramework/UnitySetUpAttributeExample.cs.meta b/Assets/APIExamples/Tests/Editor/UnityTestFramework/UnitySetUpAttributeExample.cs.meta new file mode 100644 index 0000000..af6b98f --- /dev/null +++ b/Assets/APIExamples/Tests/Editor/UnityTestFramework/UnitySetUpAttributeExample.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: b07d09a814004048af278e139b81f903 +timeCreated: 1762465453 \ No newline at end of file diff --git a/Assets/APIExamples/Tests/Editor/UnityTestFramework/UnityTearDownAttributeExample.cs b/Assets/APIExamples/Tests/Editor/UnityTestFramework/UnityTearDownAttributeExample.cs new file mode 100644 index 0000000..4657374 --- /dev/null +++ b/Assets/APIExamples/Tests/Editor/UnityTestFramework/UnityTearDownAttributeExample.cs @@ -0,0 +1,50 @@ +// Copyright (c) 2021-2025 Koji Hasegawa. +// This software is released under the MIT License. + +using System.Collections; +using System.Threading.Tasks; +using NUnit.Framework; +using UnityEngine; +using UnityEngine.TestTools; + +namespace APIExamples.Editor.UnityTestFramework +{ + /// + /// の使用例 + /// + /// + [TestFixture] + public class UnityTearDownAttributeExample + { + /// + /// TearDownをコルーチン書式で記述できます + /// 専用ではなく、通常のTest向けのTearDownとしても使用できます + /// + [UnityTearDown] + public IEnumerator TearDownCoroutine() + { + yield return null; + Debug.Log($"TearDown"); + } + + [Test] + public void TestMethod() + { + Debug.Log($"TestMethod"); + } + + [Test] + public async Task TestMethodAsync() + { + await Task.Yield(); + Debug.Log($"TestMethodAsync"); + } + + [UnityTest] + public IEnumerator UnityTestMethod() + { + yield return null; + Debug.Log($"UnityTestMethod"); + } + } +} diff --git a/Assets/APIExamples/Tests/Editor/UnityTestFramework/UnityTearDownAttributeExample.cs.meta b/Assets/APIExamples/Tests/Editor/UnityTestFramework/UnityTearDownAttributeExample.cs.meta new file mode 100644 index 0000000..558afc8 --- /dev/null +++ b/Assets/APIExamples/Tests/Editor/UnityTestFramework/UnityTearDownAttributeExample.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 3e67f7d46673461fad71d72b4fd1bbf0 +timeCreated: 1762465453 \ No newline at end of file diff --git a/Assets/APIExamples/Tests/Editor/UnityTestFramework/UnityTestAttributeExample.cs b/Assets/APIExamples/Tests/Editor/UnityTestFramework/UnityTestAttributeExample.cs index 0364c89..0c75cb4 100644 --- a/Assets/APIExamples/Tests/Editor/UnityTestFramework/UnityTestAttributeExample.cs +++ b/Assets/APIExamples/Tests/Editor/UnityTestFramework/UnityTestAttributeExample.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021-2023 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. using System; @@ -12,10 +12,9 @@ namespace APIExamples.Editor.UnityTestFramework { /// /// フレームをまたがるテストをで実装する例 - /// UniTaskの使用例を含みます /// /// - /// Runtime/UnityTestFramework/UnityTestAttributeExampleをベースに、Edit Modeで動くもの + /// をベースに、Edit Modeテスト向けに修正したもの /// [TestFixture] public class UnityTestAttributeExample @@ -25,6 +24,7 @@ public class UnityTestAttributeExample { var before = Time.frameCount; yield return null; + var actual = Time.frameCount; Assert.That(actual, Is.EqualTo(before)); // Note: Edit Modeテストではそもそもフレームカウントされない @@ -37,23 +37,26 @@ public class UnityTestAttributeExample } [UnityTest] - [Explicit("Edit ModeテストではWaitForEndOfFrameがエラーとなるため実行対象から除外")] - public IEnumerator YieldInstructionの実装クラスはEditMoteテストでは使用できない_実行時エラー() + [Explicit("Edit Modeテストでは動作しない")] + public IEnumerator YieldInstructionの実装クラス_EditMoteテストでは動作しない() { - var before = Time.frameCount; - yield return new WaitForEndOfFrame(); - var actual = Time.frameCount; + var start = Time.time; // The time at the beginning of this frame + const float WaitSeconds = 0.5f; + yield return new WaitForSeconds(WaitSeconds); + + var actual = Time.time - start; - Assert.That(actual, Is.EqualTo(before)); + Assert.That(actual, Is.EqualTo(WaitSeconds).Within(0.1f)); } [UnityTest] - [Explicit("Edit ModeテストではWaitForSecondsRealtimeが動作しないため実行対象から除外")] - public IEnumerator CustomYieldInstructionの実装クラスはEditMoteテストでは使用できない_動作しない() + [Explicit("Edit Modeテストでは動作しない")] + public IEnumerator CustomYieldInstructionの実装クラス_EditMoteテストでは動作しない() { var start = Time.time; // The time at the beginning of this frame const float WaitSeconds = 0.5f; yield return new WaitForSecondsRealtime(WaitSeconds); + var actual = Time.time - start; Assert.That(actual, Is.EqualTo(WaitSeconds).Within(0.1f)); @@ -83,6 +86,7 @@ public class UnityTestAttributeExample public IEnumerator コルーチンを起動してコールバックを受け取る例() { var actual = 0; + yield return BarCoroutine(i => { actual = i; @@ -91,11 +95,12 @@ public class UnityTestAttributeExample Assert.That(actual, Is.EqualTo(1)); } - [Ignore("Edit Modeテストではテストが終了しないため実行対象から除外/ Freeze in the Edit Mode tests")] [UnityTest] + [Ignore("Edit Modeテストではテストが終了しないため実行対象から除外/ Freeze in the Edit Mode tests")] public IEnumerator UniTaskでコルーチンを起動してコールバックを受け取る例_EditModeテストではテストが終了しない() => UniTask.ToCoroutine(async () => { var actual = 0; + await BarCoroutine(i => { actual = i; diff --git a/Assets/APIExamples/Tests/Editor/UnityTestFramework/UnityTestFrameworkVersionCheck.cs b/Assets/APIExamples/Tests/Editor/UnityTestFramework/UnityTestFrameworkVersionCheck.cs new file mode 100644 index 0000000..5a4c958 --- /dev/null +++ b/Assets/APIExamples/Tests/Editor/UnityTestFramework/UnityTestFrameworkVersionCheck.cs @@ -0,0 +1,71 @@ +// Copyright (c) 2021-2025 Koji Hasegawa. +// This software is released under the MIT License. + +using System.Linq; +using System.Threading.Tasks; +using Cysharp.Threading.Tasks; +using NUnit.Framework; +using TestHelper.Attributes; +using UnityEditor.PackageManager; + +namespace APIExamples.Editor.UnityTestFramework +{ + [TestFixture] + public class UnityTestFrameworkVersionCheck + { + private static async UniTask GetTestFrameworkPackageVersionAsync() + { + var request = Client.List(false, false); + while (!request.IsCompleted) + { + await UniTask.Yield(); + } + + Assume.That(request.Status, Is.EqualTo(StatusCode.Success)); + + return request.Result.Where(x => x.name == "com.unity.test-framework") + .Select(x => x.version) + .FirstOrDefault(); + } + + [Test] + [UnityVersion(olderThan: "6000.0.44f1")] + public async Task Unity6000_0_43f1まで_TestFrameworkバージョンは任意() + { + var actual = await GetTestFrameworkPackageVersionAsync(); + Assert.That(actual, Is.EqualTo("1.4.6")); + } + + [Test] + [UnityVersion(newerThanOrEqual: "6000.0.44f1", olderThan: "6000.0.59f2")] + public async Task Unity6000_0_44f1から58f2まで_TestFrameworkはv1_5_1固定() + { + var actual = await GetTestFrameworkPackageVersionAsync(); + Assert.That(actual, Is.EqualTo("1.5.1")); + } + + [Test] + [UnityVersion(newerThanOrEqual: "6000.0.59f2", olderThan: "6000.1.0f1")] + public async Task Unity6000_0_59f2以降_TestFrameworkはv1_6_0固定() + { + var actual = await GetTestFrameworkPackageVersionAsync(); + Assert.That(actual, Is.EqualTo("1.6.0")); + } + + [Test] + [UnityVersion(newerThanOrEqual: "6000.1.0f1", olderThan: "6000.2.6f1")] + public async Task Unity6000_1_0f1から6000_2_5f1まで_TestFrameworkはv1_5_1固定() + { + var actual = await GetTestFrameworkPackageVersionAsync(); + Assert.That(actual, Is.EqualTo("1.5.1")); + } + + [Test] + [UnityVersion(newerThanOrEqual: "6000.2.6f1")] + public async Task Unity6000_2_6f1以降_TestFrameworkはv1_6_0固定() + { + var actual = await GetTestFrameworkPackageVersionAsync(); + Assert.That(actual, Is.EqualTo("1.6.0")); + } + } +} diff --git a/Assets/APIExamples/Tests/Editor/UnityTestFramework/UnityTestFrameworkVersionCheck.cs.meta b/Assets/APIExamples/Tests/Editor/UnityTestFramework/UnityTestFrameworkVersionCheck.cs.meta new file mode 100644 index 0000000..b199776 --- /dev/null +++ b/Assets/APIExamples/Tests/Editor/UnityTestFramework/UnityTestFrameworkVersionCheck.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: 91e2dca48c4042ac8e1d516baf3e96c5 +timeCreated: 1759567497 \ No newline at end of file diff --git a/Assets/APIExamples/Tests/Runtime/APIExamples.Tests.asmdef b/Assets/APIExamples/Tests/Runtime/APIExamples.Tests.asmdef index 176c69b..eefcc21 100644 --- a/Assets/APIExamples/Tests/Runtime/APIExamples.Tests.asmdef +++ b/Assets/APIExamples/Tests/Runtime/APIExamples.Tests.asmdef @@ -5,7 +5,8 @@ "UnityEngine.TestRunner", "UnityEditor.TestRunner", "APIExamples", - "UniTask" + "UniTask", + "TestHelper" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/Assets/APIExamples/Tests/Runtime/AssemblyInfo.cs b/Assets/APIExamples/Tests/Runtime/AssemblyInfo.cs index 13b338d..c863ac1 100644 --- a/Assets/APIExamples/Tests/Runtime/AssemblyInfo.cs +++ b/Assets/APIExamples/Tests/Runtime/AssemblyInfo.cs @@ -1,6 +1,6 @@ -// Copyright (c) 2021-2022 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. -using NUnit.Framework; +using System.Runtime.CompilerServices; -[assembly: Category("APIExamples")] +[assembly: InternalsVisibleTo("APIExample.Editor.Tests")] diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/AsyncSetupAttributeExample.cs b/Assets/APIExamples/Tests/Runtime/NUnit/AsyncSetupAttributeExample.cs index 8404772..78552e6 100644 --- a/Assets/APIExamples/Tests/Runtime/NUnit/AsyncSetupAttributeExample.cs +++ b/Assets/APIExamples/Tests/Runtime/NUnit/AsyncSetupAttributeExample.cs @@ -1,49 +1,61 @@ -// Copyright (c) 2021-2023 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. +using System.Collections; +using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using NUnit.Framework; -using UnityEngine; using UnityEngine.TestTools; -#pragma warning disable CS1998 - namespace APIExamples.NUnit { /// - /// 非同期のの例 - /// はasyncサポートされていない(UTF v1.3時点) + /// 非同期のの使用例 + /// はasyncサポートされていない(UTF v1.6.0時点) + ///

/// Async SetUp attribute example - /// Async OneTimeSetUp attribute is not yet supported in UTF v1.3 + /// Async OneTimeSetUp attribute is not yet supported in UTF v1.6.0 ///

/// /// Required: Unity Test Framework v1.3 or later /// + /// + /// + /// [TestFixture] - [UnityPlatform(exclude = new[] { RuntimePlatform.WebGLPlayer })] - // WebGLではTask.Delayが終了しない(v1.3.9時点) https://unity3d.atlassian.net/servicedesk/customer/portal/2/IN-28109 + [SuppressMessage("ReSharper", "AccessToStaticMemberViaDerivedType")] public class AsyncSetupAttributeExample { + private int _setupCount; + /// /// 各テストメソッドの前に実行されます /// [SetUp] - public async Task SetUp() + public async Task SetUpAsync() { - await Task.Delay(200); - Debug.Log($"SetUp, {Time.time}"); + await Task.Yield(); + _setupCount++; } - [Test] + [Test, Order(0)] public void TestMethod() { - Debug.Log($"TestMethod, {Time.time}"); + Assert.That(_setupCount, Is.EqualTo(1), "最初のテストなのでSetUpは1回実行されている"); + } + + [Test, Order(1)] + public async Task TestMethodAsync() + { + await Task.Yield(); + Assert.That(_setupCount, Is.EqualTo(2), "2番目のテストなのでSetUpは2回実行されている"); } - [Test] - public void TestMethod2() + [UnityTest, Order(2)] + public IEnumerator UnityTestMethod() { - Debug.Log($"TestMethod2, {Time.time}"); + yield return null; + Assert.That(_setupCount, Is.EqualTo(3), "3番目のテストなのでSetUpは3回実行されている"); } } } diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/AsyncTearDownAttributeExample.cs b/Assets/APIExamples/Tests/Runtime/NUnit/AsyncTearDownAttributeExample.cs index c119781..4b0719a 100644 --- a/Assets/APIExamples/Tests/Runtime/NUnit/AsyncTearDownAttributeExample.cs +++ b/Assets/APIExamples/Tests/Runtime/NUnit/AsyncTearDownAttributeExample.cs @@ -1,49 +1,58 @@ -// Copyright (c) 2021-2023 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. +using System.Collections; using System.Threading.Tasks; using NUnit.Framework; using UnityEngine; using UnityEngine.TestTools; -#pragma warning disable CS1998 - namespace APIExamples.NUnit { /// - /// 非同期のの例 - /// はasyncサポートされていない(UTF v1.3時点) + /// 非同期のの使用例 + /// はasyncサポートされていない(UTF v1.6.0時点) + ///

/// Async TearDown attribute example - /// Async OneTimeTearDown attribute is not yet supported in UTF v1.3 + /// Async OneTimeTearDown attribute is not yet supported in UTF v1.6.0 ///

/// /// Required: Unity Test Framework v1.3 or later /// + /// + /// + /// [TestFixture] - [UnityPlatform(exclude = new[] { RuntimePlatform.WebGLPlayer })] - // WebGLではTask.Delayが終了しない(v1.3.9時点) https://unity3d.atlassian.net/servicedesk/customer/portal/2/IN-28109 public class AsyncTearDownAttributeExample { /// /// 各テストメソッドの後に実行されます /// [TearDown] - public async Task TearDown() + public async Task TearDownAsync() { - await Task.Delay(200); - Debug.Log($"TearDown, {Time.time}"); + await Task.Yield(); + Debug.Log($"TearDownAsync"); } [Test] public void TestMethod() { - Debug.Log($"TestMethod, {Time.time}"); + Debug.Log($"TestMethod"); } [Test] - public void TestMethod2() + public async Task TestMethodAsync() + { + await Task.Yield(); + Debug.Log($"TestMethodAsync"); + } + + [UnityTest] + public IEnumerator UnityTestMethod() { - Debug.Log($"TestMethod2, {Time.time}"); + yield return null; + Debug.Log($"UnityTestMethod"); } } } diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/AsyncTestExample.cs b/Assets/APIExamples/Tests/Runtime/NUnit/AsyncTestExample.cs index b0491e2..c10197a 100644 --- a/Assets/APIExamples/Tests/Runtime/NUnit/AsyncTestExample.cs +++ b/Assets/APIExamples/Tests/Runtime/NUnit/AsyncTestExample.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021-2023 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. using System; @@ -7,10 +7,6 @@ using Cysharp.Threading.Tasks; using NUnit.Framework; using UnityEngine; -using UnityEngine.TestTools; - -#pragma warning disable CS1998 -// ReSharper disable AccessToStaticMemberViaDerivedType namespace APIExamples.NUnit { @@ -26,8 +22,6 @@ public class AsyncTestExample { [Test] [Description("Can await Task")] - [UnityPlatform(exclude = new[] { RuntimePlatform.WebGLPlayer })] - // WebGLではTask.Delayが終了しない(v1.3.9時点) https://unity3d.atlassian.net/servicedesk/customer/portal/2/IN-28109 public async Task 非同期テストの例_Taskをawaitできる() { await Foo(1); @@ -38,13 +32,13 @@ public class AsyncTestExample private static async Task Foo(int id) { - await Task.Delay(200); + await Task.Yield(); Debug.Log($"Foo({id})"); } private static async Task Bar(int id) { - await Task.Delay(200); + await Task.Yield(); Debug.Log($"Bar({id})"); return id + 1; } @@ -61,13 +55,13 @@ private static async Task Bar(int id) private static async UniTask UniTaskFoo(int id) { - await UniTask.Delay(200); + await Task.Yield(); Debug.Log($"UniTaskFoo({id})"); } private static async UniTask UniTaskBar(int id) { - await UniTask.Delay(200); + await Task.Yield(); Debug.Log($"UniTaskBar({id})"); return id + 1; } diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/CategoryAttributeExample.cs b/Assets/APIExamples/Tests/Runtime/NUnit/CategoryAttributeExample.cs index 9b04120..b75504a 100644 --- a/Assets/APIExamples/Tests/Runtime/NUnit/CategoryAttributeExample.cs +++ b/Assets/APIExamples/Tests/Runtime/NUnit/CategoryAttributeExample.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021-2022 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. using NUnit.Framework; @@ -8,20 +8,23 @@ namespace APIExamples.NUnit /// /// の記述例 /// + /// + /// アセンブリへの配置例は、UGUIExample など統合テスト編サンプルの AssemblyInfo.cs を参照してください。 + /// [TestFixture] - [Category("CategoryExample")] + [Category("CategoryFoo")] public class CategoryAttributeExample { [Test] - [Category("LearningTests")] - public void CategorizedMethodExample() + [Category("CategoryBar")] + public void CategorizedMethod() { } [Test] - [Category("LearningTests")] - [Category("IgnoreCI")] - public void MultiCategorizedMethodExample() + [Category("CategoryBaz")] + [Category("CategoryQux")] + public void MultiCategorizedMethodMethod() { } } diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/ConstraintExample.cs b/Assets/APIExamples/Tests/Runtime/NUnit/ConstraintExample.cs index f7023ec..1516df4 100644 --- a/Assets/APIExamples/Tests/Runtime/NUnit/ConstraintExample.cs +++ b/Assets/APIExamples/Tests/Runtime/NUnit/ConstraintExample.cs @@ -2,7 +2,6 @@ // This software is released under the MIT License. using System; -using System.Collections; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; @@ -130,11 +129,11 @@ public class 等価 } [Test] - public void EqualConstraint_配列が等しいこと() + public void EqualConstraint_コレクションが等しいこと() { - var actual = new[] { "Katsuro", "Jenny", "Lindsay" }; + var actual = new List { "Katsuro", "Jenny", "Lindsay" }; - Assert.That(actual, Is.EqualTo(new[] { "Katsuro", "Jenny", "Lindsay" })); + Assert.That(actual, Is.EqualTo(new[] { "Katsuro", "Jenny", "Lindsay" })); // Listを配列で検証可能 // 失敗時メッセージ例: // Expected and actual are both // Values differ at index [1] @@ -310,7 +309,7 @@ public class コレクション } [Test] - public void HasLength_配列の個数を検証() + public void HasLength_コレクションの要素数を検証() { var actual = new[] { 2, 3, 5, 6 }; Assert.That(actual, Has.Length.EqualTo(4)); @@ -366,7 +365,7 @@ public class コレクション } [TestFixture] - public class 比較 + public class 数値 { [Test] public void GreaterThanConstraint_より大きい() @@ -425,7 +424,7 @@ public class 比較 } [TestFixture] - public class 合成 + public class オペレーター { [Test] public void AndConstraint_AND条件() @@ -470,7 +469,7 @@ public class 合成 } [TestFixture] - public class 条件 + public class 状態 { [Test] public void EmptyConstraint_空であること() @@ -578,7 +577,8 @@ public class ファイルとディレクトリ [Test] public void SamePathConstraint_パス文字列が等しいこと() { - Assert.That("\\folder1\\.\\junk\\..\\folder2", Is.SamePath("/folder1/folder2")); + var actual = "\\folder1\\.\\junk\\..\\folder2"; + Assert.That(actual, Is.SamePath("/folder1/folder2")); // 失敗時メッセージ例: // Expected: Path matching "/folder1/folder2" // But was: "\folder1\.\junk\..\folder2\xxx" @@ -587,7 +587,8 @@ public class ファイルとディレクトリ [Test] public void SamePathConstraint_パス文字列が等しいこと_IgnoreCase修飾子も有効() { - Assert.That("\\folder1\\.\\junk\\..\\Folder2", Is.SamePath("/Folder1/folder2").IgnoreCase); + var actual = "\\folder1\\.\\junk\\..\\Folder2"; + Assert.That(actual, Is.SamePath("/Folder1/folder2").IgnoreCase); // 失敗時メッセージ例: // Expected: Path matching "/Folder1/folder2" // But was: "\folder1\.\junk\..\Folder2" @@ -596,8 +597,11 @@ public class ファイルとディレクトリ [Test] public void SamePathOrUnderConstraint_パス文字列が期待値と同じかその配下であること() { - Assert.That("\\folder1\\.\\junk\\..\\folder2", Is.SamePathOrUnder("/folder1/folder2")); - Assert.That("\\folder1\\.\\junk\\..\\folder2\\folder3", Is.SamePathOrUnder("/folder1/folder2")); + var expected = "/folder1/folder2"; + var actual1 = "\\folder1\\.\\junk\\..\\folder2"; + var actual2 = "\\folder1\\.\\junk\\..\\folder2\\folder3"; + Assert.That(actual1, Is.SamePathOrUnder(expected)); + Assert.That(actual2, Is.SamePathOrUnder(expected)); // 失敗時メッセージ例: // Expected: Path under or matching "/folder1/folder2" // But was: "\folder1\.\junk\..\folder3\folder2" @@ -606,8 +610,8 @@ public class ファイルとディレクトリ [Test] public void SamePathOrUnderConstraint_パス文字列が期待値と同じかその配下であること_IgnoreCase修飾子も有効() { - Assert.That("\\folder1\\.\\junk\\..\\Folder2\\folder3", - Is.SamePathOrUnder("/Folder1/folder2").IgnoreCase); + var actual = "\\folder1\\.\\junk\\..\\Folder2\\folder3"; + Assert.That(actual, Is.SamePathOrUnder("/Folder1/folder2").IgnoreCase); // 失敗時メッセージ例: // Expected: Path under or matching "/Folder1/folder2" // But was: "\folder1\.\junk\..\Folder2\folder3" @@ -616,7 +620,8 @@ public class ファイルとディレクトリ [Test] public void SubPathConstraint_パス文字列が期待値のサブパスであること() { - Assert.That("/folder1/folder2/folder3", Is.SubPathOf("/folder1/folder2")); + var actual = "/folder1/folder2/folder3"; + Assert.That(actual, Is.SubPathOf("/folder1/folder2")); // Note: 最新のNUnitでは`Is.SubPath()`で、実装も異なっている。NUnitのドキュメントにある例がNUnit 3.5では通らない } } @@ -801,7 +806,7 @@ void GetNotThrow() { } // But was: Time.time, Is.GreaterThan(start + 2.0f).After(2500)); // ミリ秒しか指定できない模様 - // 失敗時メッセージ例: - // Expected: greater than 2.33228302f after 2500 millisecond delay - // But was: 0.33228299f - } - - [Test] - [Explicit("Asyncテストでも期待通り動作しないので除外(Unity Test Framework v1.4.0時点)")] - // https://unity3d.atlassian.net/servicedesk/customer/portal/2/IN-30529 - public async Task DelayedConstraint_AsyncTestでも無効() + public void DelayedConstraint_指定時間経過後に評価される() { - var start = Time.time; // The time at the beginning of this frame - await Task.Delay(0); + var start = Time.realtimeSinceStartup; // Note: 非同期ではなく同一フレームで遅延処理されるため Time.time は変化しません - Assert.That(() => Time.time, Is.GreaterThan(start + 2.0f).After(2500)); // ミリ秒しか指定できない模様 + Assert.That(() => Time.realtimeSinceStartup, Is.GreaterThan(start + 0.2f).After(500)); // 失敗時メッセージ例: // Expected: greater than 2.33228302f after 2500 millisecond delay // But was: 0.33228299f } - - [UnityTest] - [Explicit("UnityTest属性のテストでも期待通り動作しないので除外")] - public IEnumerator DelayedConstraint_UnityTest属性のテストでも無効() - { - var start = Time.time; // The time at the beginning of this frame - yield return null; - - Assert.That(() => Time.time, Is.GreaterThan(start + 2.0f).After(2500)); // ミリ秒しか指定できない模様 - // 失敗時メッセージ例: - // Expected: greater than 2.39063787f after 2500 millisecond delay - // But was: 0.390637904f - } } } } diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/MaxTimeAttributeExample.cs b/Assets/APIExamples/Tests/Runtime/NUnit/MaxTimeAttributeExample.cs index fc802c1..1558af4 100644 --- a/Assets/APIExamples/Tests/Runtime/NUnit/MaxTimeAttributeExample.cs +++ b/Assets/APIExamples/Tests/Runtime/NUnit/MaxTimeAttributeExample.cs @@ -1,12 +1,12 @@ // Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. +using System; using System.Collections; using System.Threading.Tasks; using NUnit.Framework; using UnityEngine; using UnityEngine.TestTools; -using Debug = UnityEngine.Debug; namespace APIExamples.NUnit { @@ -25,30 +25,24 @@ public class MaxTimeAttributeExample [MaxTime(100)] public void MaxTime属性_指定ミリ秒よりも時間のかかるテストは実行後に失敗() { - var loopCount = 50000000; - var sum = 0f; - for (var i = 0; i < loopCount; i++) + var endTime = DateTime.Now.AddMilliseconds(200); + while (DateTime.Now < endTime) { - sum += Random.value; } - - Debug.Log("テストは最後まで実行されます"); } [UnityTest] [MaxTime(100)] public IEnumerator MaxTime属性_指定ミリ秒よりも時間のかかるテストは実行後に失敗_UnityTest属性() { - yield return new WaitForSeconds(0.5f); - Debug.Log("テストは最後まで実行されます"); + yield return new WaitForSeconds(0.2f); } [Test] [MaxTime(100)] public async Task MaxTime属性_指定ミリ秒よりも時間のかかるテストは実行後に失敗_非同期テスト() { - await Task.Delay(500); - Debug.Log("テストは最後まで実行されます"); + await Task.Delay(200); } } } diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/OneTimeSetupAttributeExample.cs b/Assets/APIExamples/Tests/Runtime/NUnit/OneTimeSetupAttributeExample.cs new file mode 100644 index 0000000..22422ef --- /dev/null +++ b/Assets/APIExamples/Tests/Runtime/NUnit/OneTimeSetupAttributeExample.cs @@ -0,0 +1,66 @@ +// Copyright (c) 2021-2025 Koji Hasegawa. +// This software is released under the MIT License. + +using System.Collections; +using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; +using NUnit.Framework; +using UnityEngine.TestTools; + +namespace APIExamples.NUnit +{ + /// + /// の使用例 + /// + /// + /// + /// + [TestFixture] + [SuppressMessage("ReSharper", "AccessToStaticMemberViaDerivedType")] + public class OneTimeSetupAttributeExample + { + private int _oneTimeSetupCount; + private int _setupCount; + + /// + /// テストクラス内の最初のテストの実行前に一度だけ実行されます + /// + [OneTimeSetUp] + public void OneTimeSetUp() + { + _oneTimeSetupCount++; + } + + /// + /// 各テストメソッドの前に実行されます + /// + [SetUp] + public void SetUp() + { + _setupCount++; + } + + [Test, Order(0)] + public void TestMethod() + { + Assert.That(_oneTimeSetupCount, Is.EqualTo(1), "OneTimeSetUpはTestFixtureごとに一度だけ実行される"); + Assert.That(_setupCount, Is.EqualTo(1), "最初のテストなのでSetUpは1回実行されている"); + } + + [Test, Order(1)] + public async Task TestMethodAsync() + { + await Task.Yield(); + Assert.That(_oneTimeSetupCount, Is.EqualTo(1), "OneTimeSetUpはTestFixtureごとに一度だけ実行される"); + Assert.That(_setupCount, Is.EqualTo(2), "2番目のテストなのでSetUpは2回実行されている"); + } + + [UnityTest, Order(2)] + public IEnumerator UnityTestMethod() + { + yield return null; + Assert.That(_oneTimeSetupCount, Is.EqualTo(1), "OneTimeSetUpはTestFixtureごとに一度だけ実行される"); + Assert.That(_setupCount, Is.EqualTo(3), "3番目のテストなのでSetUpは3回実行されている"); + } + } +} diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/OneTimeSetupAttributeExample.cs.meta b/Assets/APIExamples/Tests/Runtime/NUnit/OneTimeSetupAttributeExample.cs.meta new file mode 100644 index 0000000..515f1e2 --- /dev/null +++ b/Assets/APIExamples/Tests/Runtime/NUnit/OneTimeSetupAttributeExample.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: f5debcab7d6f405f9755f7e1955426e8 +timeCreated: 1627036574 \ No newline at end of file diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/OneTimeTearDownAttributeExample.cs b/Assets/APIExamples/Tests/Runtime/NUnit/OneTimeTearDownAttributeExample.cs new file mode 100644 index 0000000..5a12325 --- /dev/null +++ b/Assets/APIExamples/Tests/Runtime/NUnit/OneTimeTearDownAttributeExample.cs @@ -0,0 +1,69 @@ +// Copyright (c) 2021-2025 Koji Hasegawa. +// This software is released under the MIT License. + +using System.Collections; +using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; +using NUnit.Framework; +using UnityEngine; +using UnityEngine.TestTools; + +namespace APIExamples.NUnit +{ + /// + /// の使用例 + /// + /// + /// + /// + [TestFixture] + [SuppressMessage("ReSharper", "AccessToStaticMemberViaDerivedType")] + public class OneTimeTearDownAttributeExample + { + private int _oneTimeTeardownCount; + private int _teardownCount; + + /// + /// クラス内の最後のテストの実行後に一度だけ実行されます + /// + [OneTimeTearDown] + public void OneTimeTearDown() + { + Debug.Log($"OneTimeTearDown"); + _oneTimeTeardownCount++; + + Assert.That(_oneTimeTeardownCount, Is.EqualTo(1), "OneTimeTearDownはTestFixtureごとに一度だけ実行される"); + Assert.That(_teardownCount, Is.EqualTo(3), "3つのテストがあるのでTearDownは3回実行されている"); + } + + /// + /// 各テストメソッドの後に実行されます + /// + [TearDown] + public void TearDown() + { + Debug.Log($"TearDown"); + _teardownCount++; + } + + [Test] + public void TestMethod() + { + Debug.Log($"TestMethod"); + } + + [Test] + public async Task TestMethodAsync() + { + await Task.Yield(); + Debug.Log($"TestMethodAsync"); + } + + [UnityTest] + public IEnumerator UnityTestMethod() + { + yield return null; + Debug.Log($"UnityTestMethod"); + } + } +} diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/TearDownExample.cs.meta b/Assets/APIExamples/Tests/Runtime/NUnit/OneTimeTearDownAttributeExample.cs.meta similarity index 100% rename from Assets/APIExamples/Tests/Runtime/NUnit/TearDownExample.cs.meta rename to Assets/APIExamples/Tests/Runtime/NUnit/OneTimeTearDownAttributeExample.cs.meta diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/OrderAttributeExample.cs b/Assets/APIExamples/Tests/Runtime/NUnit/OrderAttributeExample.cs index e35a717..3c1f37c 100644 --- a/Assets/APIExamples/Tests/Runtime/NUnit/OrderAttributeExample.cs +++ b/Assets/APIExamples/Tests/Runtime/NUnit/OrderAttributeExample.cs @@ -38,7 +38,7 @@ public void OrderedTest3() public async Task OrderedTest2() { Assert.That(++s_count, Is.EqualTo(3)); - await Task.Delay(0); + await Task.Yield(); } [UnityTest] diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/RandomAttributeExample.cs b/Assets/APIExamples/Tests/Runtime/NUnit/RandomAttributeExample.cs index 0b77f39..1fae3e2 100644 --- a/Assets/APIExamples/Tests/Runtime/NUnit/RandomAttributeExample.cs +++ b/Assets/APIExamples/Tests/Runtime/NUnit/RandomAttributeExample.cs @@ -33,7 +33,7 @@ public class RandomAttributeExample [Random(0, 5, 3)] int i, [Random(5, 10, 3)] int j) { - await Task.Delay(0); + await Task.Yield(); Assert.That(i + j, Is.InRange((0 + 5), (4 + 9))); } diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/RangeAttributeExample.cs b/Assets/APIExamples/Tests/Runtime/NUnit/RangeAttributeExample.cs index 021cd41..455586b 100644 --- a/Assets/APIExamples/Tests/Runtime/NUnit/RangeAttributeExample.cs +++ b/Assets/APIExamples/Tests/Runtime/NUnit/RangeAttributeExample.cs @@ -34,7 +34,7 @@ public class RangeAttributeExample [Range(0.6f, 0.7f, 0.1f)] float f, [Range(0.08d, 0.09d, 0.005d)] double d) { - await Task.Delay(0); + await Task.Yield(); Assert.That(d + f + l + i, Is.InRange(0, 7)); } diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/SetupAttributeExample.cs b/Assets/APIExamples/Tests/Runtime/NUnit/SetupAttributeExample.cs index 4f79fb9..c26ae0e 100644 --- a/Assets/APIExamples/Tests/Runtime/NUnit/SetupAttributeExample.cs +++ b/Assets/APIExamples/Tests/Runtime/NUnit/SetupAttributeExample.cs @@ -1,25 +1,25 @@ -// Copyright (c) 2021-2023 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. +using System.Collections; +using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; using NUnit.Framework; -using UnityEngine; +using UnityEngine.TestTools; namespace APIExamples.NUnit { /// - /// , の例 + /// の使用例 /// + /// + /// + /// [TestFixture] + [SuppressMessage("ReSharper", "AccessToStaticMemberViaDerivedType")] public class SetupAttributeExample { - /// - /// クラス内の最初のテストの実行前に一度だけ実行されます - /// - [OneTimeSetUp] - public void OneTimeSetUp() - { - Debug.Log($"OneTimeSetUp, {Time.time}"); - } + private int _setupCount; /// /// 各テストメソッドの前に実行されます @@ -27,19 +27,27 @@ public void OneTimeSetUp() [SetUp] public void SetUp() { - Debug.Log($"SetUp, {Time.time}"); + _setupCount++; } - [Test] + [Test, Order(0)] public void TestMethod() { - Debug.Log($"TestMethod, {Time.time}"); + Assert.That(_setupCount, Is.EqualTo(1), "最初のテストなのでSetUpは1回実行されている"); + } + + [Test, Order(1)] + public async Task TestMethodAsync() + { + await Task.Yield(); + Assert.That(_setupCount, Is.EqualTo(2), "2番目のテストなのでSetUpは2回実行されている"); } - [Test] - public void TestMethod2() + [UnityTest, Order(2)] + public IEnumerator UnityTestMethod() { - Debug.Log($"TestMethod2, {Time.time}"); + yield return null; + Assert.That(_setupCount, Is.EqualTo(3), "3番目のテストなのでSetUpは3回実行されている"); } } } diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/SetupAttributeExample.cs.meta b/Assets/APIExamples/Tests/Runtime/NUnit/SetupAttributeExample.cs.meta index 515f1e2..91ce4e1 100644 --- a/Assets/APIExamples/Tests/Runtime/NUnit/SetupAttributeExample.cs.meta +++ b/Assets/APIExamples/Tests/Runtime/NUnit/SetupAttributeExample.cs.meta @@ -1,3 +1,3 @@ -fileFormatVersion: 2 -guid: f5debcab7d6f405f9755f7e1955426e8 -timeCreated: 1627036574 \ No newline at end of file +fileFormatVersion: 2 +guid: 2b076d3a9ea94c439e61c97d4cc95168 +timeCreated: 1762465031 \ No newline at end of file diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/TearDownAttributeExample.cs b/Assets/APIExamples/Tests/Runtime/NUnit/TearDownAttributeExample.cs new file mode 100644 index 0000000..4836d43 --- /dev/null +++ b/Assets/APIExamples/Tests/Runtime/NUnit/TearDownAttributeExample.cs @@ -0,0 +1,52 @@ +// Copyright (c) 2021-2025 Koji Hasegawa. +// This software is released under the MIT License. + +using System.Collections; +using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; +using NUnit.Framework; +using UnityEngine; +using UnityEngine.TestTools; + +namespace APIExamples.NUnit +{ + /// + /// の使用例 + /// + /// + /// + /// + [TestFixture] + [SuppressMessage("ReSharper", "AccessToStaticMemberViaDerivedType")] + public class TearDownAttributeExample + { + /// + /// 各テストメソッドの後に実行されます + /// + [TearDown] + public void TearDown() + { + Debug.Log($"TearDown"); + } + + [Test] + public void TestMethod() + { + Debug.Log($"TestMethod"); + } + + [Test] + public async Task TestMethodAsync() + { + await Task.Yield(); + Debug.Log($"TestMethodAsync"); + } + + [UnityTest] + public IEnumerator UnityTestMethod() + { + yield return null; + Debug.Log($"UnityTestMethod"); + } + } +} diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/TearDownAttributeExample.cs.meta b/Assets/APIExamples/Tests/Runtime/NUnit/TearDownAttributeExample.cs.meta new file mode 100644 index 0000000..cac434a --- /dev/null +++ b/Assets/APIExamples/Tests/Runtime/NUnit/TearDownAttributeExample.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: a62310a19258496daea6025cba719003 +timeCreated: 1762465043 \ No newline at end of file diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/TearDownExample.cs b/Assets/APIExamples/Tests/Runtime/NUnit/TearDownExample.cs deleted file mode 100644 index 3c63c6e..0000000 --- a/Assets/APIExamples/Tests/Runtime/NUnit/TearDownExample.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2021-2023 Koji Hasegawa. -// This software is released under the MIT License. - -using NUnit.Framework; -using UnityEngine; - -namespace APIExamples.NUnit -{ - /// - /// , の例 - /// - [TestFixture] - public class TearDownExample - { - /// - /// クラス内の最後のテストの実行後に一度だけ実行されます - /// - [OneTimeTearDown] - public void OneTimeTearDown() - { - Debug.Log($"OneTimeTearDown, {Time.time}"); - } - - /// - /// 各テストメソッドの後に実行されます - /// - [TearDown] - public void TearDown() - { - Debug.Log($"TearDown, {Time.time}"); - } - - [Test] - public void TestMethod() - { - Debug.Log($"TestMethod, {Time.time}"); - } - - [Test] - public void TestMethod2() - { - Debug.Log($"TestMethod2, {Time.time}"); - } - } -} diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/TestCaseAttributeExample.cs b/Assets/APIExamples/Tests/Runtime/NUnit/TestCaseAttributeExample.cs index 95f0725..86df174 100644 --- a/Assets/APIExamples/Tests/Runtime/NUnit/TestCaseAttributeExample.cs +++ b/Assets/APIExamples/Tests/Runtime/NUnit/TestCaseAttributeExample.cs @@ -1,44 +1,57 @@ // Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. +using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using NUnit.Framework; using UnityEngine.TestTools; -// ReSharper disable AccessToStaticMemberViaDerivedType - namespace APIExamples.NUnit { /// /// によるパラメタライズドテストの記述例. ///

- /// は、入力要素と期待値の組み合わせを指定できます。 /// と組み合わせては使用できません。 ///

/// /// 1xダメージのテストケースは を参照してください。 /// + /// [TestFixture] + [SuppressMessage("ReSharper", "AccessToStaticMemberViaDerivedType")] public class TestCaseAttributeExample { - [TestCase(Element.Fire, Element.Water)] - [TestCase(Element.Water, Element.Wood)] - [TestCase(Element.Wood, Element.Fire)] + [TestCase(Element.Fire, Element.Water)] // 火 ← 水 + [TestCase(Element.Water, Element.Wood)] // 水 ← 木 + [TestCase(Element.Wood, Element.Fire)] // 木 ← 火 public void GetDamageMultiplier_弱点属性からの攻撃はダメージ2x(Element defence, Element attack) { var actual = defence.GetDamageMultiplier(attack); - Assert.That(actual, Is.EqualTo(2.0f)); } - [TestCase(Element.Fire, Element.Water)] - [TestCase(Element.Water, Element.Wood)] - [TestCase(Element.Wood, Element.Fire)] - public async Task 非同期テストではTestCase属性を使用できる(Element defence, Element attack) + [TestCase(Element.Fire, Element.None, ExpectedResult = 1.0f)] + [TestCase(Element.Fire, Element.Water, ExpectedResult = 2.0f)] + [TestCase(Element.Fire, Element.Wood, ExpectedResult = 1.0f)] + [TestCase(Element.Water, Element.None, ExpectedResult = 1.0f)] + [TestCase(Element.Water, Element.Fire, ExpectedResult = 1.0f)] + [TestCase(Element.Water, Element.Wood, ExpectedResult = 2.0f)] + [TestCase(Element.Wood, Element.None, ExpectedResult = 1.0f)] + [TestCase(Element.Wood, Element.Fire, ExpectedResult = 2.0f)] + [TestCase(Element.Wood, Element.Water, ExpectedResult = 1.0f)] + public float ExpectedResultによるアサーションの例(Element defence, Element attack) { var actual = defence.GetDamageMultiplier(attack); - await Task.Yield(); + return actual; // 戻り値をExpectedResultと比較するアサーションが行われる + } + [TestCase(Element.Fire, Element.Water)] // 火 ← 水 + [TestCase(Element.Water, Element.Wood)] // 水 ← 木 + [TestCase(Element.Wood, Element.Fire)] // 木 ← 火 + public async Task 非同期テストでもTestCase属性を使用できる(Element defence, Element attack) + { + await Task.Yield(); + var actual = defence.GetDamageMultiplier(attack); Assert.That(actual, Is.EqualTo(2.0f)); } } diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/TestCaseSourceAttributeExample.cs b/Assets/APIExamples/Tests/Runtime/NUnit/TestCaseSourceAttributeExample.cs index 1aa868f..a2fbbe3 100644 --- a/Assets/APIExamples/Tests/Runtime/NUnit/TestCaseSourceAttributeExample.cs +++ b/Assets/APIExamples/Tests/Runtime/NUnit/TestCaseSourceAttributeExample.cs @@ -1,30 +1,28 @@ // Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. -using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using NUnit.Framework; using UnityEngine.TestTools; -// ReSharper disable AccessToStaticMemberViaDerivedType - namespace APIExamples.NUnit { /// /// によるパラメタライズドテストの記述例. ///

- /// は、入力要素と期待値の組み合わせを static で指定できます。 /// と組み合わせては使用できません。 ///

/// /// 1xダメージのテストケースは を参照してください。 /// + /// [TestFixture] + [SuppressMessage("ReSharper", "AccessToStaticMemberViaDerivedType")] public class TestCaseSourceAttributeExample { // テストケースを静的フィールドで定義 - // Note: TestCaseData は NUnit でなく、Unity Test Framework の提供するデータ型です private static TestCaseData[] s_weaknessElementCombinationCases = { new TestCaseData(Element.Fire, Element.Water), // 火 ← 水 @@ -32,16 +30,14 @@ public class TestCaseSourceAttributeExample new TestCaseData(Element.Wood, Element.Fire), // 木 ← 火 }; - [TestCaseSource(nameof(s_weaknessElementCombinationCases))] // フィールドを指定する例 + [TestCaseSource(nameof(s_weaknessElementCombinationCases))] public void GetDamageMultiplier_弱点属性からの攻撃はダメージ2x(Element defence, Element attack) { var actual = defence.GetDamageMultiplier(attack); - Assert.That(actual, Is.EqualTo(2.0f)); } // テストケースを返す静的メソッド - // Note: TestCaseData は NUnit でなく、Unity Test Framework の提供するデータ型です public static IEnumerable GetWeaknessElementCombinationCases() { yield return new TestCaseData(Element.Fire, Element.Water); // 火 ← 水 @@ -49,11 +45,10 @@ public static IEnumerable GetWeaknessElementCombinationCases() yield return new TestCaseData(Element.Wood, Element.Fire); // 木 ← 火 } - [TestCaseSource(nameof(GetWeaknessElementCombinationCases))] // メソッドを指定する例 + [TestCaseSource(nameof(GetWeaknessElementCombinationCases))] public void GetDamageMultiplier_弱点属性からの攻撃はダメージ2x_メソッド指定の例(Element defence, Element attack) { var actual = defence.GetDamageMultiplier(attack); - Assert.That(actual, Is.EqualTo(2.0f)); } @@ -69,15 +64,29 @@ public static IEnumerable GetWeaknessElementCombinationCasesInClas } [TestCaseSource(typeof(TestCasesInClass), nameof(TestCasesInClass.GetWeaknessElementCombinationCasesInClass))] - public void GetDamageMultiplier_弱点属性からの攻撃はダメージ2x_別クラスの例(Element defence, Element attack) + public void GetDamageMultiplier_弱点属性からの攻撃はダメージ2x_クラス指定の例(Element defence, Element attack) { var actual = defence.GetDamageMultiplier(attack); + Assert.That(actual, Is.EqualTo(2.0f)); + } + // 名前付きTestCaseData + private static TestCaseData[] s_weaknessElementCombinationCasesWithName = + { + new TestCaseData(Element.Fire, Element.Water).SetName("火 ← 水"), + new TestCaseData(Element.Water, Element.Wood).SetName("水 ← 木"), + new TestCaseData(Element.Wood, Element.Fire).SetName("木 ← 火"), + }; + + [TestCaseSource(nameof(s_weaknessElementCombinationCasesWithName))] + public void TestCaseDataにTestNameプロパティを指定した例(Element defence, Element attack) + { + var actual = defence.GetDamageMultiplier(attack); Assert.That(actual, Is.EqualTo(2.0f)); } [TestCaseSource(nameof(s_weaknessElementCombinationCases))] - public async Task 非同期テストではTestCaseSource属性を使用できる(Element defence, Element attack) + public async Task 非同期テストでもTestCaseSource属性を使用できる(Element defence, Element attack) { var actual = defence.GetDamageMultiplier(attack); await Task.Yield(); diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/TimeoutAttributeExample.cs b/Assets/APIExamples/Tests/Runtime/NUnit/TimeoutAttributeExample.cs index dacc2d6..fe27e9e 100644 --- a/Assets/APIExamples/Tests/Runtime/NUnit/TimeoutAttributeExample.cs +++ b/Assets/APIExamples/Tests/Runtime/NUnit/TimeoutAttributeExample.cs @@ -1,110 +1,107 @@ -// Copyright (c) 2021-2023 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. using System; using System.Collections; -using System.Diagnostics; using System.Threading.Tasks; +using Cysharp.Threading.Tasks; using NUnit.Framework; +using TestHelper.Attributes; using UnityEngine; using UnityEngine.TestTools; -#pragma warning disable CS0162 - namespace APIExamples.NUnit { /// /// およびデフォルトタイムアウト時間の確認 /// + /// + /// このクラスに書かれている振る舞いは、Unity Test Framework v1.4.6およびv1.6.0のものです。バージョンによって振る舞いが異なりますので注意してください。 + ///
+ /// 非同期 (async) テストでタイムアウト及びTimeout属性が機能しない問題は、Unity Test Framework v1.3.4で修正されました。 + /// + ///
[TestFixture] + [Explicit("Timeout属性によって失敗するテストの例")] public class TimeoutAttributeExample { - private readonly Stopwatch _stopwatch = new Stopwatch(); - private const bool Fail = false; // このフラグをtrueにするとこのクラスのテストはすべて失敗します - - [SetUp] - public void SetUp() + [Test] + [Timeout(200)] + public void Timeout属性_同期テストではタイムアウトで割り込みは発生しないが終了時に指定時間を超えていたらテスト失敗() { - _stopwatch.Restart(); + var endTime = DateTime.Now.AddSeconds(0.5d); + while (DateTime.Now < endTime) + { + } } - [TearDown] - public void TearDown() + [UnityTest] + [Timeout(200)] + public IEnumerator Timeout属性_UnityTest属性でWaitForSeconds_割り込みは発生しないが終了時に指定時間を超えていたらテスト失敗() { - UnityEngine.Debug.Log($"{_stopwatch.ElapsedMilliseconds} [ms]"); - Time.timeScale = 1f; + yield return new WaitForSeconds(0.5f); } - [Explicit("時間がかかるのでExplicit")] [UnityTest] - public IEnumerator タイムアウトのデフォルトは3分() + public IEnumerator タイムアウトのデフォルトは3分_3分でタイムアウト() { - var waitSeconds = 3 * 60 - 1; // タイムアウトのデフォルトは3[min] - if (Fail) + var endTime = DateTime.Now.AddMinutes(3d).AddSeconds(1d); + while (DateTime.Now < endTime) { - waitSeconds++; + yield return null; } - - yield return new WaitForSeconds(waitSeconds); } [UnityTest] - [Timeout(2000)] - public IEnumerator タイムアウトを2秒に設定() + [Timeout(200)] + public IEnumerator Timeout属性_UnityTest属性でYieldReturnNull_指定ミリ秒でタイムアウト() { - var waitSeconds = 1f; - if (Fail) + var endTime = DateTime.Now.AddSeconds(0.5d); + while (DateTime.Now < endTime) { - waitSeconds = 10f; + yield return null; } - - yield return new WaitForSeconds(waitSeconds); } [UnityTest] - [Timeout(2000)] - public IEnumerator タイムアウト値はTimeScaleに影響されない() + [Timeout(1000)] + [TimeScale(10.0f)] + public IEnumerator Timeout属性_タイムアウト値はTimeScaleに影響されない_指定ミリ秒でタイムアウト() { - var waitSeconds = 1f; - if (Fail) + var endTime = Time.realtimeSinceStartup + 2.0f; + while (Time.realtimeSinceStartup < endTime) { - waitSeconds = 10f; + yield return null; } - - Time.timeScale = 5f; - yield return new WaitForSecondsRealtime(waitSeconds); } - [UnityTest] - [Timeout(2000)] - public IEnumerator タイムアウトはWaitForSeconds以外では有効でない_中断されない() + [Test] + [Timeout(200)] + public async Task Timeout属性_非同期テストでDelay_指定ミリ秒でタイムアウト() { - var waitSeconds = 1f; - if (Fail) - { - waitSeconds = 10f; - } + await Task.Delay(TimeSpan.FromSeconds(0.5f)); + } - var startTime = DateTime.Now; - while ((DateTime.Now - startTime).Seconds < waitSeconds) + [Test] + [Timeout(200)] + public async Task Timeout属性_非同期テストでYield_指定ミリ秒でタイムアウト() + { + var endTime = DateTime.Now.AddSeconds(0.5d); + while (DateTime.Now < endTime) { - yield return null; // Timeout時間を超えてもテストは中断されない。指定時間を超過していれば失敗と判定はされる + await Task.Yield(); } } [Test] - [Timeout(2000)] - // Note: 非同期(async)テストでタイムアウト及びTimeout属性が機能しない問題は、Unity Test Framework v1.3.4で修正された - // See: https://unity3d.atlassian.net/servicedesk/customer/portal/2/IN-28108 - public async Task 非同期テストでタイムアウトを2秒に設定() + [Timeout(200)] + public async Task Timeout属性_非同期テストでNextFrame_指定ミリ秒でタイムアウト() { - var waitSeconds = 1f; - if (Fail) + var endTime = DateTime.Now.AddSeconds(0.5d); + while (DateTime.Now < endTime) { - waitSeconds = 10f; + await UniTask.NextFrame(); } - - await Task.Delay(TimeSpan.FromSeconds(waitSeconds)); } } } diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/ValueSourceAttributeExample.cs b/Assets/APIExamples/Tests/Runtime/NUnit/ValueSourceAttributeExample.cs index 901399e..cf96041 100644 --- a/Assets/APIExamples/Tests/Runtime/NUnit/ValueSourceAttributeExample.cs +++ b/Assets/APIExamples/Tests/Runtime/NUnit/ValueSourceAttributeExample.cs @@ -3,27 +3,26 @@ using System.Collections; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using NUnit.Framework; using UnityEngine.TestTools; -// ReSharper disable AccessToStaticMemberViaDerivedType - namespace APIExamples.NUnit { /// /// によるパラメタライズドテストの記述例. ///

- /// は組み合わせテストになるため、期待値が同じになる要素ごとにテストメソッドを定義するとわかりやすくなります。 - ///

- /// 組み合わせ生成ルールのデフォルトは全網羅です。明示的に全網羅であることを示すには を使用できます。 + /// 組み合わせ生成ルールのデフォルトは全組み合わせ網羅です。明示的に全組み合わせ網羅であることを示すには を使用できます。 /// 組み合わせを絞り込む のサンプルは を参照してください。 /// 組み合わせを固定する のサンプルは を参照してください。 ///

/// /// 2xダメージのテストケースは を参照してください。 /// + /// [TestFixture] + [SuppressMessage("ReSharper", "AccessToStaticMemberViaDerivedType")] public class ValueSourceAttributeExample { // テストケースの引数が取る値を静的フィールドで定義 @@ -31,15 +30,15 @@ public class ValueSourceAttributeExample [Test] public void GetDamageMultiplier_無属性からの攻撃はすべて等倍ダメージ( - [ValueSource(nameof(s_elements))] Element defence) // フィールドを指定する例 + [ValueSource(nameof(s_elements))] Element defence, // フィールドを指定する例 + [Values(Element.None)] Element attack) { - var actual = defence.GetDamageMultiplier(Element.None); - + var actual = defence.GetDamageMultiplier(attack); Assert.That(actual, Is.EqualTo(1.0f)); } - // テストケースの引数が取る値を返す静的メソッド - public static IEnumerable GetElements() + // テストケースの引数が取る値を静的メソッドで定義 + private static IEnumerable GetElements() { yield return Element.None; yield return Element.Fire; @@ -49,10 +48,10 @@ public static IEnumerable GetElements() [Test] public void GetDamageMultiplier_無属性への攻撃はすべて等倍ダメージ( + [Values(Element.None)] Element defence, [ValueSource(nameof(GetElements))] Element attack) // メソッドを指定する例 { - var actual = Element.None.GetDamageMultiplier(attack); - + var actual = defence.GetDamageMultiplier(attack); Assert.That(actual, Is.EqualTo(1.0f)); } @@ -61,12 +60,11 @@ public static IEnumerable GetElements() [ParametrizedIgnore(Element.Water, Element.Wood)] [ParametrizedIgnore(Element.Wood, Element.Fire)] public void GetDamageMultiplier_ParametrizedIgnore属性で等倍ダメージにならない組み合わせを除外_すべて等倍ダメージ( - // Note: ParametrizedIgnore 属性は NUnit でなく、Unity Test Framework v1.4 で追加された属性です + // Note: ParametrizedIgnore 属性は Unity Test Framework v1.4 で追加された属性です [ValueSource(nameof(s_elements))] Element defence, - [ValueSource(nameof(s_elements))] Element attack) + [ValueSource(nameof(GetElements))] Element attack) { var actual = defence.GetDamageMultiplier(attack); - Assert.That(actual, Is.EqualTo(1.0f)); } @@ -77,7 +75,7 @@ public static IEnumerable GetElements() public IEnumerator UnityTestでもValueSource属性は使用可能( // Note: UnityTest で ParametrizedIgnore 属性が使用できるのは、Unity Test Framework v1.4.6以降です [ValueSource(nameof(s_elements))] Element defence, - [ValueSource(nameof(s_elements))] Element attack) + [ValueSource(nameof(GetElements))] Element attack) { var actual = defence.GetDamageMultiplier(attack); yield return null; @@ -92,7 +90,7 @@ public static IEnumerable GetElements() public async Task 非同期テストでもValueSource属性は使用可能( // Note: Async test で ParametrizedIgnore 属性が使用できるのは、Unity Test Framework v1.4.6以降です [ValueSource(nameof(s_elements))] Element defence, - [ValueSource(nameof(s_elements))] Element attack) + [ValueSource(nameof(GetElements))] Element attack) { var actual = defence.GetDamageMultiplier(attack); await Task.Yield(); diff --git a/Assets/APIExamples/Tests/Runtime/NUnit/ValuesAttributeExample.cs b/Assets/APIExamples/Tests/Runtime/NUnit/ValuesAttributeExample.cs index 8ea1328..b5396ca 100644 --- a/Assets/APIExamples/Tests/Runtime/NUnit/ValuesAttributeExample.cs +++ b/Assets/APIExamples/Tests/Runtime/NUnit/ValuesAttributeExample.cs @@ -2,40 +2,36 @@ // This software is released under the MIT License. using System.Collections; +using System.Diagnostics.CodeAnalysis; using System.Threading.Tasks; using NUnit.Framework; using UnityEngine.TestTools; -// ReSharper disable AccessToStaticMemberViaDerivedType - namespace APIExamples.NUnit { /// /// によるパラメタライズドテストの記述例. ///

- /// は組み合わせテストになるため、期待値が同じになる要素ごとにメソッドを定義するとわかりやすくなります。 - ///

- /// 組み合わせ生成ルールのデフォルトは全網羅です。明示的に全網羅であることを示すには を使用できます。 + /// 組み合わせ生成ルールのデフォルトは全組み合わせ網羅です。明示的に全組み合わせ網羅であることを示すには を使用できます。 /// 組み合わせを絞り込む のサンプルは を参照してください。 /// 組み合わせを固定する のサンプルは を参照してください。 - ///

- /// /// 数値型にでたらめな値を与える のサンプルは を参照してください。 /// 数値型の値を範囲指定で与える のサンプルは を参照してください。 - ///

+ ///

+ /// /// 2xダメージのテストケースは を参照してください。 /// + /// [TestFixture] + [SuppressMessage("ReSharper", "AccessToStaticMemberViaDerivedType")] public class ValuesAttributeExample { [Test] public void GetDamageMultiplier_無属性からの攻撃はすべて等倍ダメージ( - [Values(Element.None, Element.Fire, Element.Water, Element.Wood)] - Element defence, + [Values] Element defence, // Note: enumおよびbool型に対してValue属性の引数を省略したときはすべての値が渡されます [Values(Element.None)] Element attack) { var actual = defence.GetDamageMultiplier(attack); - Assert.That(actual, Is.EqualTo(1.0f)); } @@ -45,7 +41,6 @@ public class ValuesAttributeExample [Values] Element attack) // Note: enumおよびbool型に対してValue属性の引数を省略したときはすべての値が渡されます { var actual = defence.GetDamageMultiplier(attack); - Assert.That(actual, Is.EqualTo(1.0f)); } @@ -54,12 +49,11 @@ public class ValuesAttributeExample [ParametrizedIgnore(Element.Water, Element.Wood)] [ParametrizedIgnore(Element.Wood, Element.Fire)] public void GetDamageMultiplier_ParametrizedIgnore属性で等倍ダメージにならない組み合わせを除外_すべて等倍ダメージ( - // Note: ParametrizedIgnore 属性は NUnit でなく、Unity Test Framework v1.4 で追加された属性です + // Note: ParametrizedIgnore 属性は Unity Test Framework v1.4 で追加された属性です [Values] Element defence, [Values] Element attack) { var actual = defence.GetDamageMultiplier(attack); - Assert.That(actual, Is.EqualTo(1.0f)); } diff --git a/Assets/APIExamples/Tests/Runtime/UnityTestFramework/AllocatingGcMemoryExample.cs b/Assets/APIExamples/Tests/Runtime/UnityTestFramework/AllocatingGcMemoryExample.cs index 00bb41a..5736210 100644 --- a/Assets/APIExamples/Tests/Runtime/UnityTestFramework/AllocatingGcMemoryExample.cs +++ b/Assets/APIExamples/Tests/Runtime/UnityTestFramework/AllocatingGcMemoryExample.cs @@ -74,7 +74,7 @@ void UseColor() Assert.That(UseColor, Is.Not.AllocatingGCMemory()); } - [Ignore("Is.Not.AllocatingGCMemory()をasyncメソッドに使用するとUnityエディターがフリーズ(Unity Test Framework v1.4.0時点)")] + [Ignore("Is.Not.AllocatingGCMemory()をasyncメソッドに使用するとUnityエディターがフリーズ(Unity Test Framework v1.6.0時点)")] [Test] public async Task プリミティブ型_ヒープアロケーションなしAsync_Unityエディターがフリーズ() { @@ -91,7 +91,7 @@ async Task UsePrimitives() Assert.That(async () => await UsePrimitives(), Is.Not.AllocatingGCMemory()); } - [Explicit("Is.AllocatingGCMemory()をasyncメソッドに使用しても常に成功してしまう(Unity Test Framework v1.4.0時点)")] + [Explicit("Is.AllocatingGCMemory()をasyncメソッドに使用しても常に成功してしまう(Unity Test Framework v1.6.0時点)")] [Test] public async Task String型_ヒープアロケーションありAsync_常に成功してしまう() { diff --git a/Assets/APIExamples/Tests/Runtime/UnityTestFramework/EqualityComparerExample.cs b/Assets/APIExamples/Tests/Runtime/UnityTestFramework/EqualityComparerExample.cs index e8cc9a6..6a4241a 100644 --- a/Assets/APIExamples/Tests/Runtime/UnityTestFramework/EqualityComparerExample.cs +++ b/Assets/APIExamples/Tests/Runtime/UnityTestFramework/EqualityComparerExample.cs @@ -63,6 +63,16 @@ public class EqualityComparerExample Assert.That(actual, Is.EqualTo(expected).Using(comparer)); } + [Test] + public void Vector2ComparerWithEqualsOperator使用例_等価オペレーターで比較される() + { + var actual = new Vector2(10f, 0f); + var expected = new Vector2(10.0f, 0f); + + Assert.That(actual, Is.EqualTo(expected).Using(Vector2ComparerWithEqualsOperator.Instance)); + // Note: actual == expected で比較 + } + [Test] public void Vector3EqualityComparer使用例_だいたい合ってるのでヨシ() { @@ -73,6 +83,16 @@ public class EqualityComparerExample Assert.That(actual, Is.EqualTo(expected).Using(comparer)); } + [Test] + public void Vector3ComparerWithEqualsOperator使用例_等価オペレーターで比較される() + { + var actual = new Vector3(10f, 0f, 0f); + var expected = new Vector3(10.0f, 0f, 0f); + + Assert.That(actual, Is.EqualTo(expected).Using(Vector3ComparerWithEqualsOperator.Instance)); + // Note: actual == expected で比較 + } + [Test] public void Vector4EqualityComparer使用例_だいたい合ってるのでヨシ() { @@ -82,5 +102,15 @@ public class EqualityComparerExample Assert.That(actual, Is.EqualTo(expected).Using(comparer)); } + + [Test] + public void Vector4ComparerWithEqualsOperator使用例_等価オペレーターで比較される() + { + var actual = new Vector4(10f, 0f, 0f, 0f); + var expected = new Vector4(10.0f, 0f, 0f, 0f); + + Assert.That(actual, Is.EqualTo(expected).Using(Vector4ComparerWithEqualsOperator.Instance)); + // Note: actual == expected で比較 + } } } diff --git a/Assets/APIExamples/Tests/Runtime/UnityTestFramework/LogAssertExample.cs b/Assets/APIExamples/Tests/Runtime/UnityTestFramework/LogAssertExample.cs index ce08ed9..a38b88f 100644 --- a/Assets/APIExamples/Tests/Runtime/UnityTestFramework/LogAssertExample.cs +++ b/Assets/APIExamples/Tests/Runtime/UnityTestFramework/LogAssertExample.cs @@ -88,7 +88,7 @@ public class LogAssertExample if (Fail) { - await Task.Delay(200); + await Task.Yield(); Debug.LogError("expected message"); // フレームが進むとLogAssert.Expectは無効 } } @@ -138,7 +138,7 @@ public class LogAssertExample { Debug.Log("expected message"); - await Task.Delay(200); + await Task.Yield(); LogAssert.Expect(LogType.Log, "expected message"); } diff --git a/Assets/APIExamples/Tests/Runtime/UnityTestFramework/MonoBehaviourTestExample.cs b/Assets/APIExamples/Tests/Runtime/UnityTestFramework/MonoBehaviourTestExample.cs index b591502..f44a791 100644 --- a/Assets/APIExamples/Tests/Runtime/UnityTestFramework/MonoBehaviourTestExample.cs +++ b/Assets/APIExamples/Tests/Runtime/UnityTestFramework/MonoBehaviourTestExample.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. using System.Collections; @@ -6,80 +6,91 @@ using UnityEngine; using UnityEngine.TestTools; +#pragma warning disable CS0618 // Type or member is obsolete + namespace APIExamples.UnityTestFramework { /// - /// の使用例 + /// の使用例 /// + [TestFixture] public class MonoBehaviourTestExample { + /// + /// の実装例(テストスパイ) + ///

+ /// Start が完了した時点で終了します + ///

+ private class SpyMyMonoBehaviour : MyMonoBehaviour, IMonoBehaviourTest + { + public bool WasAwake => base._wasAwake; + public bool WasStart => base._wasStart; + public bool WasDestroy => base._wasDestroy; + + /// + /// テスト終了条件を満たしたらtrueを返します + /// + public bool IsTestFinished => WasStart; // Startが完了したら終了 + } + [UnityTest] - public IEnumerator MonoBehaviourTestの使用例() + public IEnumerator MonoBehaviourTestをテストスパイとして使用したMonoBehaviourのテスト() { - yield return new MonoBehaviourTest(); + // Exercise + yield return new MonoBehaviourTest(); + + // Verify + var spy = GameObject.FindObjectOfType(); + Assert.That(spy.WasAwake, Is.True); + Assert.That(spy.WasStart, Is.True); + Assert.That(spy.WasDestroy, Is.False); + + // Teardown + GameObject.DestroyImmediate(spy.gameObject); } /// - /// の実装例 + /// の実装例(モックオブジェクト) + ///

+ /// GameObject が破棄されたら内部情報を検証して終了します ///

- private class MyMonoBehaviourTest : SUTMonoBehaviour, IMonoBehaviourTest + private class MockMyMonoBehaviour : MyMonoBehaviour, IMonoBehaviourTest { /// - /// テスト終了条件を満たしたらtrueを返します - /// アサーションもここに書きます + /// テスト終了条件を満たしたらtrueを返します。 + /// モックオブジェクトとしての実装例なので、アサーションまで行ないます /// public bool IsTestFinished { get { - // Exercise - if (!base._doneDestroy) + if (!base._wasDestroy) { - return false; // テスト実行を継続 + return false; // 条件を満たすまで(OnDestroyが呼ばれるまで)テスト実行を継続 } - // Verify - Assert.That(base._doneAwake, Is.True); - Assert.That(base._doneStart, Is.True); - Assert.That(base._doneDestroy, Is.True); + // Verify + Assert.That(base._wasAwake, Is.True); + Assert.That(base._wasStart, Is.True); + Assert.That(base._wasDestroy, Is.True); - return true; // テスト終了 + return true; } } } - /// - /// テスト対象MonoBehaviour - /// 生成されて5フレームで破棄されます - /// - private class SUTMonoBehaviour : MonoBehaviour + [UnityTest] + public IEnumerator MonoBehaviourTestをモックオブジェクトとして使用したMonoBehaviourのテスト() { - protected bool _doneAwake; - protected bool _doneStart; - private int _frameCount; - protected bool _doneDestroy; - - private void Awake() - { - _doneAwake = true; - } - - private void Start() - { - _doneStart = true; - } - - private void Update() - { - if (++_frameCount > 4) - { - Destroy(this); - } - } + // Exercise & Verify + yield return new MonoBehaviourTest(); - private void OnDestroy() + // Teardown + // Note: MockMyMonoBehaviour の実装ではこの時点で破棄済みですが、通常は後始末が必要です + var mock = GameObject.FindObjectOfType(); + if (mock != null) { - _doneDestroy = true; + GameObject.DestroyImmediate(mock.gameObject); } } } diff --git a/Assets/APIExamples/Tests/Runtime/UnityTestFramework/PreBuildSetupAttributeExample.cs b/Assets/APIExamples/Tests/Runtime/UnityTestFramework/PreBuildSetupAttributeExample.cs index 0f6bc71..878526e 100644 --- a/Assets/APIExamples/Tests/Runtime/UnityTestFramework/PreBuildSetupAttributeExample.cs +++ b/Assets/APIExamples/Tests/Runtime/UnityTestFramework/PreBuildSetupAttributeExample.cs @@ -21,7 +21,6 @@ public class PreBuildSetupAttributeExample [Test] public void PrebuildSetupAttributeを付与したテストの例() { - Assert.That(true, Is.True); } } } diff --git a/Assets/APIExamples/Tests/Runtime/UnityTestFramework/PreBuildSetupExample.cs b/Assets/APIExamples/Tests/Runtime/UnityTestFramework/PreBuildSetupExample.cs index e22a271..84d2f8c 100644 --- a/Assets/APIExamples/Tests/Runtime/UnityTestFramework/PreBuildSetupExample.cs +++ b/Assets/APIExamples/Tests/Runtime/UnityTestFramework/PreBuildSetupExample.cs @@ -26,7 +26,6 @@ public void Cleanup() [Test] public void IPrebuildSetupを実装したテストの例() { - Assert.That(true, Is.True); } } } diff --git a/Assets/APIExamples/Tests/Runtime/UnityTestFramework/UnitySetUpAttributeExample.cs b/Assets/APIExamples/Tests/Runtime/UnityTestFramework/UnitySetUpAttributeExample.cs index 0d8a36d..fc06faa 100644 --- a/Assets/APIExamples/Tests/Runtime/UnityTestFramework/UnitySetUpAttributeExample.cs +++ b/Assets/APIExamples/Tests/Runtime/UnityTestFramework/UnitySetUpAttributeExample.cs @@ -1,10 +1,9 @@ -// Copyright (c) 2021 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. using System.Collections; +using System.Threading.Tasks; using NUnit.Framework; -using UnityEngine; -using UnityEngine.SceneManagement; using UnityEngine.TestTools; namespace APIExamples.UnityTestFramework @@ -12,36 +11,43 @@ namespace APIExamples.UnityTestFramework /// /// の使用例 /// + /// + /// + /// [TestFixture] public class UnitySetUpAttributeExample { + private int _setupCount; + /// - /// SetUpをコルーチンで記述できます + /// SetUpをコルーチン書式で記述できます /// 専用ではなく、通常のTest向けのSetUpとしても使用できます /// [UnitySetUp] public IEnumerator SetUpCoroutine() { - yield return SceneManager.LoadSceneAsync("HelloTesting"); + yield return null; + _setupCount++; } - [Test] - public void Test属性テストメソッド() + [Test, Order(0)] + public void TestMethod() { - var cube = GameObject.Find("Cube"); - Object.DestroyImmediate(cube); + Assert.That(_setupCount, Is.EqualTo(1), "最初のテストなのでSetUpは1回実行されている"); + } - Assert.That((bool)cube, Is.False); + [Test, Order(1)] + public async Task TestMethodAsync() + { + await Task.Yield(); + Assert.That(_setupCount, Is.EqualTo(2), "2番目のテストなのでSetUpは2回実行されている"); } - [UnityTest] - public IEnumerator UnityTest属性テストメソッド() + [UnityTest, Order(2)] + public IEnumerator UnityTestMethod() { - var cube = GameObject.Find("Cube"); - Object.Destroy(cube); yield return null; - - Assert.That((bool)cube, Is.False); + Assert.That(_setupCount, Is.EqualTo(3), "3番目のテストなのでSetUpは3回実行されている"); } } } diff --git a/Assets/APIExamples/Tests/Runtime/UnityTestFramework/UnityTearDownAttributeExample.cs b/Assets/APIExamples/Tests/Runtime/UnityTestFramework/UnityTearDownAttributeExample.cs index 0c5c278..cdc5559 100644 --- a/Assets/APIExamples/Tests/Runtime/UnityTestFramework/UnityTearDownAttributeExample.cs +++ b/Assets/APIExamples/Tests/Runtime/UnityTestFramework/UnityTearDownAttributeExample.cs @@ -1,49 +1,52 @@ -// Copyright (c) 2021 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. using System.Collections; +using System.Threading.Tasks; using NUnit.Framework; using UnityEngine; using UnityEngine.TestTools; -using UnityEngine.TestTools.Utils; namespace APIExamples.UnityTestFramework { /// /// の使用例 /// + /// + /// + /// [TestFixture] public class UnityTearDownAttributeExample { - private Object _cube; - /// - /// TearDownをコルーチンで記述できます + /// TearDownをコルーチン書式で記述できます /// 専用ではなく、通常のTest向けのTearDownとしても使用できます /// [UnityTearDown] public IEnumerator TearDownCoroutine() { - Object.Destroy(_cube); yield return null; - // Note: WebGLでも動作しているか確認するためにここで`Assert.Fail()`したらfailしたので動いている模様 + Debug.Log($"TearDown"); } [Test] - public void Test属性のテストメソッド() + public void TestMethod() { - _cube = Utils.CreatePrimitive(PrimitiveType.Cube); + Debug.Log($"TestMethod"); + } - Assert.That((bool)_cube, Is.True); + [Test] + public async Task TestMethodAsync() + { + await Task.Yield(); + Debug.Log($"TestMethodAsync"); } [UnityTest] - public IEnumerator UnityTest属性のテストメソッド() + public IEnumerator UnityTestMethod() { - _cube = Utils.CreatePrimitive(PrimitiveType.Cube); yield return null; - - Assert.That((bool)_cube, Is.True); + Debug.Log($"UnityTestMethod"); } } } diff --git a/Assets/APIExamples/Tests/Runtime/UnityTestFramework/UnityTestAttributeExample.cs b/Assets/APIExamples/Tests/Runtime/UnityTestFramework/UnityTestAttributeExample.cs index fcd3da9..a656525 100644 --- a/Assets/APIExamples/Tests/Runtime/UnityTestFramework/UnityTestAttributeExample.cs +++ b/Assets/APIExamples/Tests/Runtime/UnityTestFramework/UnityTestAttributeExample.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021-2023 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. using System; @@ -13,7 +13,6 @@ namespace APIExamples.UnityTestFramework { /// /// フレームをまたがるテストをで実装する例 - /// UniTaskの使用例を含みます /// [TestFixture] public class UnityTestAttributeExample @@ -23,6 +22,7 @@ public class UnityTestAttributeExample { var before = Time.frameCount; yield return null; + var actual = Time.frameCount; Assert.That(actual, Is.EqualTo(before + 1)); @@ -35,15 +35,15 @@ public class UnityTestAttributeExample } [UnityTest] - [Category("IgnoreCI")] - [Description("CIでは(Linux Editorでは?)フレームが進んでしまう(648 to 41767)のでとりあえず除外")] public IEnumerator YieldInstructionの実装クラスを使用できる() { - var before = Time.frameCount; - yield return new WaitForEndOfFrame(); - var actual = Time.frameCount; + var start = Time.time; // The time at the beginning of this frame + const float WaitSeconds = 0.5f; + yield return new WaitForSeconds(WaitSeconds); - Assert.That(actual, Is.EqualTo(before)); + var actual = Time.time - start; + + Assert.That(actual, Is.EqualTo(WaitSeconds).Within(0.1f)); } [UnityTest] @@ -52,6 +52,7 @@ public class UnityTestAttributeExample var start = Time.time; // The time at the beginning of this frame const float WaitSeconds = 0.5f; yield return new WaitForSecondsRealtime(WaitSeconds); + var actual = Time.time - start; Assert.That(actual, Is.EqualTo(WaitSeconds).Within(0.1f)); @@ -60,7 +61,7 @@ public class UnityTestAttributeExample [UnityTest] public IEnumerator AsyncOperationの終了を待つテストの例() { - yield return SceneManager.LoadSceneAsync("HelloTesting"); + yield return SceneManager.LoadSceneAsync("ContainScenesInBuild"); var cube = GameObject.Find("Cube"); Assert.That((bool)cube, Is.True); @@ -69,7 +70,7 @@ public class UnityTestAttributeExample [UnityTest] public IEnumerator UniTaskでAsyncメソッドを使用するテストの例() => UniTask.ToCoroutine(async () => { - await SceneManager.LoadSceneAsync("HelloTesting"); + await SceneManager.LoadSceneAsync("ContainScenesInBuild"); var cube = GameObject.Find("Cube"); Assert.That((bool)cube, Is.True); @@ -79,6 +80,7 @@ public class UnityTestAttributeExample public IEnumerator コルーチンを起動してコールバックを受け取る例() { var actual = 0; + yield return BarCoroutine(i => { actual = i; @@ -91,6 +93,7 @@ public class UnityTestAttributeExample public IEnumerator UniTaskでコルーチンを起動してコールバックを受け取る例() => UniTask.ToCoroutine(async () => { var actual = 0; + await BarCoroutine(i => { actual = i; diff --git a/Assets/BasicExample/Scenes/HelloTesting.unity b/Assets/BasicExample/Scenes/HelloTesting.unity deleted file mode 100644 index 1052144..0000000 --- a/Assets/BasicExample/Scenes/HelloTesting.unity +++ /dev/null @@ -1,396 +0,0 @@ -%YAML 1.1 -%TAG !u! tag:unity3d.com,2011: ---- !u!29 &1 -OcclusionCullingSettings: - m_ObjectHideFlags: 0 - serializedVersion: 2 - m_OcclusionBakeSettings: - smallestOccluder: 5 - smallestHole: 0.25 - backfaceThreshold: 100 - m_SceneGUID: 00000000000000000000000000000000 - m_OcclusionCullingData: {fileID: 0} ---- !u!104 &2 -RenderSettings: - m_ObjectHideFlags: 0 - serializedVersion: 9 - m_Fog: 0 - m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} - m_FogMode: 3 - m_FogDensity: 0.01 - m_LinearFogStart: 0 - m_LinearFogEnd: 300 - m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1} - m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1} - m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1} - m_AmbientIntensity: 1 - m_AmbientMode: 0 - m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1} - m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0} - m_HaloStrength: 0.5 - m_FlareStrength: 1 - m_FlareFadeSpeed: 3 - m_HaloTexture: {fileID: 0} - m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0} - m_DefaultReflectionMode: 0 - m_DefaultReflectionResolution: 128 - m_ReflectionBounces: 1 - m_ReflectionIntensity: 1 - m_CustomReflection: {fileID: 0} - m_Sun: {fileID: 0} - m_IndirectSpecularColor: {r: 0.44657838, g: 0.49641234, b: 0.57481676, a: 1} - m_UseRadianceAmbientProbe: 0 ---- !u!157 &3 -LightmapSettings: - m_ObjectHideFlags: 0 - serializedVersion: 12 - m_GIWorkflowMode: 1 - m_GISettings: - serializedVersion: 2 - m_BounceScale: 1 - m_IndirectOutputScale: 1 - m_AlbedoBoost: 1 - m_EnvironmentLightingMode: 0 - m_EnableBakedLightmaps: 1 - m_EnableRealtimeLightmaps: 0 - m_LightmapEditorSettings: - serializedVersion: 12 - m_Resolution: 2 - m_BakeResolution: 40 - m_AtlasSize: 1024 - m_AO: 0 - m_AOMaxDistance: 1 - m_CompAOExponent: 1 - m_CompAOExponentDirect: 0 - m_ExtractAmbientOcclusion: 0 - m_Padding: 2 - m_LightmapParameters: {fileID: 0} - m_LightmapsBakeMode: 1 - m_TextureCompression: 1 - m_FinalGather: 0 - m_FinalGatherFiltering: 1 - m_FinalGatherRayCount: 256 - m_ReflectionCompression: 2 - m_MixedBakeMode: 2 - m_BakeBackend: 1 - m_PVRSampling: 1 - m_PVRDirectSampleCount: 32 - m_PVRSampleCount: 512 - m_PVRBounces: 2 - m_PVREnvironmentSampleCount: 256 - m_PVREnvironmentReferencePointCount: 2048 - m_PVRFilteringMode: 1 - m_PVRDenoiserTypeDirect: 1 - m_PVRDenoiserTypeIndirect: 1 - m_PVRDenoiserTypeAO: 1 - m_PVRFilterTypeDirect: 0 - m_PVRFilterTypeIndirect: 0 - m_PVRFilterTypeAO: 0 - m_PVREnvironmentMIS: 1 - m_PVRCulling: 1 - m_PVRFilteringGaussRadiusDirect: 1 - m_PVRFilteringGaussRadiusIndirect: 5 - m_PVRFilteringGaussRadiusAO: 2 - m_PVRFilteringAtrousPositionSigmaDirect: 0.5 - m_PVRFilteringAtrousPositionSigmaIndirect: 2 - m_PVRFilteringAtrousPositionSigmaAO: 1 - m_ExportTrainingData: 0 - m_TrainingDataDestination: TrainingData - m_LightProbeSampleCountMultiplier: 4 - m_LightingDataAsset: {fileID: 0} - m_LightingSettings: {fileID: 0} ---- !u!196 &4 -NavMeshSettings: - serializedVersion: 2 - m_ObjectHideFlags: 0 - m_BuildSettings: - serializedVersion: 2 - agentTypeID: 0 - agentRadius: 0.5 - agentHeight: 2 - agentSlope: 45 - agentClimb: 0.4 - ledgeDropHeight: 0 - maxJumpAcrossDistance: 0 - minRegionArea: 2 - manualCellSize: 0 - cellSize: 0.16666667 - manualTileSize: 0 - tileSize: 256 - accuratePlacement: 0 - maxJobWorkers: 0 - preserveTilesOutsideBounds: 0 - debug: - m_Flags: 0 - m_NavMeshData: {fileID: 0} ---- !u!1 &659326155 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 659326159} - - component: {fileID: 659326158} - - component: {fileID: 659326157} - - component: {fileID: 659326156} - m_Layer: 0 - m_Name: Cube - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!65 &659326156 -BoxCollider: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 659326155} - m_Material: {fileID: 0} - m_IsTrigger: 0 - m_Enabled: 1 - serializedVersion: 2 - m_Size: {x: 1, y: 1, z: 1} - m_Center: {x: 0, y: 0, z: 0} ---- !u!23 &659326157 -MeshRenderer: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 659326155} - m_Enabled: 1 - m_CastShadows: 1 - m_ReceiveShadows: 1 - m_DynamicOccludee: 1 - m_MotionVectors: 1 - m_LightProbeUsage: 1 - m_ReflectionProbeUsage: 1 - m_RayTracingMode: 2 - m_RayTraceProcedural: 0 - m_RenderingLayerMask: 1 - m_RendererPriority: 0 - m_Materials: - - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} - m_StaticBatchInfo: - firstSubMesh: 0 - subMeshCount: 0 - m_StaticBatchRoot: {fileID: 0} - m_ProbeAnchor: {fileID: 0} - m_LightProbeVolumeOverride: {fileID: 0} - m_ScaleInLightmap: 1 - m_ReceiveGI: 1 - m_PreserveUVs: 0 - m_IgnoreNormalsForChartDetection: 0 - m_ImportantGI: 0 - m_StitchLightmapSeams: 1 - m_SelectedEditorRenderState: 3 - m_MinimumChartSize: 4 - m_AutoUVMaxDistance: 0.5 - m_AutoUVMaxAngle: 89 - m_LightmapParameters: {fileID: 0} - m_SortingLayerID: 0 - m_SortingLayer: 0 - m_SortingOrder: 0 - m_AdditionalVertexStreams: {fileID: 0} ---- !u!33 &659326158 -MeshFilter: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 659326155} - m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} ---- !u!4 &659326159 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 659326155} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 924.2142, y: 351.34674, z: -17.195045} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 2 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} ---- !u!1 &1155269674 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1155269676} - - component: {fileID: 1155269675} - m_Layer: 0 - m_Name: Directional Light - m_TagString: Untagged - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!108 &1155269675 -Light: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1155269674} - m_Enabled: 1 - serializedVersion: 10 - m_Type: 1 - m_Shape: 0 - m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} - m_Intensity: 1 - m_Range: 10 - m_SpotAngle: 30 - m_InnerSpotAngle: 21.80208 - m_CookieSize: 10 - m_Shadows: - m_Type: 2 - m_Resolution: -1 - m_CustomResolution: -1 - m_Strength: 1 - m_Bias: 0.05 - m_NormalBias: 0.4 - m_NearPlane: 0.2 - m_CullingMatrixOverride: - e00: 1 - e01: 0 - e02: 0 - e03: 0 - e10: 0 - e11: 1 - e12: 0 - e13: 0 - e20: 0 - e21: 0 - e22: 1 - e23: 0 - e30: 0 - e31: 0 - e32: 0 - e33: 1 - m_UseCullingMatrixOverride: 0 - m_Cookie: {fileID: 0} - m_DrawHalo: 0 - m_Flare: {fileID: 0} - m_RenderMode: 0 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingLayerMask: 1 - m_Lightmapping: 4 - m_LightShadowCasterMode: 0 - m_AreaSize: {x: 1, y: 1} - m_BounceIntensity: 1 - m_ColorTemperature: 6570 - m_UseColorTemperature: 0 - m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} - m_UseBoundingSphereOverride: 0 - m_UseViewFrustumForShadowCasterCull: 1 - m_ShadowRadius: 0 - m_ShadowAngle: 0 ---- !u!4 &1155269676 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1155269674} - m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} - m_LocalPosition: {x: 0, y: 3, z: 0} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 1 - m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} ---- !u!1 &1961294089 -GameObject: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - serializedVersion: 6 - m_Component: - - component: {fileID: 1961294092} - - component: {fileID: 1961294091} - - component: {fileID: 1961294090} - m_Layer: 0 - m_Name: Main Camera - m_TagString: MainCamera - m_Icon: {fileID: 0} - m_NavMeshLayer: 0 - m_StaticEditorFlags: 0 - m_IsActive: 1 ---- !u!81 &1961294090 -AudioListener: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1961294089} - m_Enabled: 1 ---- !u!20 &1961294091 -Camera: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1961294089} - m_Enabled: 1 - serializedVersion: 2 - m_ClearFlags: 1 - m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0} - m_projectionMatrixMode: 1 - m_GateFitMode: 2 - m_FOVAxisMode: 0 - m_SensorSize: {x: 36, y: 24} - m_LensShift: {x: 0, y: 0} - m_FocalLength: 50 - m_NormalizedViewPortRect: - serializedVersion: 2 - x: 0 - y: 0 - width: 1 - height: 1 - near clip plane: 0.3 - far clip plane: 1000 - field of view: 60 - orthographic: 0 - orthographic size: 5 - m_Depth: -1 - m_CullingMask: - serializedVersion: 2 - m_Bits: 4294967295 - m_RenderingPath: -1 - m_TargetTexture: {fileID: 0} - m_TargetDisplay: 0 - m_TargetEye: 3 - m_HDR: 1 - m_AllowMSAA: 1 - m_AllowDynamicResolution: 0 - m_ForceIntoRT: 0 - m_OcclusionCulling: 1 - m_StereoConvergence: 10 - m_StereoSeparation: 0.022 ---- !u!4 &1961294092 -Transform: - m_ObjectHideFlags: 0 - m_CorrespondingSourceObject: {fileID: 0} - m_PrefabInstance: {fileID: 0} - m_PrefabAsset: {fileID: 0} - m_GameObject: {fileID: 1961294089} - m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 0, y: 1, z: -10} - m_LocalScale: {x: 1, y: 1, z: 1} - m_Children: [] - m_Father: {fileID: 0} - m_RootOrder: 0 - m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} diff --git a/Assets/BasicExample/Scenes/HelloTesting.unity.meta b/Assets/BasicExample/Scenes/HelloTesting.unity.meta deleted file mode 100644 index 68c3990..0000000 --- a/Assets/BasicExample/Scenes/HelloTesting.unity.meta +++ /dev/null @@ -1,7 +0,0 @@ -fileFormatVersion: 2 -guid: 6c40ba2f8a021430aa36a5cd247cda1e -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Assets/BasicExample/Scripts/Runtime/Entities/CharacterStatus.cs b/Assets/BasicExample/Scripts/Runtime/Entities/CharacterStatus.cs index cae15d1..79fed50 100644 --- a/Assets/BasicExample/Scripts/Runtime/Entities/CharacterStatus.cs +++ b/Assets/BasicExample/Scripts/Runtime/Entities/CharacterStatus.cs @@ -17,24 +17,24 @@ public class CharacterStatus : IDestructible [field: SerializeField, Tooltip("属性")] private Element Element { get; set; } - [field: SerializeField, Tooltip("最大ヒットポイント")] - private int MaxHitPoint { get; set; } - [field: SerializeField, Tooltip("防御力(buff分を除く)")] private int Defense { get; set; } [field: SerializeField, Tooltip("攻撃力(buff分を除く)")] private int Attack { get; set; } - public int HitPoint { get; set; } + [field: SerializeField, Tooltip("最大ヒットポイント")] + private int MaxHitPoint { get; set; } + + internal int HitPoint { get; private set; } private HitPointGaugeSetting _bounds; - public CharacterStatus(Element element = Element.None, int hp = 0, int defense = 0, int attack = 0) + public CharacterStatus(Element element = Element.None, int defense = 0, int attack = 0, int hp = 0) { Element = element; - MaxHitPoint = hp; Defense = defense; Attack = attack; + MaxHitPoint = hp; HitPoint = hp; _bounds = ScriptableObject.CreateInstance(); } @@ -53,9 +53,9 @@ public bool IsDestroyed() } /// - public bool TakeDamage(Element element, int attackPower) + public bool TakeDamage(Element element, int attack) { - var attackPowerWithElement = (int)(attackPower * Element.GetDamageMultiplier(element)); + var attackPowerWithElement = (int)(attack * Element.GetDamageMultiplier(element)); var damage = attackPowerWithElement - Defense; if (damage <= 0) { diff --git a/Assets/BasicExample/Scripts/Runtime/Entities/Enemy.cs b/Assets/BasicExample/Scripts/Runtime/Entities/Enemy.cs index ebea3e0..9bcce78 100644 --- a/Assets/BasicExample/Scripts/Runtime/Entities/Enemy.cs +++ b/Assets/BasicExample/Scripts/Runtime/Entities/Enemy.cs @@ -22,6 +22,6 @@ public class Enemy : MonoBehaviour, IDestructible public bool IsDestroyed() => race.IsDestroyed(); /// - public bool TakeDamage(Element element, int attackPower) => race.TakeDamage(element, attackPower); + public bool TakeDamage(Element element, int attack) => race.TakeDamage(element, attack); } } diff --git a/Assets/BasicExample/Scripts/Runtime/Entities/Enums/Element.cs b/Assets/BasicExample/Scripts/Runtime/Entities/Enums/Element.cs index baa0144..aba775e 100644 --- a/Assets/BasicExample/Scripts/Runtime/Entities/Enums/Element.cs +++ b/Assets/BasicExample/Scripts/Runtime/Entities/Enums/Element.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. using System; @@ -8,17 +8,12 @@ namespace BasicExample.Entities.Enums /// /// 元素的な属性 /// - /// - /// 当たり障りなさそうな陰陽五行とします。種類は未来永劫バージョンアップしても増えません(フラグ - /// public enum Element { None, - Wood, Fire, Water, - Earth, - Metal, + Wood, } public static class ElementExtensions @@ -34,16 +29,12 @@ public static string GetName(this Element self) { case Element.None: return "無"; - case Element.Wood: - return "木"; case Element.Fire: return "火"; case Element.Water: return "水"; - case Element.Earth: - return "土"; - case Element.Metal: - return "金"; + case Element.Wood: + return "木"; default: throw new ArgumentException($"Unknown Element: {self.ToString()}"); } @@ -53,61 +44,26 @@ public static string GetName(this Element self) /// 属性攻撃を受けたときの被ダメージ倍率を返す ///
/// - /// 攻撃の属性 - /// + /// 攻撃側の属性 + /// 被ダメージ倍率 public static float GetDamageMultiplier(this Element self, Element attack) { - switch (self) + if (self == Element.Wood && attack == Element.Fire) { - case Element.Wood: - switch (attack) - { - case Element.Fire: - return 2.0f; - case Element.Water: - return 0.5f; - default: - return 1.0f; - } - case Element.Fire: - switch (attack) - { - case Element.Water: - return 2.0f; - case Element.Wood: - return 0.5f; - default: - return 1.0f; - } - case Element.Water: - switch (attack) - { - case Element.Wood: - return 2.0f; - case Element.Fire: - return 0.5f; - default: - return 1.0f; - } - case Element.Earth: - switch (attack) - { - case Element.Metal: - return 2.0f; - default: - return 0.5f; - } - case Element.Metal: - switch (attack) - { - case Element.Earth: - return 2.0f; - default: - return 0.5f; - } - default: - return 1.0f; + return 2.0f; + } + + if (self == Element.Fire && attack == Element.Water) + { + return 2.0f; } + + if (self == Element.Water && attack == Element.Wood) + { + return 2.0f; + } + + return 1.0f; } } } diff --git a/Assets/BasicExample/Scripts/Runtime/Entities/IDestructible.cs b/Assets/BasicExample/Scripts/Runtime/Entities/IDestructible.cs index 271b67c..8a8a0d6 100644 --- a/Assets/BasicExample/Scripts/Runtime/Entities/IDestructible.cs +++ b/Assets/BasicExample/Scripts/Runtime/Entities/IDestructible.cs @@ -27,8 +27,8 @@ public interface IDestructible /// 攻撃を与える /// /// 攻撃の属性 - /// 攻撃力 + /// 攻撃力 /// true: 1以上のダメージが入った - bool TakeDamage(Element element, int attackPower); + bool TakeDamage(Element element, int attack); } } diff --git a/Assets/BasicExample/Scripts/Runtime/Entities/Player.cs b/Assets/BasicExample/Scripts/Runtime/Entities/Player.cs index f103d47..00ddf67 100644 --- a/Assets/BasicExample/Scripts/Runtime/Entities/Player.cs +++ b/Assets/BasicExample/Scripts/Runtime/Entities/Player.cs @@ -18,6 +18,6 @@ public class Player : MonoBehaviour, IDestructible public bool IsDestroyed() => status.IsDestroyed(); /// - public bool TakeDamage(Element element, int attackPower) => status.TakeDamage(element, attackPower); + public bool TakeDamage(Element element, int attack) => status.TakeDamage(element, attack); } } diff --git a/Assets/BasicExample/Scripts/Runtime/Entities/ScriptableObjects/Race.cs b/Assets/BasicExample/Scripts/Runtime/Entities/ScriptableObjects/Race.cs index a81ca46..16d9125 100644 --- a/Assets/BasicExample/Scripts/Runtime/Entities/ScriptableObjects/Race.cs +++ b/Assets/BasicExample/Scripts/Runtime/Entities/ScriptableObjects/Race.cs @@ -38,6 +38,6 @@ public class Race : ScriptableObject, IDestructible public bool IsDestroyed() => status.IsDestroyed(); /// - public bool TakeDamage(Element element, int attackPower) => status.TakeDamage(element, attackPower); + public bool TakeDamage(Element element, int attack) => status.TakeDamage(element, attack); } } diff --git a/Assets/BasicExample/Tests/Editor/AssetValidators/LevelValidator.cs b/Assets/BasicExample/Tests/Editor/AssetValidators/LevelValidator.cs deleted file mode 100644 index d76d689..0000000 --- a/Assets/BasicExample/Tests/Editor/AssetValidators/LevelValidator.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2021 Koji Hasegawa. -// This software is released under the MIT License. - -using System.Collections.Generic; -using System.Linq; -using BasicExample.Level; -using NUnit.Framework; -using UnityEditor; -using UnityEditor.SceneManagement; -using UnityEngine; - -namespace BasicExample.Editor.AssetValidators -{ - /// - /// Scenes/Levels/下のすべてのSceneに対して、次のコンポーネントが設置されていることを検証する - /// - - /// - - /// - /// - /// の応用例 - /// - public class LevelValidator - { - private static IEnumerable Levels => AssetDatabase - .FindAssets("t:SceneAsset", new [] { "Assets/BasicExample/Scenes/Levels" }) - .Select(AssetDatabase.GUIDToAssetPath); - - [TestCaseSource(nameof(Levels))] - public void Levels下のSceneにSpawnPointが設置されていること(string path) - { - EditorSceneManager.OpenScene(path); - var spawnPoints = Object.FindObjectsOfType(); - - Assert.That(spawnPoints.Any, Is.True); - } - - [TestCaseSource(nameof(Levels))] - public void Levels下のSceneにExitPointが設置されていること(string path) - { - EditorSceneManager.OpenScene(path); - var exitPoints = Object.FindObjectsOfType(); - - Assert.That(exitPoints.Length, Is.GreaterThanOrEqualTo(1), "ExitPointは1つ以上設定されている"); - - foreach (var exitPoint in exitPoints) - { - var obj = exitPoint.gameObject; - var colliders = obj.GetComponents(); - Assert.That(colliders.Length, Is.GreaterThanOrEqualTo(1), $"{obj.name}にはコライダが設定されている"); - } - } - } -} diff --git a/Assets/BasicExample/Tests/Editor/BasicExample.Editor.Tests.asmdef b/Assets/BasicExample/Tests/Editor/BasicExample.Editor.Tests.asmdef index cfb51bf..625f125 100644 --- a/Assets/BasicExample/Tests/Editor/BasicExample.Editor.Tests.asmdef +++ b/Assets/BasicExample/Tests/Editor/BasicExample.Editor.Tests.asmdef @@ -5,7 +5,8 @@ "UnityEngine.TestRunner", "UnityEditor.TestRunner", "BasicExample.Editor", - "BasicExample" + "BasicExample", + "BasicExample.Tests" ], "includePlatforms": [ "Editor" diff --git a/Assets/BasicExample/Tests/Editor/AssetValidators.meta b/Assets/BasicExample/Tests/Editor/Validators.meta similarity index 100% rename from Assets/BasicExample/Tests/Editor/AssetValidators.meta rename to Assets/BasicExample/Tests/Editor/Validators.meta diff --git a/Assets/BasicExample/Tests/Editor/Validators/LevelValidator.cs b/Assets/BasicExample/Tests/Editor/Validators/LevelValidator.cs new file mode 100644 index 0000000..b1831e0 --- /dev/null +++ b/Assets/BasicExample/Tests/Editor/Validators/LevelValidator.cs @@ -0,0 +1,58 @@ +// Copyright (c) 2021-2025 Koji Hasegawa. +// This software is released under the MIT License. + +using System.Collections.Generic; +using System.IO; +using System.Linq; +using BasicExample.Level; +using NUnit.Framework; +using UnityEditor; +using UnityEditor.SceneManagement; +using UnityEngine; + +namespace BasicExample.Editor.Validators +{ + /// + /// Scenes/Levels/ 下のすべての Scene に対して、次のコンポーネントが設置されていることを検証する + /// + /// + /// + /// + /// + /// + /// の使用例 + /// + [TestFixture] + public class LevelValidator + { + private static IEnumerable Levels => AssetDatabase + .FindAssets("t:SceneAsset", new[] { "Assets/BasicExample/Scenes/Levels" }) + .Select(AssetDatabase.GUIDToAssetPath) + .Select(path => new TestCaseData(path).SetName(Path.GetFileName(path))); + + [TestCaseSource(nameof(Levels))] + public void Levels下のSceneにSpawnPointが1つ設置されていること(string path) + { + EditorSceneManager.OpenScene(path); + var spawnPoints = Object.FindObjectsOfType(); + + Assert.That(spawnPoints, Has.Length.EqualTo(1)); + } + + [TestCaseSource(nameof(Levels))] + public void Levels下のSceneにExitPointが設置されていること(string path) + { + EditorSceneManager.OpenScene(path); + var exitPoints = Object.FindObjectsOfType(); + + Assert.That(exitPoints, Is.Not.Empty, "ExitPointは1つ以上設定されている"); + + foreach (var exitPoint in exitPoints) + { + var obj = exitPoint.gameObject; + var colliders = obj.GetComponents(); + Assert.That(colliders, Is.Not.Empty, $"{obj.name}にはコライダが設定されている"); + } + } + } +} diff --git a/Assets/BasicExample/Tests/Editor/AssetValidators/LevelValidator.cs.meta b/Assets/BasicExample/Tests/Editor/Validators/LevelValidator.cs.meta similarity index 100% rename from Assets/BasicExample/Tests/Editor/AssetValidators/LevelValidator.cs.meta rename to Assets/BasicExample/Tests/Editor/Validators/LevelValidator.cs.meta diff --git a/Assets/BasicExample/Tests/Editor/Validators/PrefabValidator.cs b/Assets/BasicExample/Tests/Editor/Validators/PrefabValidator.cs new file mode 100644 index 0000000..5c4eba6 --- /dev/null +++ b/Assets/BasicExample/Tests/Editor/Validators/PrefabValidator.cs @@ -0,0 +1,48 @@ +// Copyright (c) 2021-2025 Koji Hasegawa. +// This software is released under the MIT License. + +using System.Collections.Generic; +using System.IO; +using System.Linq; +using NUnit.Framework; +using UnityEditor; +using UnityEngine; + +namespace BasicExample.Editor.Validators +{ + /// + /// Assets/ 下のすべての Prefab に対して、missing script がないことを検証する. + /// + /// + /// の使用例 + /// + [TestFixture] + public class PrefabValidator + { + private static IEnumerable Prefabs => AssetDatabase + .FindAssets("t:Prefab", new string[] { "Assets/" }) + .Select(AssetDatabase.GUIDToAssetPath) + .Select(path => new TestCaseData(path).SetName(Path.GetFileName(path))); + + private static void AssertMissingScriptRecursive(GameObject gameObject) + { + var components = gameObject.GetComponents(); + foreach (var component in components) + { + Assert.That(component, Is.Not.Null, $"Component in {gameObject.name}"); + } + + foreach (Transform child in gameObject.transform) + { + AssertMissingScriptRecursive(child.gameObject); + } + } + + [TestCaseSource(nameof(Prefabs))] + public void MissingScriptがないこと(string path) + { + var root = AssetDatabase.LoadAssetAtPath(path); + AssertMissingScriptRecursive(root); + } + } +} diff --git a/Assets/BasicExample/Tests/Editor/Validators/PrefabValidator.cs.meta b/Assets/BasicExample/Tests/Editor/Validators/PrefabValidator.cs.meta new file mode 100644 index 0000000..5ce0e64 --- /dev/null +++ b/Assets/BasicExample/Tests/Editor/Validators/PrefabValidator.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: bf0c636a5e5b4c5cb37c516c23a59ce2 +timeCreated: 1758386625 \ No newline at end of file diff --git a/Assets/BasicExample/Tests/Editor/AssetValidators/RaceValidator.cs b/Assets/BasicExample/Tests/Editor/Validators/RaceValidator.cs similarity index 80% rename from Assets/BasicExample/Tests/Editor/AssetValidators/RaceValidator.cs rename to Assets/BasicExample/Tests/Editor/Validators/RaceValidator.cs index 77e9915..be8c9c7 100644 --- a/Assets/BasicExample/Tests/Editor/AssetValidators/RaceValidator.cs +++ b/Assets/BasicExample/Tests/Editor/Validators/RaceValidator.cs @@ -11,19 +11,19 @@ using UnityEditor; using Object = UnityEngine.Object; -namespace BasicExample.Editor.AssetValidators +namespace BasicExample.Editor.Validators { /// - /// ScriptableObjects/Races/下のすべてのSOに対して、フィールドの設定漏れがないことを検証する + /// ScriptableObjects/Races/ 下のすべての ScriptableObject に対して、フィールドの設定漏れがないことを検証する. /// /// - /// の応用例として書いたものの、フィールドは素直にRace型を使うほうがよさそう + /// の応用例として書いたものの、フィールドは素直にRace型を使うほうがよさそう /// public class RaceValidator { // Race型のScriptableObjectを列挙 private static IEnumerable RacePaths => AssetDatabase - .FindAssets("t:Race", new [] { "Assets/BasicExample/ScriptableObjects/Races" }) + .FindAssets("t:Race", new[] { "Assets/BasicExample/ScriptableObjects/Races" }) .Select(AssetDatabase.GUIDToAssetPath); // Race型のフィールドを列挙 diff --git a/Assets/BasicExample/Tests/Editor/AssetValidators/RaceValidator.cs.meta b/Assets/BasicExample/Tests/Editor/Validators/RaceValidator.cs.meta similarity index 100% rename from Assets/BasicExample/Tests/Editor/AssetValidators/RaceValidator.cs.meta rename to Assets/BasicExample/Tests/Editor/Validators/RaceValidator.cs.meta diff --git a/Assets/BasicExample/Tests/Editor/Validators/SceneValidator.cs b/Assets/BasicExample/Tests/Editor/Validators/SceneValidator.cs new file mode 100644 index 0000000..07fc90e --- /dev/null +++ b/Assets/BasicExample/Tests/Editor/Validators/SceneValidator.cs @@ -0,0 +1,52 @@ +// Copyright (c) 2021-2025 Koji Hasegawa. +// This software is released under the MIT License. + +using System.Collections.Generic; +using System.IO; +using System.Linq; +using NUnit.Framework; +using UnityEditor; +using UnityEditor.SceneManagement; +using UnityEngine; + +namespace BasicExample.Editor.Validators +{ + /// + /// Assets/ 下のすべての Scene に対して、missing script がないことを検証する. + /// + /// + /// の使用例 + /// + [TestFixture] + public class SceneValidator + { + private static IEnumerable Scenes => AssetDatabase + .FindAssets("t:SceneAsset", new string[] { "Assets/" }) + .Select(AssetDatabase.GUIDToAssetPath) + .Select(path => new TestCaseData(path).SetName(Path.GetFileName(path))); + + private static void AssertMissingScriptRecursive(GameObject gameObject) + { + var components = gameObject.GetComponents(); + foreach (var component in components) + { + Assert.That(component, Is.Not.Null, $"Component in {gameObject.name}"); + } + + foreach (Transform child in gameObject.transform) + { + AssertMissingScriptRecursive(child.gameObject); + } + } + + [TestCaseSource(nameof(Scenes))] + public void MissingScriptがないこと(string path) + { + var scene = EditorSceneManager.OpenScene(path); + foreach (var root in scene.GetRootGameObjects()) + { + AssertMissingScriptRecursive(root); + } + } + } +} diff --git a/Assets/BasicExample/Tests/Editor/Validators/SceneValidator.cs.meta b/Assets/BasicExample/Tests/Editor/Validators/SceneValidator.cs.meta new file mode 100644 index 0000000..5271dda --- /dev/null +++ b/Assets/BasicExample/Tests/Editor/Validators/SceneValidator.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 54b8dccf49f1c435aa18ab1c2cfe1549 \ No newline at end of file diff --git a/Assets/BasicExample/Tests/Runtime/BasicExample.Tests.asmdef b/Assets/BasicExample/Tests/Runtime/BasicExample.Tests.asmdef index 4c8f656..8d5a9f0 100644 --- a/Assets/BasicExample/Tests/Runtime/BasicExample.Tests.asmdef +++ b/Assets/BasicExample/Tests/Runtime/BasicExample.Tests.asmdef @@ -4,6 +4,8 @@ "references": [ "UnityEngine.TestRunner", "UnityEditor.TestRunner", + "NUnit.Analyzers_Unity", + "TestHelper", "BasicExample" ], "includePlatforms": [], diff --git a/Assets/BasicExample/Tests/Runtime/Entities/CharacterStatusTest.cs b/Assets/BasicExample/Tests/Runtime/Entities/CharacterStatusTest.cs index c76ee4a..68a2ac1 100644 --- a/Assets/BasicExample/Tests/Runtime/Entities/CharacterStatusTest.cs +++ b/Assets/BasicExample/Tests/Runtime/Entities/CharacterStatusTest.cs @@ -13,67 +13,81 @@ public class CharacterStatusTest public void IsDestroyed_まだ生きている() { var sut = new CharacterStatus(hp: 1); + Assume.That(sut.HitPoint, Is.EqualTo(1)); Assert.That(sut.IsDestroyed(), Is.False); - Assert.That(sut.HitPoint, Is.EqualTo(1)); } [Test] public void IsDestroyed_もう死んでいる() { - var sut = new CharacterStatus(hp: 1); - sut.TakeDamage(Element.None, 1); + var sut = new CharacterStatus(hp: 0); + Assume.That(sut.HitPoint, Is.EqualTo(0)); Assert.That(sut.IsDestroyed(), Is.True); } [Test] - public void TakeDamage_防御力5に対して攻撃力1_被ダメージなし() + public void TakeDamage_防御力3に対して攻撃力1_ダメージなし() { - var sut = new CharacterStatus(element: Element.None, hp: 2, defense: 5); - var damaged = sut.TakeDamage(Element.None, 1); + // Setup + var sut = new CharacterStatus(Element.None, defense: 3); + + // Exercise + var damage = sut.TakeDamage(Element.None, attack: 1); - Assert.That(damaged, Is.False); + // Verify + Assert.That(damage, Is.False); } [Test] - public void TakeDamage_防御力5に対して攻撃力1_HP減少なし() + public void TakeDamage_防御力3に対して攻撃力1_HP減少なし() { - var sut = new CharacterStatus(element: Element.None, hp: 2, defense: 5); - sut.TakeDamage(Element.None, 1); + // Setup + var beforeHp = 100; + var sut = new CharacterStatus(Element.None, defense: 3, hp: beforeHp); + + // Exercise + sut.TakeDamage(Element.None, attack: 1); - Assert.That(sut.HitPoint, Is.EqualTo(2)); + // Verify + var deltaHp = sut.HitPoint - beforeHp; + Assert.That(deltaHp, Is.EqualTo(0)); } [Test] - public void TakeDamage_防御力0に対して攻撃力1_被ダメージあり() + public void TakeDamage_防御力0に対して攻撃力1_ダメージあり() { - var sut = new CharacterStatus(element: Element.None, hp: 2, defense: 0); - var damaged = sut.TakeDamage(Element.None, 1); + var sut = new CharacterStatus(Element.None, defense: 0); - Assert.That(damaged, Is.True); + var damage = sut.TakeDamage(Element.None, attack: 1); + + Assert.That(damage, Is.True); } [Test] public void TakeDamage_防御力2に対して攻撃力3_HPが1減少() { - var sut = new CharacterStatus(element: Element.None, hp: 5, defense: 2); - sut.TakeDamage(element: Element.None, attackPower: 3); + var beforeHp = 100; + var sut = new CharacterStatus(Element.None, defense: 2, hp: beforeHp); + + sut.TakeDamage(Element.None, attack: 3); - var actual = sut.HitPoint - 5; // delta HP - Assert.That(actual, Is.EqualTo(-1)); + var deltaHp = sut.HitPoint - beforeHp; + Assert.That(deltaHp, Is.EqualTo(-1)); } [TestCase(2, 3, -1)] [TestCase(5, 7, -2)] public void TakeDamage_防御力より攻撃力が大きい_HPが差分だけ減少(int defence, int attackPower, int expected) { - var beforeHp = 5; - var sut = new CharacterStatus(element: Element.None, hp: beforeHp, defense: defence); - sut.TakeDamage(element: Element.None, attackPower: attackPower); + var beforeHp = 100; + var sut = new CharacterStatus(Element.None, defense: defence, hp: beforeHp); + + sut.TakeDamage(Element.None, attack: attackPower); - var actual = sut.HitPoint - beforeHp; // delta HP - Assert.That(actual, Is.EqualTo(expected)); + var deltaHp = sut.HitPoint - beforeHp; + Assert.That(deltaHp, Is.EqualTo(expected)); } } } diff --git a/Assets/BasicExample/Tests/Runtime/Entities/Enums/ElementTest.cs b/Assets/BasicExample/Tests/Runtime/Entities/Enums/ElementTest.cs index abe16b3..2ed5c88 100644 --- a/Assets/BasicExample/Tests/Runtime/Entities/Enums/ElementTest.cs +++ b/Assets/BasicExample/Tests/Runtime/Entities/Enums/ElementTest.cs @@ -18,45 +18,17 @@ public class ElementTest [TestCase(Element.Wood, Element.Fire)] [TestCase(Element.Fire, Element.Water)] [TestCase(Element.Water, Element.Wood)] - [TestCase(Element.Earth, Element.Metal)] - [TestCase(Element.Metal, Element.Earth)] public void GetDamageMultiplier_弱点属性からの攻撃_ダメージ2倍(Element defence, Element attack) { var actual = defence.GetDamageMultiplier(attack); Assert.That(actual, Is.EqualTo(2.0f)); } - [TestCase(Element.Wood, Element.Water)] - [TestCase(Element.Fire, Element.Wood)] - [TestCase(Element.Water, Element.Fire)] - public void GetDamageMultiplier_得意属性からの攻撃_ダメージ半減(Element defence, Element attack) - { - var actual = defence.GetDamageMultiplier(attack); - Assert.That(actual, Is.EqualTo(0.5f)); - } - - [Test] - [ParametrizedIgnore(Element.Earth, Element.Metal)] - [ParametrizedIgnore(Element.Metal, Element.Earth)] - public void GetDamageMultiplier_土金の得意属性_ダメージ半減( - [Values(Element.Earth, Element.Metal)] Element defence, - [Values] Element attack) - { - var actual = defence.GetDamageMultiplier(attack); - Assert.That(actual, Is.EqualTo(0.5f)); - } - [Test] [ParametrizedIgnore(Element.Wood, Element.Fire)] [ParametrizedIgnore(Element.Fire, Element.Water)] [ParametrizedIgnore(Element.Water, Element.Wood)] - [ParametrizedIgnore(Element.Wood, Element.Water)] - [ParametrizedIgnore(Element.Fire, Element.Wood)] - [ParametrizedIgnore(Element.Water, Element.Fire)] - public void GetDamageMultiplier_相性なし_ダメージは等倍( - [Values(Element.None, Element.Wood, Element.Fire, Element.Water)] - Element defence, - [Values] Element attack) + public void GetDamageMultiplier_相性なし_ダメージは等倍([Values] Element defence, [Values] Element attack) { var actual = defence.GetDamageMultiplier(attack); Assert.That(actual, Is.EqualTo(1.0f)); diff --git a/Assets/BasicExample/Tests/Runtime/Entities/PassiveEffectTest.cs b/Assets/BasicExample/Tests/Runtime/Entities/PassiveEffectTest.cs index 9b1d82a..74ec1d2 100644 --- a/Assets/BasicExample/Tests/Runtime/Entities/PassiveEffectTest.cs +++ b/Assets/BasicExample/Tests/Runtime/Entities/PassiveEffectTest.cs @@ -1,150 +1,143 @@ -// Copyright (c) 2021-2022 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. using System.Collections; using BasicExample.Entities.Enums; using NUnit.Framework; +using TestHelper.Attributes; using UnityEngine; using UnityEngine.TestTools; -using UnityEngine.TestTools.Utils; namespace BasicExample.Entities { [TestFixture] public class PassiveEffectTest { + private static PassiveEffect CreatePassiveEffect(bool buff = false, bool debuff = false) + { + var passiveEffect = new GameObject().AddComponent(); + + if (buff) + { + passiveEffect.Buff(); + } + + if (debuff) + { + passiveEffect.DeBuff(); + } + + return passiveEffect; + } + [TestFixture] public class 状態遷移テスト { - private static readonly FloatEqualityComparer s_expireTimeComparer = new FloatEqualityComparer(0.1f); - [TestFixture] public class 通常状態からの遷移 { - private PassiveEffect _sut; - - [SetUp] - public void SetUp() - { - _sut = new GameObject().AddComponent(); // 通常状態 - } - [Test] public void デバフ_弱体状態になること() { - _sut.DeBuff(); - Assert.That(_sut.State(), Is.EqualTo(PassiveEffectState.Weakening)); + var sut = CreatePassiveEffect(); + sut.DeBuff(); + Assert.That(sut.State(), Is.EqualTo(PassiveEffectState.Weakening)); } [Test] public void バフ_強化状態になること() { - _sut.Buff(); - Assert.That(_sut.State(), Is.EqualTo(PassiveEffectState.Strengthening)); + var sut = CreatePassiveEffect(); + sut.Buff(); + Assert.That(sut.State(), Is.EqualTo(PassiveEffectState.Strengthening)); } } [TestFixture] public class 弱体状態からの遷移 { - private PassiveEffect _sut; - - [SetUp] - public void SetUp() - { - _sut = new GameObject().AddComponent(); - _sut.DeBuff(); // 弱体状態 - } - - [TearDown] - public void TearDown() + [Test] + public void バフ_通常状態になること() { - Time.timeScale = 1.0f; + var sut = CreatePassiveEffect(debuff: true); + sut.Buff(); + Assert.That(sut.State(), Is.EqualTo(PassiveEffectState.Normal)); } [Test] public void デバフ_弱体状態が維持されること() { - _sut.DeBuff(); - Assert.That(_sut.State(), Is.EqualTo(PassiveEffectState.Weakening)); + var sut = CreatePassiveEffect(debuff: true); + sut.DeBuff(); + Assert.That(sut.State(), Is.EqualTo(PassiveEffectState.Weakening)); } [UnityTest] + [TimeScale(10.0f)] public IEnumerator デバフ_持続時間が30秒にリセットされること() { - Time.timeScale = 100.0f; - yield return new WaitForSeconds(10f); + var sut = CreatePassiveEffect(debuff: true); + yield return new WaitForSeconds(5.0f); + Assume.That(sut.State(), Is.EqualTo(PassiveEffectState.Weakening)); + Assume.That(sut.PassiveEffectExpireTime(), Is.EqualTo(25.0f).Within(0.1f)); - _sut.DeBuff(); - Assert.That(_sut.State(), Is.EqualTo(PassiveEffectState.Weakening)); - Assert.That(_sut.PassiveEffectExpireTime(), Is.EqualTo(30f).Using(s_expireTimeComparer)); - } + sut.DeBuff(); - [Test] - public void バフ_通常状態になること() - { - _sut.Buff(); - Assert.That(_sut.State(), Is.EqualTo(PassiveEffectState.Normal)); + Assert.That(sut.State(), Is.EqualTo(PassiveEffectState.Weakening)); + Assert.That(sut.PassiveEffectExpireTime(), Is.EqualTo(30.0f).Within(0.1f)); } [UnityTest] + [TimeScale(10.0f)] public IEnumerator 時間切れ_通常状態になること() { - Time.timeScale = 100.0f; - yield return new WaitForSeconds(30f); - Assert.That(_sut.State(), Is.EqualTo(PassiveEffectState.Normal)); + var sut = CreatePassiveEffect(debuff: true); + yield return new WaitForSeconds(30.2f); + Assert.That(sut.State(), Is.EqualTo(PassiveEffectState.Normal)); } } [TestFixture] public class 強化状態からの遷移 { - private PassiveEffect _sut; - - [SetUp] - public void SetUp() - { - _sut = new GameObject().AddComponent(); - _sut.Buff(); // 強化状態 - } - - [TearDown] - public void TearDown() - { - Time.timeScale = 1.0f; - } - [Test] public void デバフ_通常状態になること() { - _sut.DeBuff(); - Assert.That(_sut.State(), Is.EqualTo(PassiveEffectState.Normal)); + var sut = CreatePassiveEffect(buff: true); + sut.DeBuff(); + Assert.That(sut.State(), Is.EqualTo(PassiveEffectState.Normal)); } [Test] public void バフ_強化状態が維持されること() { - _sut.Buff(); - Assert.That(_sut.State(), Is.EqualTo(PassiveEffectState.Strengthening)); + var sut = CreatePassiveEffect(buff: true); + sut.Buff(); + Assert.That(sut.State(), Is.EqualTo(PassiveEffectState.Strengthening)); } [UnityTest] + [TimeScale(10.0f)] public IEnumerator バフ_持続時間が30秒にリセットされること() { - Time.timeScale = 100.0f; - yield return new WaitForSeconds(10f); + var sut = CreatePassiveEffect(buff: true); + yield return new WaitForSeconds(5.0f); + Assume.That(sut.State(), Is.EqualTo(PassiveEffectState.Strengthening)); + Assume.That(sut.PassiveEffectExpireTime(), Is.EqualTo(25.0f).Within(0.2f)); + + sut.Buff(); - _sut.Buff(); - Assert.That(_sut.State(), Is.EqualTo(PassiveEffectState.Strengthening)); - Assert.That(_sut.PassiveEffectExpireTime(), Is.EqualTo(30f).Using(s_expireTimeComparer)); + Assert.That(sut.State(), Is.EqualTo(PassiveEffectState.Strengthening)); + Assert.That(sut.PassiveEffectExpireTime(), Is.EqualTo(30.0f).Within(0.1f)); } [UnityTest] + [TimeScale(10.0f)] public IEnumerator 時間切れ_通常状態になること() { - Time.timeScale = 100.0f; - yield return new WaitForSeconds(30f); - Assert.That(_sut.State(), Is.EqualTo(PassiveEffectState.Normal)); + var sut = CreatePassiveEffect(buff: true); + yield return new WaitForSeconds(30.2f); + Assert.That(sut.State(), Is.EqualTo(PassiveEffectState.Normal)); } } } diff --git a/Assets/InputSystemExample/Tests/Runtime/MonkeyTest.cs b/Assets/InputSystemExample/Tests/Runtime/MonkeyTest.cs index 3149f96..8e52372 100644 --- a/Assets/InputSystemExample/Tests/Runtime/MonkeyTest.cs +++ b/Assets/InputSystemExample/Tests/Runtime/MonkeyTest.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021-2023 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. using System.Diagnostics.CodeAnalysis; @@ -45,7 +45,7 @@ public void TearDown() [Test] public async Task MonkeyTesting() { - var random = new RandomImpl(); // 擬似乱数生成器 + var random = new RandomWrapper(); // 擬似乱数生成器 Debug.Log($"Random that monkey uses: {random}"); // シード値をログ出力(再現可能にするため) await SceneManager.LoadSceneAsync("InputSystemExample"); @@ -57,8 +57,8 @@ public async Task MonkeyTesting() using (var tokenSource = new CancellationTokenSource()) { - PressKeys(new RandomImpl(random.Next()), tokenSource.Token).Forget(); - MoveMouse(new RandomImpl(random.Next()), tokenSource.Token).Forget(); + PressKeys(new RandomWrapper(random.Next()), tokenSource.Token).Forget(); + MoveMouse(new RandomWrapper(random.Next()), tokenSource.Token).Forget(); var expireTime = Time.time + 10.0f; // 10秒間動作させる(3分以上にする場合はTimeout属性でタイムアウト時間を延長) while (Time.time < expireTime) @@ -117,7 +117,7 @@ private async UniTask MoveMouse(IRandom random, CancellationToken token) while (true) { var mouseDelta = random.NextNormalizedVector2(); // マウスの移動量を抽選 - _input.Set(mouse.delta, mouseDelta); // マウス移動 + _input.Set(mouse.delta, mouseDelta); // マウス移動 await UniTask.NextFrame(cancellationToken: token); } diff --git a/Assets/TestDoubleExample/Scripts/Runtime/Janken/IRandom.cs b/Assets/TestDoubleExample/Scripts/Runtime/Janken/IRandom.cs index eeff491..d40cea7 100644 --- a/Assets/TestDoubleExample/Scripts/Runtime/Janken/IRandom.cs +++ b/Assets/TestDoubleExample/Scripts/Runtime/Janken/IRandom.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021-2022 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. namespace TestDoubleExample.Janken @@ -9,11 +9,8 @@ namespace TestDoubleExample.Janken public interface IRandom { /// - /// 指定範囲内のランダムな整数を返す + /// 指定された範囲のランダムな浮動小数点数を返す /// - /// 下限値 - /// 上限値(結果に含まない) - /// - int Range(int minValue, int maxValue); + float Range(float minInclusive, float maxInclusive); } } diff --git a/Assets/TestDoubleExample/Scripts/Runtime/Janken/Janken.cs b/Assets/TestDoubleExample/Scripts/Runtime/Janken/Janken.cs index bc5f2dc..021043d 100644 --- a/Assets/TestDoubleExample/Scripts/Runtime/Janken/Janken.cs +++ b/Assets/TestDoubleExample/Scripts/Runtime/Janken/Janken.cs @@ -1,4 +1,4 @@ -// Copyright (c) 2021-2022 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. namespace TestDoubleExample.Janken @@ -8,24 +8,35 @@ namespace TestDoubleExample.Janken /// public class Janken { - private readonly IRandom _random; + private readonly IRandom _random; // 依存オブジェクト /// - /// 擬似乱数生成器をコンストラクタインジェクションで受け取ります + /// 擬似乱数生成器をコンストラクタインジェクションで受け取るコンストラクタ /// /// 擬似乱数生成器 - public Janken(IRandom random) + public Janken(IRandom random = null) { - _random = random; + _random = random ?? new UnityEngineRandom(); } /// /// じゃんけんぽん /// - /// ランダムな手(本当にランダムかどうかは_randomに依存) + /// ランダムな手(本当にランダムかどうかは _random に依存) public Hand Pon() { - return (Hand)_random.Range(0, 3); + var value = _random.Range(0.0f, 1.0f); // 0.0〜1.0のランダムな値が返る + if (value < 0.33f) + { + return Hand.Rock; + } + + if (value < 0.66f) + { + return Hand.Scissors; + } + + return Hand.Paper; } } } diff --git a/Assets/TestDoubleExample/Scripts/Runtime/Janken/NondeterministicJanken.cs b/Assets/TestDoubleExample/Scripts/Runtime/Janken/NondeterministicJanken.cs deleted file mode 100644 index ada154e..0000000 --- a/Assets/TestDoubleExample/Scripts/Runtime/Janken/NondeterministicJanken.cs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright (c) 2021-2022 Koji Hasegawa. -// This software is released under the MIT License. - -namespace TestDoubleExample.Janken -{ - /// - /// 非決定的なテストしかできないじゃんけんロジック - /// - public class NondeterministicJanken - { - /// - /// じゃんけんぽん - /// - /// ランダムな手 - public Hand Pon() - { - return (Hand)UnityEngine.Random.Range(0, 3); - } - } -} diff --git a/Assets/TestDoubleExample/Scripts/Runtime/Janken/NondeterministicJanken.cs.meta b/Assets/TestDoubleExample/Scripts/Runtime/Janken/NondeterministicJanken.cs.meta deleted file mode 100644 index d958038..0000000 --- a/Assets/TestDoubleExample/Scripts/Runtime/Janken/NondeterministicJanken.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 6899f2ce4ca642b8aa5a6651a4e38f3d -timeCreated: 1659195902 \ No newline at end of file diff --git a/Assets/TestDoubleExample/Scripts/Runtime/Janken/Random.cs b/Assets/TestDoubleExample/Scripts/Runtime/Janken/Random.cs deleted file mode 100644 index 4db9d45..0000000 --- a/Assets/TestDoubleExample/Scripts/Runtime/Janken/Random.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2021-2022 Koji Hasegawa. -// This software is released under the MIT License. - -namespace TestDoubleExample.Janken -{ - /// - /// の実装 - /// を使用 - /// - public class Random : IRandom - { - /// - public int Range(int minValue, int maxValue) - { - return UnityEngine.Random.Range(minValue, maxValue); - } - } -} diff --git a/Assets/TestDoubleExample/Scripts/Runtime/Janken/UnityEngineRandom.cs b/Assets/TestDoubleExample/Scripts/Runtime/Janken/UnityEngineRandom.cs new file mode 100644 index 0000000..51062a4 --- /dev/null +++ b/Assets/TestDoubleExample/Scripts/Runtime/Janken/UnityEngineRandom.cs @@ -0,0 +1,19 @@ +// Copyright (c) 2021-2025 Koji Hasegawa. +// This software is released under the MIT License. + +using UnityEngine; + +namespace TestDoubleExample.Janken +{ + /// + /// を使用する 実装 + /// + public class UnityEngineRandom : IRandom + { + /// + public float Range(float minInclusive, float maxInclusive) + { + return Random.Range(minInclusive, maxInclusive); + } + } +} diff --git a/Assets/TestDoubleExample/Scripts/Runtime/Janken/Random.cs.meta b/Assets/TestDoubleExample/Scripts/Runtime/Janken/UnityEngineRandom.cs.meta similarity index 100% rename from Assets/TestDoubleExample/Scripts/Runtime/Janken/Random.cs.meta rename to Assets/TestDoubleExample/Scripts/Runtime/Janken/UnityEngineRandom.cs.meta diff --git a/Assets/TestDoubleExample/Scripts/Runtime/Janken/VRandom.cs b/Assets/TestDoubleExample/Scripts/Runtime/Janken/VRandom.cs deleted file mode 100644 index a6a961e..0000000 --- a/Assets/TestDoubleExample/Scripts/Runtime/Janken/VRandom.cs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) 2021-2022 Koji Hasegawa. -// This software is released under the MIT License. - -namespace TestDoubleExample.Janken -{ - /// - /// の実装 - /// はvirtualメソッド - /// - public class VRandom : IRandom - { - /// - public virtual int Range(int minValue, int maxValue) - { - return UnityEngine.Random.Range(minValue, maxValue); - } - } -} diff --git a/Assets/TestDoubleExample/Scripts/Runtime/Janken/VRandom.cs.meta b/Assets/TestDoubleExample/Scripts/Runtime/Janken/VRandom.cs.meta deleted file mode 100644 index 45c0cf6..0000000 --- a/Assets/TestDoubleExample/Scripts/Runtime/Janken/VRandom.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 387fc1308ca548adb5d4e17b3c33ee58 -timeCreated: 1659364930 \ No newline at end of file diff --git a/Assets/TestDoubleExample/Tests/Runtime/Janken/JankenTest.cs b/Assets/TestDoubleExample/Tests/Runtime/Janken/JankenTest.cs index 27b2323..21a499a 100644 --- a/Assets/TestDoubleExample/Tests/Runtime/Janken/JankenTest.cs +++ b/Assets/TestDoubleExample/Tests/Runtime/Janken/JankenTest.cs @@ -1,7 +1,8 @@ -// Copyright (c) 2021-2022 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. using NUnit.Framework; +using TestDoubleExample.TestDoubles; namespace TestDoubleExample.Janken { @@ -11,74 +12,44 @@ namespace TestDoubleExample.Janken public class JankenTest { [Test] - public void Pon_テストスタブを注入して間接入力を与えることによる決定的なテスト() + public void Pon_PRNGが0を返すとき_ぐーを返す() { - var stub = new StubRandom(2); // 常に2を返すテストスタブを生成 - var sut = new Janken(stub); // テスト対象にスタブを注入 + var stub = new StubRandom(0.0f); // 常に0を返すテストスタブを生成 + var sut = new Janken(stub); // テスト対象にスタブを注入 var actual = sut.Pon(); - Assert.That(actual, Is.EqualTo(Hand.Paper)); // 結果は常に「ぱー」 + Assert.That(actual, Is.EqualTo(Hand.Rock)); // 結果は常に「ぐー」 } - /// - /// テストスタブ実装 - /// - private class StubRandom : IRandom + [Test] + public void Pon_PRNGがdot5を返すとき_ちょきを返す() { - private readonly int _response; - - public StubRandom(int response) - { - _response = response; - } + var stub = new StubRandom(0.5f); // 常に0.5を返すテストスタブを生成 + var sut = new Janken(stub); // テスト対象にスタブを注入 + var actual = sut.Pon(); - /// - /// 固定値を返すスタブメソッド - /// - /// 常にコンストラクタで指定された固定値を返す - public int Range(int minValue, int maxValue) - { - return _response; // 常にコンストラクタで指定された固定値を返す - } + Assert.That(actual, Is.EqualTo(Hand.Scissors)); // 結果は常に「ちょき」 } [Test] - public void Pon_テストスパイを注入することによる間接出力のテスト() + public void Pon_PRNGが1を返すとき_ぱーを返す() { - var spy = new SpyRandom(); // テストスパイを生成 - var sut = new Janken(spy); // テスト対象にスパイを注入 - sut.Pon(); + var stub = new StubRandom(1.0f); // 常に1を返すテストスタブを生成 + var sut = new Janken(stub); // テスト対象にスタブを注入 + var actual = sut.Pon(); - Assert.That(spy._actualMinValue, Is.EqualTo(0)); - Assert.That(spy._actualMaxValue, Is.EqualTo(3)); + Assert.That(actual, Is.EqualTo(Hand.Paper)); // 結果は常に「ぱー」 } - /// - /// テストスパイ実装 - /// - private class SpyRandom : IRandom + [Test] + public void Pon_PRNGのRangeに要求している値域は0から1であること() { - /// - /// の第一引数をキャプチャ - /// - internal int _actualMinValue; - - /// - /// の第二引数をキャプチャ - /// - internal int _actualMaxValue; - - /// - /// 引数をキャプチャするスパイメソッド - /// - /// 常に1を返す - public int Range(int minValue, int maxValue) - { - this._actualMinValue = minValue; // 第一引数をキャプチャ - this._actualMaxValue = maxValue; // 第二引数をキャプチャ + var spy = new SpyRandom(); // テストスパイを生成 + var sut = new Janken(spy); // テスト対象にスパイを注入 + sut.Pon(); // Note: SUTの戻り値は検証しない - return 1; // テスト結果に影響しないのであれば、スタブのように固定値を返しても、本物の依存オブジェクトに委譲してもよい - } + Assert.That(spy.LastMinInclusive, Is.EqualTo(0.0f)); + Assert.That(spy.LastMaxInclusive, Is.EqualTo(1.0f)); } } } diff --git a/Assets/TestDoubleExample/Tests/Runtime/Janken/JankenTestNSubstitute.cs b/Assets/TestDoubleExample/Tests/Runtime/Janken/JankenTestNSubstitute.cs deleted file mode 100644 index 401cf79..0000000 --- a/Assets/TestDoubleExample/Tests/Runtime/Janken/JankenTestNSubstitute.cs +++ /dev/null @@ -1,121 +0,0 @@ -// Copyright (c) 2021-2023 Koji Hasegawa. -// This software is released under the MIT License. - -using NSubstitute; -using NUnit.Framework; - -namespace TestDoubleExample.Janken -{ - /// - /// NSubstituteの使用例 - /// - public class JankenTestNSubstitute - { - [Test] - public void Pon_NSubstituteで間接入力を固定してテストする例() - { - var stub = Substitute.For(); - stub.Range(0, 3).Returns(0); // Range(0, 3)に対し、常に0を返すスタブを設定 - - var sut = new Janken(stub); // テスト対象にスタブを注入 - var actual = sut.Pon(); - - Assert.That(actual, Is.EqualTo(Hand.Rock)); // 結果は常に「ぐー」 - } - - [Test] - public void Pon_NSubstituteで間接入力を固定してテストする例_Anyにより引数を限定しない() - { - var stub = Substitute.For(); - stub.Range(Arg.Any(), Arg.Any()).Returns(1); // `Arg.Any()`には任意の整数がマッチする - - var sut = new Janken(stub); // テスト対象にスタブを注入 - var actual = sut.Pon(); - - Assert.That(actual, Is.EqualTo(Hand.Scissors)); // 結果は常に「ちょき」 - } - - [Test] - public void Pon_NSubstituteで間接入力を固定してテストする例_ReturnsForAnyArgsにより引数を限定しない() - { - var stub = Substitute.For(); - stub.Range(default, default).ReturnsForAnyArgs(2); // 引数を限定しないで常に2を返す - // Note: Range()の引数は無視されますが、わかりやすくなるよう`default`を指定しています - - var sut = new Janken(stub); // テスト対象にスタブを注入 - var actual = sut.Pon(); - - Assert.That(actual, Is.EqualTo(Hand.Paper)); // 結果は常に「ぱー」 - } - - [Test] - public void Pon_NSubstituteで間接入力を複数指定してテストする例() - { - var stub = Substitute.For(); - stub.Range(0, 3).Returns(0, 1, 2); // 期待値を複数渡すと順に使用されます - - var sut = new Janken(stub); - - Assert.That(sut.Pon(), Is.EqualTo(Hand.Rock)); // 1回目は「ぐー」固定 - Assert.That(sut.Pon(), Is.EqualTo(Hand.Scissors)); // 2回目は「ちょき」固定 - Assert.That(sut.Pon(), Is.EqualTo(Hand.Paper)); // 3回目は「ぱー」固定 - } - - [Test] - public void Pon_NSubstituteで間接入力を引数から導出する例() - { - var stub = Substitute.For(); - stub.Range(Arg.Any(), Arg.Any()).Returns(x => (int)x[1] - 1); // 第二引数の値-1(つまり最大値)を返す - - var sut = new Janken(stub); - var actual = sut.Pon(); - - Assert.That(actual, Is.EqualTo(Hand.Paper)); // 結果は常に「ぱー」 - } - - [Test] - public void Pon_NSubstituteで間接出力をテストする例() - { - var spy = Substitute.For(); - - var sut = new Janken(spy); // テスト対象にスパイを注入 - sut.Pon(); - - spy.Received().Range(0, 3); // 引数(0, 3)で呼ばれたことを検証 - - spy.DidNotReceive().Range(Arg.Is(x => x != 0), Arg.Any()); // 第一引数は0以外では呼ばれていないことを検証 - spy.DidNotReceive().Range(Arg.Any(), Arg.Is(x => x != 3)); // 第二引数は3以外では呼ばれていないことを検証 - } - - [TestFixture] - public class ClassMockingExamples - { - [Test] - [Explicit("実行時エラーになるため除外")] - public void Pon_classの非virtualメソッドは置き換えできない() - { - var stub = Substitute.For(); // classを指定 - stub.Range(0, 3).Returns(0); // 実行時にCouldNotSetReturnDueToNoLastCallException発生 - // Note: アナライザー`NSubstitute.Analyzers.CSharp`をプロジェクトに導入すると、このパターンをコンパイル時警告にできます - // アナライザーが動作するUnityバージョンについては https://www.nowsprinting.com/entry/2021/04/18/200619 を参照してください - - var sut = new Janken(stub); - var actual = sut.Pon(); - - Assert.That(actual, Is.EqualTo(Hand.Rock)); - } - - [Test] - public void Pon_classでもvirtualメソッドは置き換えできる() - { - var stub = Substitute.For(); // classを指定 - stub.Range(0, 3).Returns(1); // classでもvirtualメソッドは置き換えできる - - var sut = new Janken(stub); - var actual = sut.Pon(); - - Assert.That(actual, Is.EqualTo(Hand.Scissors)); - } - } - } -} diff --git a/Assets/TestDoubleExample/Tests/Runtime/Janken/NSubstituteJankenTest.cs b/Assets/TestDoubleExample/Tests/Runtime/Janken/NSubstituteJankenTest.cs new file mode 100644 index 0000000..a6697f0 --- /dev/null +++ b/Assets/TestDoubleExample/Tests/Runtime/Janken/NSubstituteJankenTest.cs @@ -0,0 +1,89 @@ +// Copyright (c) 2021-2025 Koji Hasegawa. +// This software is released under the MIT License. + +using NSubstitute; +using NUnit.Framework; + +namespace TestDoubleExample.Janken +{ + /// + /// NSubstitute によるテストの例 + /// + public class NSubstituteJankenTest + { + [Test] + public void Pon_PRNGが0を返すとき_ぐーを返す() + { + var stub = Substitute.For(); + stub.Range(0.0f, 1.0f).Returns(0.0f); // 常に0を返すテストスタブを生成 + // Note: Rangeメソッドの引数が (0f, 1f) のとき指定された戻り値を返す + + var sut = new Janken(stub); // テスト対象にスタブを注入 + var actual = sut.Pon(); + + Assert.That(actual, Is.EqualTo(Hand.Rock)); // 結果は常に「ぐー」 + } + + [Test] + public void Pon_PRNGがdot5を返すとき_ちょきを返す() + { + var stub = Substitute.For(); + stub.Range(Arg.Any(), Arg.Any()).Returns(0.5f); // 常に0.5を返すテストスタブを生成 + // Note: Rangeメソッドの引数2つの値がいくつであっても指定された戻り値を返す(Arg.Any()を使用) + + var sut = new Janken(stub); // テスト対象にスタブを注入 + var actual = sut.Pon(); + + Assert.That(actual, Is.EqualTo(Hand.Scissors)); // 結果は常に「ちょき」 + } + + [Test] + public void Pon_PRNGが1を返すとき_ぱーを返す() + { + var stub = Substitute.For(); + stub.Range(0f, 0f).ReturnsForAnyArgs(1.0f); // 常に1を返すテストスタブを生成 + // Note: Rangeメソッドの引数2つの値がいくつであっても指定された戻り値を返す(ReturnsForAnyArgsを使用) + + var sut = new Janken(stub); // テスト対象にスタブを注入 + var actual = sut.Pon(); + + Assert.That(actual, Is.EqualTo(Hand.Paper)); // 結果は常に「ぱー」 + } + + [Test] + public void NSubstituteで常に最大値を返すスタブの例() + { + var stub = Substitute.For(); + stub.Range(Arg.Any(), Arg.Any()).Returns(x => (float)x[1]); // 第二引数の値(つまり最大値)を返す + + var sut = new Janken(stub); + var actual = sut.Pon(); + + Assert.That(actual, Is.EqualTo(Hand.Paper)); // 結果は常に「ぱー」 + } + + [Test] + public void NSubstituteで間接入力を複数指定する例() + { + var stub = Substitute.For(); + stub.Range(0f, 0f).ReturnsForAnyArgs(0.0f, 0.5f, 1.0f); // 戻り値を複数指定すると順に使用されます + var sut = new Janken(stub); + + Assert.That(sut.Pon(), Is.EqualTo(Hand.Rock)); // 1回目は常に「ぐー」 + Assert.That(sut.Pon(), Is.EqualTo(Hand.Scissors)); // 2回目は常に「ちょき」 + Assert.That(sut.Pon(), Is.EqualTo(Hand.Paper)); // 3回目は常に「ぱー」 + } + + [Test] + public void Pon_PRNGのRangeに要求している値域は0から1であること() + { + var spy = Substitute.For(); // テストスパイを生成 + var sut = new Janken(spy); // テスト対象にスパイを注入 + sut.Pon(); + + spy.Received().Range(0.0f, 1.0f); // 引数 (0f, 1f) で呼ばれたことを検証 + spy.DidNotReceive().Range(Arg.Is(x => x != 0.0f), Arg.Any()); // 第一引数は 0f 以外では呼ばれていないことを検証 + spy.DidNotReceive().Range(Arg.Any(), Arg.Is(x => x != 1.0f)); // 第二引数は 1f 以外では呼ばれていないことを検証 + } + } +} diff --git a/Assets/TestDoubleExample/Tests/Runtime/Janken/JankenTestNSubstitute.cs.meta b/Assets/TestDoubleExample/Tests/Runtime/Janken/NSubstituteJankenTest.cs.meta similarity index 100% rename from Assets/TestDoubleExample/Tests/Runtime/Janken/JankenTestNSubstitute.cs.meta rename to Assets/TestDoubleExample/Tests/Runtime/Janken/NSubstituteJankenTest.cs.meta diff --git a/Assets/TestDoubleExample/Tests/Runtime/Janken/NondeterministicJankenTest.cs b/Assets/TestDoubleExample/Tests/Runtime/Janken/NondeterministicJankenTest.cs deleted file mode 100644 index 2c088d8..0000000 --- a/Assets/TestDoubleExample/Tests/Runtime/Janken/NondeterministicJankenTest.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2021-2022 Koji Hasegawa. -// This software is released under the MIT License. - -using System.Collections.Generic; -using NUnit.Framework; -using UnityEngine.TestTools.Utils; - -namespace TestDoubleExample.Janken -{ - /// - /// 非決定的なテストしかできないじゃんけんロジックに対するテストの例 - /// - /// - /// じゃんけんくらいの試行回数であればテストダブルに頼らないテストという選択肢もあります - /// - public class NondeterministicJankenTest - { - [Test] - [Repeat(100)] - public void Pon_OrとRepeatによる非決定的なテストの例() - { - var sut = new NondeterministicJanken(); - var actual = sut.Pon(); - - Assert.That(actual, Is.EqualTo(Hand.Rock).Or.EqualTo(Hand.Paper).Or.EqualTo(Hand.Scissors)); - } - - [TestCase(Hand.Rock, 0.33f)] - [TestCase(Hand.Scissors, 0.33f)] - [TestCase(Hand.Paper, 0.33f)] - [Retry(2)] - public void Pon_出力が仕様通り分布していることをテストする例(Hand hand, float expectedRate) - { - const int NumOfAttempts = 100; - var comparer = new FloatEqualityComparer(0.1f); - var actual = new Dictionary(); - var sut = new NondeterministicJanken(); - - // Exercise - for (var i = 0; i < NumOfAttempts; i++) - { - var h = sut.Pon(); - if (actual.ContainsKey(h)) - { - actual[h]++; - } - else - { - actual.Add(h, 1); - } - } - - // Verify - var rate = (float)actual[hand] / NumOfAttempts; - Assert.That(rate, Is.EqualTo(expectedRate).Using(comparer)); - } - } -} diff --git a/Assets/TestDoubleExample/Tests/Runtime/Janken/NondeterministicJankenTest.cs.meta b/Assets/TestDoubleExample/Tests/Runtime/Janken/NondeterministicJankenTest.cs.meta deleted file mode 100644 index aa21a92..0000000 --- a/Assets/TestDoubleExample/Tests/Runtime/Janken/NondeterministicJankenTest.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 82294cc3c4b84d748ef28057de789cec -timeCreated: 1626984165 \ No newline at end of file diff --git a/Assets/TestDoubleExample/Tests/Runtime/NSubstituteTips.meta b/Assets/TestDoubleExample/Tests/Runtime/NSubstituteTips.meta deleted file mode 100644 index aa4a5a6..0000000 --- a/Assets/TestDoubleExample/Tests/Runtime/NSubstituteTips.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 68c9063a6e18452fb080616dc666914d -timeCreated: 1659841298 \ No newline at end of file diff --git a/Assets/TestDoubleExample/Tests/Runtime/NSubstituteTips/AutoAndRecursiveMocksExample.cs b/Assets/TestDoubleExample/Tests/Runtime/NSubstituteTips/AutoAndRecursiveMocksExample.cs deleted file mode 100644 index 98b3aa0..0000000 --- a/Assets/TestDoubleExample/Tests/Runtime/NSubstituteTips/AutoAndRecursiveMocksExample.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2021-2023 Koji Hasegawa. -// This software is released under the MIT License. - -using NSubstitute; -using NUnit.Framework; - -namespace TestDoubleExample.NSubstituteTips -{ - /// - /// virtualキーワード付きプロパティには自動的にnullでない値を返すスタブが生成されます - /// stringはstring.Empty、arrayは空のarrayが返ります - /// interfaceの場合は、再帰的にスタブが生成されます - /// classの場合は、そのclassのすべてのpublicメソッド・プロパティがvirtualもしくはabstractであれば、再帰的にスタブが生成されます - /// see https://nsubstitute.github.io/help/auto-and-recursive-mocks/ - /// - public class AutoAndRecursiveMocksExample - { - [Test] - public void 通常のインスタンス生成() - { - var foo = new Foo(); - Assert.That(foo.i, Is.EqualTo(0)); - Assert.That(foo.s, Is.Null); // stringのデフォルト値はnull - Assert.That(foo.a, Is.Null); // arrayのデフォルト値はnull - Assert.That(foo.bar, Is.Null); // classのデフォルトはnull - } - - [Test] - public void NSubstituteによる再帰的モック生成の例() - { - var foo = Substitute.For(); - - // Auto values - Assert.That(foo.i, Is.EqualTo(0)); - Assert.That(foo.s, Is.EqualTo("")); // string.Emptyを返してくれる - Assert.That(foo.a, Is.EqualTo(new string[] { })); // 空のarrayを返してくれる - Assert.That(foo.bar, Is.Not.Null); // Barのインスタンスを返してくれる - - // Recursive mocks - Assert.That(foo.bar.i, Is.EqualTo(0)); - Assert.That(foo.bar.s, Is.EqualTo("")); - Assert.That(foo.bar.a, Is.EqualTo(new string[] { })); - Assert.That(foo.bar.baz.i, Is.EqualTo(0)); - Assert.That(foo.bar.baz.s, Is.EqualTo("")); - Assert.That(foo.bar.baz.a, Is.EqualTo(new string[] { })); - Assert.That(foo.bar.baz.qux, Is.Null); // Quxはvirtualでないプロパティを含むためインスタンス生成されない - } - - public class Foo - { - public virtual int i { get; } - public virtual string s { get; } - public virtual string[] a { get; } - public virtual Bar bar { get; } - } - - public interface Bar - { - int i { get; } - string s { get; } - string[] a { get; } - Baz baz { get; } - } - - public abstract class Baz - { - public abstract int i { get; } - public abstract string s { get; } - public abstract string[] a { get; } - public abstract Qux qux { get; } - } - - public class Qux - { - public virtual string WithVirtual { get; } - public string[] WithoutVirtual { get; } - } - } -} diff --git a/Assets/TestDoubleExample/Tests/Runtime/NSubstituteTips/AutoAndRecursiveMocksExample.cs.meta b/Assets/TestDoubleExample/Tests/Runtime/NSubstituteTips/AutoAndRecursiveMocksExample.cs.meta deleted file mode 100644 index 45b50bf..0000000 --- a/Assets/TestDoubleExample/Tests/Runtime/NSubstituteTips/AutoAndRecursiveMocksExample.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: ed125516274241bbb35065ef06364368 -timeCreated: 1659837455 \ No newline at end of file diff --git a/Assets/TestDoubleExample/Tests/Runtime/TestDoubles.meta b/Assets/TestDoubleExample/Tests/Runtime/TestDoubles.meta new file mode 100644 index 0000000..ffa8ea0 --- /dev/null +++ b/Assets/TestDoubleExample/Tests/Runtime/TestDoubles.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ab874da19f034c62be9fd808c5fd7c64 +timeCreated: 1764533906 \ No newline at end of file diff --git a/Assets/TestDoubleExample/Tests/Runtime/TestDoubles/SpyRandom.cs b/Assets/TestDoubleExample/Tests/Runtime/TestDoubles/SpyRandom.cs new file mode 100644 index 0000000..40f8226 --- /dev/null +++ b/Assets/TestDoubleExample/Tests/Runtime/TestDoubles/SpyRandom.cs @@ -0,0 +1,29 @@ +// Copyright (c) 2021-2025 Koji Hasegawa. +// This software is released under the MIT License. + +using TestDoubleExample.Janken; + +namespace TestDoubleExample.TestDoubles +{ + /// + /// のテストスパイ実装 + /// + public class SpyRandom : IRandom + { + public float LastMinInclusive { get; private set; } + public float LastMaxInclusive { get; private set; } + + /// + /// + /// 引数で指定された値をプロパティに保存し、 による擬似乱数を返す + /// + public float Range(float minInclusive, float maxInclusive) + { + LastMinInclusive = minInclusive; + LastMaxInclusive = maxInclusive; + + return 0.0f; + // Note: テスト結果に影響しないのであれば、スタブのように固定値を返しても、本物の依存オブジェクトに委譲してもよい + } + } +} diff --git a/Assets/TestDoubleExample/Tests/Runtime/TestDoubles/SpyRandom.cs.meta b/Assets/TestDoubleExample/Tests/Runtime/TestDoubles/SpyRandom.cs.meta new file mode 100644 index 0000000..c67da6b --- /dev/null +++ b/Assets/TestDoubleExample/Tests/Runtime/TestDoubles/SpyRandom.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: d36946417c6f4b3d8fa64284ae23715a +timeCreated: 1764534252 \ No newline at end of file diff --git a/Assets/TestDoubleExample/Tests/Runtime/TestDoubles/StubRandom.cs b/Assets/TestDoubleExample/Tests/Runtime/TestDoubles/StubRandom.cs new file mode 100644 index 0000000..19f93e6 --- /dev/null +++ b/Assets/TestDoubleExample/Tests/Runtime/TestDoubles/StubRandom.cs @@ -0,0 +1,33 @@ +// Copyright (c) 2021-2025 Koji Hasegawa. +// This software is released under the MIT License. + +using TestDoubleExample.Janken; + +namespace TestDoubleExample.TestDoubles +{ + /// + /// のテストスタブ実装 + /// + public class StubRandom : IRandom + { + private readonly float _value; + + /// + /// コンストラクタ + /// + /// メソッドが返す値を指定 + public StubRandom(float value) + { + _value = value; + } + + /// + /// + /// 常にコンストラクタで指定された値を返す + /// + public float Range(float minInclusive, float maxInclusive) + { + return _value; + } + } +} diff --git a/Assets/TestDoubleExample/Tests/Runtime/TestDoubles/StubRandom.cs.meta b/Assets/TestDoubleExample/Tests/Runtime/TestDoubles/StubRandom.cs.meta new file mode 100644 index 0000000..41dcf41 --- /dev/null +++ b/Assets/TestDoubleExample/Tests/Runtime/TestDoubles/StubRandom.cs.meta @@ -0,0 +1,3 @@ +fileFormatVersion: 2 +guid: ec7c9ab6e2b640d887510830cb1dfcd5 +timeCreated: 1764533916 \ No newline at end of file diff --git a/Assets/UGUIExample/Tests/Runtime/MonkeyTest.cs b/Assets/UGUIExample/Tests/Runtime/MonkeyTest.cs index c116947..e37cd5b 100644 --- a/Assets/UGUIExample/Tests/Runtime/MonkeyTest.cs +++ b/Assets/UGUIExample/Tests/Runtime/MonkeyTest.cs @@ -1,12 +1,12 @@ -// Copyright (c) 2021-2023 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. using System; using System.Threading.Tasks; using Cysharp.Threading.Tasks; using NUnit.Framework; -using TestHelper.Monkey; using TestHelper.Random; +using TestHelper.UI; using UnityEngine; using UnityEngine.SceneManagement; @@ -22,7 +22,7 @@ public class MonkeyTest [Test] public async Task MonkeyTesting() { - var random = new RandomImpl(); // 擬似乱数生成器 + var random = new RandomWrapper(); // 擬似乱数生成器 Debug.Log($"Random that monkey uses: {random}"); // シード値をログ出力 await SceneManager.LoadSceneAsync("MainMenu"); @@ -30,10 +30,10 @@ public async Task MonkeyTesting() var config = new MonkeyConfig { - Lifetime = TimeSpan.FromSeconds(5), // 5秒間動作(3分以上にする場合はTimeout属性でテスト自体のタイムウトを延ばすこと) - DelayMillis = 200, // 操作間隔は200ms + Lifetime = TimeSpan.FromSeconds(5), // 5秒間動作(3分以上にする場合はTimeout属性でテスト自体のタイムウトを延ばすこと) + DelayMillis = 200, // 操作間隔は200ms SecondsToErrorForNoInteractiveComponent = 5, // 5秒無操作で失敗扱い - Random = random, // 擬似乱数生成器を指定 + Random = random, // 擬似乱数生成器を指定 }; await Monkey.Run(config); diff --git a/Assets/UGUIExample/Tests/Runtime/UGUIExample.Tests.asmdef b/Assets/UGUIExample/Tests/Runtime/UGUIExample.Tests.asmdef index 8f87f01..a3d3576 100644 --- a/Assets/UGUIExample/Tests/Runtime/UGUIExample.Tests.asmdef +++ b/Assets/UGUIExample/Tests/Runtime/UGUIExample.Tests.asmdef @@ -1,13 +1,14 @@ { "name": "UGUIExample.Tests", + "rootNamespace": "", "references": [ "UnityEngine.TestRunner", "UnityEditor.TestRunner", "UGUIExample", "UniTask", "TestHelper", - "TestHelper.Monkey", - "TestHelper.Random" + "TestHelper.Random", + "TestHelper.UI" ], "includePlatforms": [], "excludePlatforms": [], diff --git a/Assets/VisualRegressionExample/Tests/Runtime/ImageAssertTest.cs b/Assets/VisualRegressionExample/Tests/Runtime/ImageAssertTest.cs index 974647a..031d8c0 100644 --- a/Assets/VisualRegressionExample/Tests/Runtime/ImageAssertTest.cs +++ b/Assets/VisualRegressionExample/Tests/Runtime/ImageAssertTest.cs @@ -1,6 +1,7 @@ // Copyright (c) 2021-2023 Koji Hasegawa. // This software is released under the MIT License. +#if ENABLE_GRAPHICS_TEST_FRAMEWORK using System.Collections; using System.IO; using System.Threading.Tasks; @@ -125,3 +126,4 @@ private class CoroutineRunner : MonoBehaviour } } } +#endif diff --git a/Assets/VisualRegressionExample/Tests/Runtime/VisualRegressionExample.Tests.asmdef b/Assets/VisualRegressionExample/Tests/Runtime/VisualRegressionExample.Tests.asmdef index 2bc2317..b9f18ce 100644 --- a/Assets/VisualRegressionExample/Tests/Runtime/VisualRegressionExample.Tests.asmdef +++ b/Assets/VisualRegressionExample/Tests/Runtime/VisualRegressionExample.Tests.asmdef @@ -19,6 +19,12 @@ "defineConstraints": [ "UNITY_INCLUDE_TESTS" ], - "versionDefines": [], + "versionDefines": [ + { + "name": "com.unity.testframework.graphics", + "expression": "", + "define": "ENABLE_GRAPHICS_TEST_FRAMEWORK" + } + ], "noEngineReferences": false } \ No newline at end of file diff --git a/LocalPackages/com.nowsprinting.local-package-sample/Scripts/Editor.meta b/LocalPackages/com.nowsprinting.local-package-sample/Editor.meta similarity index 100% rename from LocalPackages/com.nowsprinting.local-package-sample/Scripts/Editor.meta rename to LocalPackages/com.nowsprinting.local-package-sample/Editor.meta diff --git a/LocalPackages/com.nowsprinting.local-package-sample/Scripts/Editor/ExampleForCoverage.cs b/LocalPackages/com.nowsprinting.local-package-sample/Editor/ExampleForCoverage.cs similarity index 99% rename from LocalPackages/com.nowsprinting.local-package-sample/Scripts/Editor/ExampleForCoverage.cs rename to LocalPackages/com.nowsprinting.local-package-sample/Editor/ExampleForCoverage.cs index e8b8e09..49cc0a9 100644 --- a/LocalPackages/com.nowsprinting.local-package-sample/Scripts/Editor/ExampleForCoverage.cs +++ b/LocalPackages/com.nowsprinting.local-package-sample/Editor/ExampleForCoverage.cs @@ -2,6 +2,7 @@ // This software is released under the MIT License. // ReSharper disable once CheckNamespace (rootNamespace not work in Unity 2019) + namespace LocalPackageSample.Editor { public static class ExampleForCoverage diff --git a/LocalPackages/com.nowsprinting.local-package-sample/Scripts/Editor/ExampleForCoverage.cs.meta b/LocalPackages/com.nowsprinting.local-package-sample/Editor/ExampleForCoverage.cs.meta similarity index 100% rename from LocalPackages/com.nowsprinting.local-package-sample/Scripts/Editor/ExampleForCoverage.cs.meta rename to LocalPackages/com.nowsprinting.local-package-sample/Editor/ExampleForCoverage.cs.meta diff --git a/LocalPackages/com.nowsprinting.local-package-sample/Scripts/Editor/LocalPackageSample.Editor.asmdef b/LocalPackages/com.nowsprinting.local-package-sample/Editor/LocalPackageSample.Editor.asmdef similarity index 100% rename from LocalPackages/com.nowsprinting.local-package-sample/Scripts/Editor/LocalPackageSample.Editor.asmdef rename to LocalPackages/com.nowsprinting.local-package-sample/Editor/LocalPackageSample.Editor.asmdef diff --git a/LocalPackages/com.nowsprinting.local-package-sample/Scripts/Editor/LocalPackageSample.Editor.asmdef.meta b/LocalPackages/com.nowsprinting.local-package-sample/Editor/LocalPackageSample.Editor.asmdef.meta similarity index 100% rename from LocalPackages/com.nowsprinting.local-package-sample/Scripts/Editor/LocalPackageSample.Editor.asmdef.meta rename to LocalPackages/com.nowsprinting.local-package-sample/Editor/LocalPackageSample.Editor.asmdef.meta diff --git a/LocalPackages/com.nowsprinting.local-package-sample/Scripts/Runtime.meta b/LocalPackages/com.nowsprinting.local-package-sample/Runtime.meta similarity index 100% rename from LocalPackages/com.nowsprinting.local-package-sample/Scripts/Runtime.meta rename to LocalPackages/com.nowsprinting.local-package-sample/Runtime.meta diff --git a/LocalPackages/com.nowsprinting.local-package-sample/Scripts/Runtime/ExampleForCoverage.cs b/LocalPackages/com.nowsprinting.local-package-sample/Runtime/ExampleForCoverage.cs similarity index 99% rename from LocalPackages/com.nowsprinting.local-package-sample/Scripts/Runtime/ExampleForCoverage.cs rename to LocalPackages/com.nowsprinting.local-package-sample/Runtime/ExampleForCoverage.cs index 69e4eac..bce28d6 100644 --- a/LocalPackages/com.nowsprinting.local-package-sample/Scripts/Runtime/ExampleForCoverage.cs +++ b/LocalPackages/com.nowsprinting.local-package-sample/Runtime/ExampleForCoverage.cs @@ -2,6 +2,7 @@ // This software is released under the MIT License. // ReSharper disable once CheckNamespace (rootNamespace not work in Unity 2019) + namespace LocalPackageSample { public static class ExampleForCoverage diff --git a/LocalPackages/com.nowsprinting.local-package-sample/Scripts/Runtime/ExampleForCoverage.cs.meta b/LocalPackages/com.nowsprinting.local-package-sample/Runtime/ExampleForCoverage.cs.meta similarity index 100% rename from LocalPackages/com.nowsprinting.local-package-sample/Scripts/Runtime/ExampleForCoverage.cs.meta rename to LocalPackages/com.nowsprinting.local-package-sample/Runtime/ExampleForCoverage.cs.meta diff --git a/LocalPackages/com.nowsprinting.local-package-sample/Scripts/Runtime/LocalPackageSample.asmdef b/LocalPackages/com.nowsprinting.local-package-sample/Runtime/LocalPackageSample.asmdef similarity index 100% rename from LocalPackages/com.nowsprinting.local-package-sample/Scripts/Runtime/LocalPackageSample.asmdef rename to LocalPackages/com.nowsprinting.local-package-sample/Runtime/LocalPackageSample.asmdef diff --git a/LocalPackages/com.nowsprinting.local-package-sample/Scripts/Runtime/LocalPackageSample.asmdef.meta b/LocalPackages/com.nowsprinting.local-package-sample/Runtime/LocalPackageSample.asmdef.meta similarity index 100% rename from LocalPackages/com.nowsprinting.local-package-sample/Scripts/Runtime/LocalPackageSample.asmdef.meta rename to LocalPackages/com.nowsprinting.local-package-sample/Runtime/LocalPackageSample.asmdef.meta diff --git a/LocalPackages/com.nowsprinting.local-package-sample/Scenes/SceneInPackage.unity b/LocalPackages/com.nowsprinting.local-package-sample/Scenes/SceneInLocalPackage.unity similarity index 90% rename from LocalPackages/com.nowsprinting.local-package-sample/Scenes/SceneInPackage.unity rename to LocalPackages/com.nowsprinting.local-package-sample/Scenes/SceneInLocalPackage.unity index 28d9b9d..64ed80f 100644 --- a/LocalPackages/com.nowsprinting.local-package-sample/Scenes/SceneInPackage.unity +++ b/LocalPackages/com.nowsprinting.local-package-sample/Scenes/SceneInLocalPackage.unity @@ -13,7 +13,7 @@ OcclusionCullingSettings: --- !u!104 &2 RenderSettings: m_ObjectHideFlags: 0 - serializedVersion: 9 + serializedVersion: 10 m_Fog: 0 m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} m_FogMode: 3 @@ -38,13 +38,12 @@ RenderSettings: m_ReflectionIntensity: 1 m_CustomReflection: {fileID: 0} m_Sun: {fileID: 0} - m_IndirectSpecularColor: {r: 0.44657838, g: 0.49641234, b: 0.57481676, a: 1} m_UseRadianceAmbientProbe: 0 --- !u!157 &3 LightmapSettings: m_ObjectHideFlags: 0 - serializedVersion: 12 - m_GIWorkflowMode: 1 + serializedVersion: 13 + m_BakeOnSceneLoad: 0 m_GISettings: serializedVersion: 2 m_BounceScale: 1 @@ -67,9 +66,6 @@ LightmapSettings: m_LightmapParameters: {fileID: 0} m_LightmapsBakeMode: 1 m_TextureCompression: 1 - m_FinalGather: 0 - m_FinalGatherFiltering: 1 - m_FinalGatherRayCount: 256 m_ReflectionCompression: 2 m_MixedBakeMode: 2 m_BakeBackend: 1 @@ -104,7 +100,7 @@ NavMeshSettings: serializedVersion: 2 m_ObjectHideFlags: 0 m_BuildSettings: - serializedVersion: 2 + serializedVersion: 3 agentTypeID: 0 agentRadius: 0.5 agentHeight: 2 @@ -117,7 +113,7 @@ NavMeshSettings: cellSize: 0.16666667 manualTileSize: 0 tileSize: 256 - accuratePlacement: 0 + buildHeightMesh: 0 maxJobWorkers: 0 preserveTilesOutsideBounds: 0 debug: @@ -150,8 +146,17 @@ CapsuleCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 551686857} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 + serializedVersion: 2 m_Radius: 0.5000001 m_Height: 2 m_Direction: 1 @@ -167,11 +172,15 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -212,12 +221,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 551686857} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 924.2142, y: 351.34674, z: -17.195045} + m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &854170358 GameObject: @@ -244,9 +254,8 @@ Light: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 854170358} m_Enabled: 1 - serializedVersion: 10 + serializedVersion: 11 m_Type: 1 - m_Shape: 0 m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} m_Intensity: 1 m_Range: 10 @@ -296,8 +305,12 @@ Light: m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} m_UseBoundingSphereOverride: 0 m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 m_ShadowRadius: 0 m_ShadowAngle: 0 + m_LightUnit: 1 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 --- !u!4 &854170360 Transform: m_ObjectHideFlags: 0 @@ -305,12 +318,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 854170358} + serializedVersion: 2 m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} m_LocalPosition: {x: 0, y: 3, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} --- !u!1 &2006839994 GameObject: @@ -352,9 +366,17 @@ Camera: m_projectionMatrixMode: 1 m_GateFitMode: 2 m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 50 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 m_SensorSize: {x: 36, y: 24} m_LensShift: {x: 0, y: 0} - m_FocalLength: 50 m_NormalizedViewPortRect: serializedVersion: 2 x: 0 @@ -388,10 +410,18 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2006839994} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 1, z: -10} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 2006839997} + - {fileID: 854170360} + - {fileID: 551686861} diff --git a/LocalPackages/com.nowsprinting.local-package-sample/Scenes/SceneInPackage.unity.meta b/LocalPackages/com.nowsprinting.local-package-sample/Scenes/SceneInLocalPackage.unity.meta similarity index 100% rename from LocalPackages/com.nowsprinting.local-package-sample/Scenes/SceneInPackage.unity.meta rename to LocalPackages/com.nowsprinting.local-package-sample/Scenes/SceneInLocalPackage.unity.meta diff --git a/LocalPackages/com.nowsprinting.local-package-sample/Scripts.meta b/LocalPackages/com.nowsprinting.local-package-sample/Scripts.meta deleted file mode 100644 index e8ca509..0000000 --- a/LocalPackages/com.nowsprinting.local-package-sample/Scripts.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 3c48a046ace8d442c8fd1836d056e41c -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/LocalPackages/com.nowsprinting.local-package-sample/Scripts/Editor/BuildAllScenesForTestPlayer.cs b/LocalPackages/com.nowsprinting.local-package-sample/Scripts/Editor/BuildAllScenesForTestPlayer.cs deleted file mode 100644 index 51e5740..0000000 --- a/LocalPackages/com.nowsprinting.local-package-sample/Scripts/Editor/BuildAllScenesForTestPlayer.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2021 Koji Hasegawa. -// This software is released under the MIT License. - -using System.Collections.Generic; -using System.Linq; -using LocalPackageSample.Editor; -using UnityEditor; -using UnityEditor.TestTools; - -[assembly: TestPlayerBuildModifier(typeof(BuildAllScenesForTestPlayer))] - -// ReSharper disable once CheckNamespace (rootNamespace not work in Unity 2019) -namespace LocalPackageSample.Editor -{ - /// - /// プレイヤーでのテスト実行前のビルドで、"Scenes in Build"に指定されていないSceneを一時的にビルドに含めます。 - /// これによって、テスト内で を使用してSceneをロードできるようになります。 - /// - /// - /// このスクリプトの利用には、Unity Test Frameworkパッケージ v1.1.13以上が必要です。 - /// 詳細は フォーラムの報告 を参照してください。 - /// - public class BuildAllScenesForTestPlayer : ITestPlayerBuildModifier - { - public BuildPlayerOptions ModifyOptions(BuildPlayerOptions playerOptions) - { - var buildSceneList = new List(playerOptions.scenes); - foreach (var scene in AssetDatabase - .FindAssets("t:SceneAsset", new string[] { "Packages/com.nowsprinting.local-package-sample" }) - .Select(AssetDatabase.GUIDToAssetPath)) - { - if (!buildSceneList.Contains(scene)) - { - buildSceneList.Add(scene); - } - } - // 引数で渡される `playerOptions.scenes` に入っているSceneの順序を変えると、テストが起動しないことがあります。 - // そのため、不足しているSceneだけを後ろに追加しています。 - - playerOptions.scenes = buildSceneList.ToArray(); - - return playerOptions; - } - } -} diff --git a/LocalPackages/com.nowsprinting.local-package-sample/Scripts/Editor/BuildAllScenesForTestPlayer.cs.meta b/LocalPackages/com.nowsprinting.local-package-sample/Scripts/Editor/BuildAllScenesForTestPlayer.cs.meta deleted file mode 100644 index 3ba9f06..0000000 --- a/LocalPackages/com.nowsprinting.local-package-sample/Scripts/Editor/BuildAllScenesForTestPlayer.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: b925ede2abfa84db59cdd3cae92c072e -timeCreated: 1622685134 \ No newline at end of file diff --git a/LocalPackages/com.nowsprinting.local-package-sample/Tests/Editor/EditorSceneManagerTest.cs b/LocalPackages/com.nowsprinting.local-package-sample/Tests/Editor/EditorSceneManagerTest.cs index 6cd729d..1aa3fab 100644 --- a/LocalPackages/com.nowsprinting.local-package-sample/Tests/Editor/EditorSceneManagerTest.cs +++ b/LocalPackages/com.nowsprinting.local-package-sample/Tests/Editor/EditorSceneManagerTest.cs @@ -1,11 +1,10 @@ -// Copyright (c) 2021 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. using NUnit.Framework; using UnityEditor.SceneManagement; using UnityEngine; -// ReSharper disable once CheckNamespace (rootNamespace not work in Unity 2019) namespace LocalPackageSample.Editor { [TestFixture] @@ -14,7 +13,8 @@ public class EditorSceneManagerTest [Test] public void OpenScene_Sceneファイルをロードしてテストを実行する例() { - EditorSceneManager.OpenScene("Packages/com.nowsprinting.local-package-sample/Scenes/SceneInPackage.unity"); + EditorSceneManager.OpenScene( + "Packages/com.nowsprinting.local-package-sample/Scenes/SceneInLocalPackage.unity"); // パスはProjectウィンドウに表示されるパスで指定。ただしパッケージ名の部分は `displayName` でなく `name` を使用。 var cylinder = GameObject.Find("Cylinder"); diff --git a/LocalPackages/com.nowsprinting.local-package-sample/Tests/Runtime/LocalPackageSample.Tests.asmdef b/LocalPackages/com.nowsprinting.local-package-sample/Tests/Runtime/LocalPackageSample.Tests.asmdef index 8b38027..656c0c0 100644 --- a/LocalPackages/com.nowsprinting.local-package-sample/Tests/Runtime/LocalPackageSample.Tests.asmdef +++ b/LocalPackages/com.nowsprinting.local-package-sample/Tests/Runtime/LocalPackageSample.Tests.asmdef @@ -4,6 +4,7 @@ "references": [ "UnityEngine.TestRunner", "UnityEditor.TestRunner", + "TestHelper", "LocalPackageSample" ], "includePlatforms": [], diff --git a/LocalPackages/com.nowsprinting.local-package-sample/Tests/Runtime/SceneManagerTest.cs b/LocalPackages/com.nowsprinting.local-package-sample/Tests/Runtime/SceneManagerTest.cs index 4b0d051..0a49f64 100644 --- a/LocalPackages/com.nowsprinting.local-package-sample/Tests/Runtime/SceneManagerTest.cs +++ b/LocalPackages/com.nowsprinting.local-package-sample/Tests/Runtime/SceneManagerTest.cs @@ -1,23 +1,22 @@ -// Copyright (c) 2021 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. using System.Collections; using NUnit.Framework; -using LocalPackageSample.Utils; +using TestHelper.Attributes; using UnityEngine; using UnityEngine.TestTools; -// ReSharper disable once CheckNamespace (rootNamespace not work in Unity 2019) namespace LocalPackageSample { [TestFixture] public class SceneManagerTest { [UnityTest] + [LoadScene("../../Scenes/SceneInLocalPackage.unity")] public IEnumerator LoadSceneAsync_ScenesInBuildに含まれていないSceneをロードする例() { - yield return TestSceneLoader.LoadSceneAsync("Packages/com.nowsprinting.local-package-sample/Scenes/SceneInPackage.unity"); - // パスはProjectウィンドウに表示されるパスで指定。ただしパッケージ名の部分は `displayName` でなく `name` を使用。 + yield return null; var cylinder = GameObject.Find("Cylinder"); Assert.That(cylinder, Is.Not.Null); diff --git a/LocalPackages/com.nowsprinting.local-package-sample/Tests/Runtime/Utils.meta b/LocalPackages/com.nowsprinting.local-package-sample/Tests/Runtime/Utils.meta deleted file mode 100644 index 088b90c..0000000 --- a/LocalPackages/com.nowsprinting.local-package-sample/Tests/Runtime/Utils.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: cc53feb1308604ddeb5461135729714f -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/LocalPackages/com.nowsprinting.local-package-sample/Tests/Runtime/Utils/TestSceneLoader.cs b/LocalPackages/com.nowsprinting.local-package-sample/Tests/Runtime/Utils/TestSceneLoader.cs deleted file mode 100644 index d9ba585..0000000 --- a/LocalPackages/com.nowsprinting.local-package-sample/Tests/Runtime/Utils/TestSceneLoader.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2021 Koji Hasegawa. -// This software is released under the MIT License. - -using System.Collections; -using UnityEngine; -using UnityEngine.SceneManagement; - -// ReSharper disable once CheckNamespace (rootNamespace not work in Unity 2019) -namespace LocalPackageSample.Utils -{ - public static class TestSceneLoader - { - /// - /// Play Modeテスト内でSceneをロードする - /// - /// - /// エディター実行では でロード。 - /// プレイヤー実行では を使用して - /// 一時的にビルド対象に含めている前提で でロードしています。 - /// - /// Packages/〜.unityまでのパスで指定 - /// - public static IEnumerator LoadSceneAsync(string path) - { - AsyncOperation loadSceneAsync = null; -#if UNITY_EDITOR - // Use EditorSceneManager at run on Unity-editor - loadSceneAsync = UnityEditor.SceneManagement.EditorSceneManager.LoadSceneAsyncInPlayMode( - path, - new LoadSceneParameters(LoadSceneMode.Single)); -#else - // Use ITestPlayerBuildModifier to change the "Scenes in Build" list before run on player - // see: Editor/BuildAllScenesForTestPlayer.cs - loadSceneAsync = SceneManager.LoadSceneAsync(path); -#endif - yield return loadSceneAsync; - } - } -} diff --git a/LocalPackages/com.nowsprinting.local-package-sample/Tests/Runtime/Utils/TestSceneLoader.cs.meta b/LocalPackages/com.nowsprinting.local-package-sample/Tests/Runtime/Utils/TestSceneLoader.cs.meta deleted file mode 100644 index 1b93d12..0000000 --- a/LocalPackages/com.nowsprinting.local-package-sample/Tests/Runtime/Utils/TestSceneLoader.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: fbd3c4354ca3f43888ce0d331ea0099d -timeCreated: 1622684487 \ No newline at end of file diff --git a/Packages/com.nowsprinting.embedded-package-sample/Scripts/Editor.meta b/Packages/com.nowsprinting.embedded-package-sample/Editor.meta similarity index 100% rename from Packages/com.nowsprinting.embedded-package-sample/Scripts/Editor.meta rename to Packages/com.nowsprinting.embedded-package-sample/Editor.meta diff --git a/Packages/com.nowsprinting.embedded-package-sample/Scripts/Editor/EmbeddedPackageSample.Editor.asmdef b/Packages/com.nowsprinting.embedded-package-sample/Editor/EmbeddedPackageSample.Editor.asmdef similarity index 100% rename from Packages/com.nowsprinting.embedded-package-sample/Scripts/Editor/EmbeddedPackageSample.Editor.asmdef rename to Packages/com.nowsprinting.embedded-package-sample/Editor/EmbeddedPackageSample.Editor.asmdef diff --git a/Packages/com.nowsprinting.embedded-package-sample/Scripts/Editor/EmbeddedPackageSample.Editor.asmdef.meta b/Packages/com.nowsprinting.embedded-package-sample/Editor/EmbeddedPackageSample.Editor.asmdef.meta similarity index 100% rename from Packages/com.nowsprinting.embedded-package-sample/Scripts/Editor/EmbeddedPackageSample.Editor.asmdef.meta rename to Packages/com.nowsprinting.embedded-package-sample/Editor/EmbeddedPackageSample.Editor.asmdef.meta diff --git a/Packages/com.nowsprinting.embedded-package-sample/Scripts/Editor/ExampleForCoverage.cs b/Packages/com.nowsprinting.embedded-package-sample/Editor/ExampleForCoverage.cs similarity index 99% rename from Packages/com.nowsprinting.embedded-package-sample/Scripts/Editor/ExampleForCoverage.cs rename to Packages/com.nowsprinting.embedded-package-sample/Editor/ExampleForCoverage.cs index a0e0d5a..c2a9290 100644 --- a/Packages/com.nowsprinting.embedded-package-sample/Scripts/Editor/ExampleForCoverage.cs +++ b/Packages/com.nowsprinting.embedded-package-sample/Editor/ExampleForCoverage.cs @@ -2,6 +2,7 @@ // This software is released under the MIT License. // ReSharper disable once CheckNamespace (rootNamespace not work in Unity 2019) + namespace EmbeddedPackageSample.Editor { public static class ExampleForCoverage diff --git a/Packages/com.nowsprinting.embedded-package-sample/Scripts/Editor/ExampleForCoverage.cs.meta b/Packages/com.nowsprinting.embedded-package-sample/Editor/ExampleForCoverage.cs.meta similarity index 100% rename from Packages/com.nowsprinting.embedded-package-sample/Scripts/Editor/ExampleForCoverage.cs.meta rename to Packages/com.nowsprinting.embedded-package-sample/Editor/ExampleForCoverage.cs.meta diff --git a/Packages/com.nowsprinting.embedded-package-sample/Scripts/Runtime.meta b/Packages/com.nowsprinting.embedded-package-sample/Runtime.meta similarity index 100% rename from Packages/com.nowsprinting.embedded-package-sample/Scripts/Runtime.meta rename to Packages/com.nowsprinting.embedded-package-sample/Runtime.meta diff --git a/Packages/com.nowsprinting.embedded-package-sample/Scripts/Runtime/EmbeddedPackageSample.asmdef b/Packages/com.nowsprinting.embedded-package-sample/Runtime/EmbeddedPackageSample.asmdef similarity index 100% rename from Packages/com.nowsprinting.embedded-package-sample/Scripts/Runtime/EmbeddedPackageSample.asmdef rename to Packages/com.nowsprinting.embedded-package-sample/Runtime/EmbeddedPackageSample.asmdef diff --git a/Packages/com.nowsprinting.embedded-package-sample/Scripts/Runtime/EmbeddedPackageSample.asmdef.meta b/Packages/com.nowsprinting.embedded-package-sample/Runtime/EmbeddedPackageSample.asmdef.meta similarity index 100% rename from Packages/com.nowsprinting.embedded-package-sample/Scripts/Runtime/EmbeddedPackageSample.asmdef.meta rename to Packages/com.nowsprinting.embedded-package-sample/Runtime/EmbeddedPackageSample.asmdef.meta diff --git a/Packages/com.nowsprinting.embedded-package-sample/Scripts/Runtime/ExampleForCoverage.cs b/Packages/com.nowsprinting.embedded-package-sample/Runtime/ExampleForCoverage.cs similarity index 99% rename from Packages/com.nowsprinting.embedded-package-sample/Scripts/Runtime/ExampleForCoverage.cs rename to Packages/com.nowsprinting.embedded-package-sample/Runtime/ExampleForCoverage.cs index d19405b..2a06411 100644 --- a/Packages/com.nowsprinting.embedded-package-sample/Scripts/Runtime/ExampleForCoverage.cs +++ b/Packages/com.nowsprinting.embedded-package-sample/Runtime/ExampleForCoverage.cs @@ -2,6 +2,7 @@ // This software is released under the MIT License. // ReSharper disable once CheckNamespace (rootNamespace not work in Unity 2019) + namespace EmbeddedPackageSample { public static class ExampleForCoverage diff --git a/Packages/com.nowsprinting.embedded-package-sample/Scripts/Runtime/ExampleForCoverage.cs.meta b/Packages/com.nowsprinting.embedded-package-sample/Runtime/ExampleForCoverage.cs.meta similarity index 100% rename from Packages/com.nowsprinting.embedded-package-sample/Scripts/Runtime/ExampleForCoverage.cs.meta rename to Packages/com.nowsprinting.embedded-package-sample/Runtime/ExampleForCoverage.cs.meta diff --git a/Packages/com.nowsprinting.embedded-package-sample/Scenes/SceneInPackage.unity b/Packages/com.nowsprinting.embedded-package-sample/Scenes/SceneInEmbeddedPackage.unity similarity index 90% rename from Packages/com.nowsprinting.embedded-package-sample/Scenes/SceneInPackage.unity rename to Packages/com.nowsprinting.embedded-package-sample/Scenes/SceneInEmbeddedPackage.unity index e207df4..0f47e54 100644 --- a/Packages/com.nowsprinting.embedded-package-sample/Scenes/SceneInPackage.unity +++ b/Packages/com.nowsprinting.embedded-package-sample/Scenes/SceneInEmbeddedPackage.unity @@ -13,7 +13,7 @@ OcclusionCullingSettings: --- !u!104 &2 RenderSettings: m_ObjectHideFlags: 0 - serializedVersion: 9 + serializedVersion: 10 m_Fog: 0 m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1} m_FogMode: 3 @@ -38,13 +38,12 @@ RenderSettings: m_ReflectionIntensity: 1 m_CustomReflection: {fileID: 0} m_Sun: {fileID: 0} - m_IndirectSpecularColor: {r: 0.44657838, g: 0.49641234, b: 0.57481676, a: 1} m_UseRadianceAmbientProbe: 0 --- !u!157 &3 LightmapSettings: m_ObjectHideFlags: 0 - serializedVersion: 12 - m_GIWorkflowMode: 1 + serializedVersion: 13 + m_BakeOnSceneLoad: 0 m_GISettings: serializedVersion: 2 m_BounceScale: 1 @@ -67,9 +66,6 @@ LightmapSettings: m_LightmapParameters: {fileID: 0} m_LightmapsBakeMode: 1 m_TextureCompression: 1 - m_FinalGather: 0 - m_FinalGatherFiltering: 1 - m_FinalGatherRayCount: 256 m_ReflectionCompression: 2 m_MixedBakeMode: 2 m_BakeBackend: 1 @@ -104,7 +100,7 @@ NavMeshSettings: serializedVersion: 2 m_ObjectHideFlags: 0 m_BuildSettings: - serializedVersion: 2 + serializedVersion: 3 agentTypeID: 0 agentRadius: 0.5 agentHeight: 2 @@ -117,7 +113,7 @@ NavMeshSettings: cellSize: 0.16666667 manualTileSize: 0 tileSize: 256 - accuratePlacement: 0 + buildHeightMesh: 0 maxJobWorkers: 0 preserveTilesOutsideBounds: 0 debug: @@ -150,8 +146,17 @@ CapsuleCollider: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 340338593} m_Material: {fileID: 0} + m_IncludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_ExcludeLayers: + serializedVersion: 2 + m_Bits: 0 + m_LayerOverridePriority: 0 m_IsTrigger: 0 + m_ProvidesContacts: 0 m_Enabled: 1 + serializedVersion: 2 m_Radius: 0.5 m_Height: 2 m_Direction: 1 @@ -167,11 +172,15 @@ MeshRenderer: m_CastShadows: 1 m_ReceiveShadows: 1 m_DynamicOccludee: 1 + m_StaticShadowCaster: 0 m_MotionVectors: 1 m_LightProbeUsage: 1 m_ReflectionProbeUsage: 1 m_RayTracingMode: 2 m_RayTraceProcedural: 0 + m_RayTracingAccelStructBuildFlagsOverride: 0 + m_RayTracingAccelStructBuildFlags: 1 + m_SmallMeshCulling: 1 m_RenderingLayerMask: 1 m_RendererPriority: 0 m_Materials: @@ -212,12 +221,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 340338593} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} - m_LocalPosition: {x: 924.2142, y: 351.34674, z: -17.195045} + m_LocalPosition: {x: 0, y: 0, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} - m_RootOrder: 2 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} --- !u!1 &854170358 GameObject: @@ -244,9 +254,8 @@ Light: m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 854170358} m_Enabled: 1 - serializedVersion: 10 + serializedVersion: 11 m_Type: 1 - m_Shape: 0 m_Color: {r: 1, g: 0.95686275, b: 0.8392157, a: 1} m_Intensity: 1 m_Range: 10 @@ -296,8 +305,12 @@ Light: m_BoundingSphereOverride: {x: 0, y: 0, z: 0, w: 0} m_UseBoundingSphereOverride: 0 m_UseViewFrustumForShadowCasterCull: 1 + m_ForceVisible: 0 m_ShadowRadius: 0 m_ShadowAngle: 0 + m_LightUnit: 1 + m_LuxAtDistance: 1 + m_EnableSpotReflector: 1 --- !u!4 &854170360 Transform: m_ObjectHideFlags: 0 @@ -305,12 +318,13 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 854170358} + serializedVersion: 2 m_LocalRotation: {x: 0.40821788, y: -0.23456968, z: 0.10938163, w: 0.8754261} m_LocalPosition: {x: 0, y: 3, z: 0} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} - m_RootOrder: 1 m_LocalEulerAnglesHint: {x: 50, y: -30, z: 0} --- !u!1 &2006839994 GameObject: @@ -352,9 +366,17 @@ Camera: m_projectionMatrixMode: 1 m_GateFitMode: 2 m_FOVAxisMode: 0 + m_Iso: 200 + m_ShutterSpeed: 0.005 + m_Aperture: 16 + m_FocusDistance: 10 + m_FocalLength: 50 + m_BladeCount: 5 + m_Curvature: {x: 2, y: 11} + m_BarrelClipping: 0.25 + m_Anamorphism: 0 m_SensorSize: {x: 36, y: 24} m_LensShift: {x: 0, y: 0} - m_FocalLength: 50 m_NormalizedViewPortRect: serializedVersion: 2 x: 0 @@ -388,10 +410,18 @@ Transform: m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 2006839994} + serializedVersion: 2 m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 1, z: -10} m_LocalScale: {x: 1, y: 1, z: 1} + m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 0} - m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!1660057539 &9223372036854775807 +SceneRoots: + m_ObjectHideFlags: 0 + m_Roots: + - {fileID: 2006839997} + - {fileID: 854170360} + - {fileID: 340338597} diff --git a/Packages/com.nowsprinting.embedded-package-sample/Scenes/SceneInPackage.unity.meta b/Packages/com.nowsprinting.embedded-package-sample/Scenes/SceneInEmbeddedPackage.unity.meta similarity index 100% rename from Packages/com.nowsprinting.embedded-package-sample/Scenes/SceneInPackage.unity.meta rename to Packages/com.nowsprinting.embedded-package-sample/Scenes/SceneInEmbeddedPackage.unity.meta diff --git a/Packages/com.nowsprinting.embedded-package-sample/Scripts.meta b/Packages/com.nowsprinting.embedded-package-sample/Scripts.meta deleted file mode 100644 index 1de877f..0000000 --- a/Packages/com.nowsprinting.embedded-package-sample/Scripts.meta +++ /dev/null @@ -1,8 +0,0 @@ -fileFormatVersion: 2 -guid: 22670d83d504b4ab1918d0d4765056a3 -folderAsset: yes -DefaultImporter: - externalObjects: {} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/com.nowsprinting.embedded-package-sample/Scripts/Editor/BuildAllScenesForTestPlayer.cs b/Packages/com.nowsprinting.embedded-package-sample/Scripts/Editor/BuildAllScenesForTestPlayer.cs deleted file mode 100644 index cbcc3bd..0000000 --- a/Packages/com.nowsprinting.embedded-package-sample/Scripts/Editor/BuildAllScenesForTestPlayer.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2021 Koji Hasegawa. -// This software is released under the MIT License. - -using System.Collections.Generic; -using System.Linq; -using EmbeddedPackageSample.Editor; -using UnityEditor; -using UnityEditor.TestTools; - -[assembly: TestPlayerBuildModifier(typeof(BuildAllScenesForTestPlayer))] - -// ReSharper disable once CheckNamespace (rootNamespace not work in Unity 2019) -namespace EmbeddedPackageSample.Editor -{ - /// - /// プレイヤーでのテスト実行前のビルドで、"Scenes in Build"に指定されていないSceneを一時的にビルドに含めます。 - /// これによって、テスト内で を使用してSceneをロードできるようになります。 - /// - /// - /// このスクリプトの利用には、Unity Test Frameworkパッケージ v1.1.13以上が必要です。 - /// 詳細は フォーラムの報告 を参照してください。 - /// - public class BuildAllScenesForTestPlayer : ITestPlayerBuildModifier - { - public BuildPlayerOptions ModifyOptions(BuildPlayerOptions playerOptions) - { - var buildSceneList = new List(playerOptions.scenes); - foreach (var scene in AssetDatabase - .FindAssets("t:SceneAsset", new [] { "Packages/com.nowsprinting.embedded-package-sample" }) - .Select(AssetDatabase.GUIDToAssetPath)) - { - if (!buildSceneList.Contains(scene)) - { - buildSceneList.Add(scene); - } - } - // 引数で渡される `playerOptions.scenes` に入っているSceneの順序を変えると、テストが起動しないことがあります。 - // そのため、不足しているSceneだけを後ろに追加しています。 - - playerOptions.scenes = buildSceneList.ToArray(); - - return playerOptions; - } - } -} diff --git a/Packages/com.nowsprinting.embedded-package-sample/Scripts/Editor/BuildAllScenesForTestPlayer.cs.meta b/Packages/com.nowsprinting.embedded-package-sample/Scripts/Editor/BuildAllScenesForTestPlayer.cs.meta deleted file mode 100644 index 2f38e5c..0000000 --- a/Packages/com.nowsprinting.embedded-package-sample/Scripts/Editor/BuildAllScenesForTestPlayer.cs.meta +++ /dev/null @@ -1,11 +0,0 @@ -fileFormatVersion: 2 -guid: 6cd4b04aeeb6c48e0a272ed129f0ebb8 -MonoImporter: - externalObjects: {} - serializedVersion: 2 - defaultReferences: [] - executionOrder: 0 - icon: {instanceID: 0} - userData: - assetBundleName: - assetBundleVariant: diff --git a/Packages/com.nowsprinting.embedded-package-sample/Tests/Editor/EditorSceneManagerTest.cs b/Packages/com.nowsprinting.embedded-package-sample/Tests/Editor/EditorSceneManagerTest.cs index 43c2e70..bcfaf95 100644 --- a/Packages/com.nowsprinting.embedded-package-sample/Tests/Editor/EditorSceneManagerTest.cs +++ b/Packages/com.nowsprinting.embedded-package-sample/Tests/Editor/EditorSceneManagerTest.cs @@ -1,11 +1,10 @@ -// Copyright (c) 2021 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. using NUnit.Framework; using UnityEditor.SceneManagement; using UnityEngine; -// ReSharper disable once CheckNamespace (rootNamespace not work in Unity 2019) namespace EmbeddedPackageSample.Editor { [TestFixture] @@ -14,7 +13,8 @@ public class EditorSceneManagerTest [Test] public void OpenScene_Sceneファイルをロードしてテストを実行する例() { - EditorSceneManager.OpenScene("Packages/com.nowsprinting.embedded-package-sample/Scenes/SceneInPackage.unity"); + EditorSceneManager.OpenScene( + "Packages/com.nowsprinting.embedded-package-sample/Scenes/SceneInEmbeddedPackage.unity"); // パスはProjectウィンドウに表示されるパスで指定。ただしパッケージ名の部分は `displayName` でなく `name` を使用。 var capsule = GameObject.Find("Capsule"); diff --git a/Packages/com.nowsprinting.embedded-package-sample/Tests/Runtime/EmbeddedPackageSample.Tests.asmdef b/Packages/com.nowsprinting.embedded-package-sample/Tests/Runtime/EmbeddedPackageSample.Tests.asmdef index 52774ef..dd965bc 100644 --- a/Packages/com.nowsprinting.embedded-package-sample/Tests/Runtime/EmbeddedPackageSample.Tests.asmdef +++ b/Packages/com.nowsprinting.embedded-package-sample/Tests/Runtime/EmbeddedPackageSample.Tests.asmdef @@ -4,6 +4,7 @@ "references": [ "UnityEngine.TestRunner", "UnityEditor.TestRunner", + "TestHelper", "EmbeddedPackageSample" ], "includePlatforms": [], diff --git a/Packages/com.nowsprinting.embedded-package-sample/Tests/Runtime/SceneManagerTest.cs b/Packages/com.nowsprinting.embedded-package-sample/Tests/Runtime/SceneManagerTest.cs index 2869353..9e6b45f 100644 --- a/Packages/com.nowsprinting.embedded-package-sample/Tests/Runtime/SceneManagerTest.cs +++ b/Packages/com.nowsprinting.embedded-package-sample/Tests/Runtime/SceneManagerTest.cs @@ -1,23 +1,22 @@ -// Copyright (c) 2021 Koji Hasegawa. +// Copyright (c) 2021-2025 Koji Hasegawa. // This software is released under the MIT License. using System.Collections; using NUnit.Framework; -using EmbeddedPackageSample.Utils; +using TestHelper.Attributes; using UnityEngine; using UnityEngine.TestTools; -// ReSharper disable once CheckNamespace (rootNamespace not work in Unity 2019) namespace EmbeddedPackageSample { [TestFixture] public class SceneManagerTest { [UnityTest] + [LoadScene("../../Scenes/SceneInEmbeddedPackage.unity")] public IEnumerator LoadSceneAsync_ScenesInBuildに含まれていないSceneをロードする例() { - yield return TestSceneLoader.LoadSceneAsync("Packages/com.nowsprinting.embedded-package-sample/Scenes/SceneInPackage.unity"); - // パスはProjectウィンドウに表示されるパスで指定。ただしパッケージ名の部分は `displayName` でなく `name` を使用。 + yield return null; var capsule = GameObject.Find("Capsule"); Assert.That(capsule, Is.Not.Null); diff --git a/Packages/com.nowsprinting.embedded-package-sample/Tests/Runtime/Utils.meta b/Packages/com.nowsprinting.embedded-package-sample/Tests/Runtime/Utils.meta deleted file mode 100644 index 22f1b24..0000000 --- a/Packages/com.nowsprinting.embedded-package-sample/Tests/Runtime/Utils.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: 3d0e241336b74cdf8c8522920f18335c -timeCreated: 1624820735 \ No newline at end of file diff --git a/Packages/com.nowsprinting.embedded-package-sample/Tests/Runtime/Utils/TestSceneLoader.cs b/Packages/com.nowsprinting.embedded-package-sample/Tests/Runtime/Utils/TestSceneLoader.cs deleted file mode 100644 index e7be62b..0000000 --- a/Packages/com.nowsprinting.embedded-package-sample/Tests/Runtime/Utils/TestSceneLoader.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2021 Koji Hasegawa. -// This software is released under the MIT License. - -using System.Collections; -using UnityEngine; -using UnityEngine.SceneManagement; - -// ReSharper disable once CheckNamespace (rootNamespace not work in Unity 2019) -namespace EmbeddedPackageSample.Utils -{ - public static class TestSceneLoader - { - /// - /// Play Modeテスト内でSceneをロードする - /// - /// - /// エディター実行では でロード。 - /// プレイヤー実行では を使用して - /// 一時的にビルド対象に含めている前提で でロードしています。 - /// - /// Packages/〜.unityまでのパスで指定 - /// - public static IEnumerator LoadSceneAsync(string path) - { - AsyncOperation loadSceneAsync = null; -#if UNITY_EDITOR - // Use EditorSceneManager at run on Unity-editor - loadSceneAsync = UnityEditor.SceneManagement.EditorSceneManager.LoadSceneAsyncInPlayMode( - path, - new LoadSceneParameters(LoadSceneMode.Single)); -#else - // Use ITestPlayerBuildModifier to change the "Scenes in Build" list before run on player - // see: Editor/BuildAllScenesForTestPlayer.cs - loadSceneAsync = SceneManager.LoadSceneAsync(path); -#endif - yield return loadSceneAsync; - } - } -} diff --git a/Packages/com.nowsprinting.embedded-package-sample/Tests/Runtime/Utils/TestSceneLoader.cs.meta b/Packages/com.nowsprinting.embedded-package-sample/Tests/Runtime/Utils/TestSceneLoader.cs.meta deleted file mode 100644 index edca484..0000000 --- a/Packages/com.nowsprinting.embedded-package-sample/Tests/Runtime/Utils/TestSceneLoader.cs.meta +++ /dev/null @@ -1,3 +0,0 @@ -fileFormatVersion: 2 -guid: bc4f3762b438406bbcd3ee6f6d41f32e -timeCreated: 1624820745 \ No newline at end of file diff --git a/Packages/manifest.json b/Packages/manifest.json index 6f8ac7f..a93354f 100644 --- a/Packages/manifest.json +++ b/Packages/manifest.json @@ -1,18 +1,17 @@ { "dependencies": { - "com.cysharp.unitask": "2.5.0", - "com.nowsprinting.create-script-folders-with-tests": "1.2.1", + "com.cysharp.unitask": "2.5.10", + "com.nowsprinting.create-script-folders-with-tests": "1.3.0", "com.nowsprinting.local-package-sample": "file:../LocalPackages/com.nowsprinting.local-package-sample", - "com.nowsprinting.test-helper": "0.3.0", - "com.nowsprinting.test-helper.input": "1.0.0", - "com.nowsprinting.test-helper.monkey": "0.5.1", - "com.nowsprinting.test-helper.random": "0.2.0", + "com.nowsprinting.test-helper": "1.3.2", + "com.nowsprinting.test-helper.input": "1.0.1", + "com.nowsprinting.test-helper.random": "1.1.0", + "com.nowsprinting.test-helper.ui": "1.1.3", "com.unity.collab-proxy": "1.14.18", "com.unity.ide.rider": "3.0.34", "com.unity.ide.visualstudio": "2.0.22", "com.unity.inputsystem": "1.7.0", "com.unity.test-framework": "1.4.6", - "com.unity.testframework.graphics": "7.17.0-exp.1", "com.unity.testtools.codecoverage": "1.2.4", "com.unity.textmeshpro": "2.1.6", "com.unity.timeline": "1.2.18", diff --git a/Packages/packages-lock.json b/Packages/packages-lock.json index 7423698..d39fe08 100644 --- a/Packages/packages-lock.json +++ b/Packages/packages-lock.json @@ -1,14 +1,14 @@ { "dependencies": { "com.cysharp.unitask": { - "version": "2.5.0", + "version": "2.5.10", "depth": 0, "source": "registry", "dependencies": {}, "url": "https://package.openupm.com" }, "com.nowsprinting.create-script-folders-with-tests": { - "version": "1.2.1", + "version": "1.3.0", "depth": 0, "source": "registry", "dependencies": {}, @@ -27,8 +27,8 @@ "dependencies": {} }, "com.nowsprinting.test-helper": { - "version": "0.4.2", - "depth": 1, + "version": "1.3.2", + "depth": 0, "source": "registry", "dependencies": { "com.unity.test-framework": "1.3.4" @@ -36,29 +36,29 @@ "url": "https://package.openupm.com" }, "com.nowsprinting.test-helper.input": { - "version": "1.0.0", + "version": "1.0.1", "depth": 0, "source": "registry", "dependencies": {}, "url": "https://package.openupm.com" }, - "com.nowsprinting.test-helper.monkey": { - "version": "0.5.1", + "com.nowsprinting.test-helper.random": { + "version": "1.1.0", "depth": 0, "source": "registry", - "dependencies": { - "com.cysharp.unitask": "2.3.3", - "com.nowsprinting.test-helper": "0.4.2", - "com.nowsprinting.test-helper.random": "0.2.0", - "com.unity.ugui": "1.0.0" - }, + "dependencies": {}, "url": "https://package.openupm.com" }, - "com.nowsprinting.test-helper.random": { - "version": "0.2.0", + "com.nowsprinting.test-helper.ui": { + "version": "1.1.3", "depth": 0, "source": "registry", - "dependencies": {}, + "dependencies": { + "com.cysharp.unitask": "2.3.3", + "com.nowsprinting.test-helper": "1.3.1", + "com.nowsprinting.test-helper.random": "1.1.0", + "com.unity.ugui": "1.0.0" + }, "url": "https://package.openupm.com" }, "com.unity.addressables": { @@ -164,23 +164,6 @@ }, "url": "https://packages.unity.com" }, - "com.unity.testframework.graphics": { - "version": "7.17.0-exp.1", - "depth": 0, - "source": "registry", - "dependencies": { - "com.unity.modules.vr": "1.0.0", - "com.unity.modules.xr": "1.0.0", - "com.unity.addressables": "1.17.15", - "com.unity.xr.management": "4.0.5", - "com.unity.nuget.newtonsoft-json": "2.0.0", - "com.unity.xr.legacyinputhelpers": "2.1.8", - "com.unity.external.test-protocol": "1.0.0-preview", - "com.unity.testtools.codecoverage": "1.2.0", - "com.unity.modules.imageconversion": "1.0.0" - }, - "url": "https://packages.unity.com" - }, "com.unity.testtools.codecoverage": { "version": "1.2.4", "depth": 0, @@ -221,29 +204,6 @@ "com.unity.modules.imgui": "1.0.0" } }, - "com.unity.xr.legacyinputhelpers": { - "version": "2.1.9", - "depth": 1, - "source": "registry", - "dependencies": { - "com.unity.modules.vr": "1.0.0", - "com.unity.modules.xr": "1.0.0" - }, - "url": "https://packages.unity.com" - }, - "com.unity.xr.management": { - "version": "4.0.5", - "depth": 1, - "source": "registry", - "dependencies": { - "com.unity.modules.vr": "1.0.0", - "com.unity.modules.xr": "1.0.0", - "com.unity.modules.subsystems": "1.0.0", - "com.unity.subsystemregistration": "1.0.6", - "com.unity.xr.legacyinputhelpers": "2.1.7" - }, - "url": "https://packages.unity.com" - }, "net.tnrd.nsubstitute": { "version": "4.2.2", "depth": 0, diff --git a/ProjectSettings/EditorBuildSettings.asset b/ProjectSettings/EditorBuildSettings.asset index 6c643e9..06220e9 100644 --- a/ProjectSettings/EditorBuildSettings.asset +++ b/ProjectSettings/EditorBuildSettings.asset @@ -5,9 +5,6 @@ EditorBuildSettings: m_ObjectHideFlags: 0 serializedVersion: 2 m_Scenes: - - enabled: 1 - path: Assets/BasicExample/Scenes/HelloTesting.unity - guid: 6c40ba2f8a021430aa36a5cd247cda1e - enabled: 1 path: Assets/UGUIExample/Scenes/Login.unity guid: e961a5fcab8254ba686099f605955a02 @@ -27,3 +24,4 @@ EditorBuildSettings: path: Assets/InputSystemExample/Scenes/InputSystemExample.unity guid: 780082c79f65c4193aeff19ec9b21382 m_configObjects: {} + m_UseUCBPForAssetBundles: 0 diff --git a/ProjectSettings/ProjectSettings.asset b/ProjectSettings/ProjectSettings.asset index 549aad2..798cd3e 100644 --- a/ProjectSettings/ProjectSettings.asset +++ b/ProjectSettings/ProjectSettings.asset @@ -275,7 +275,196 @@ PlayerSettings: AndroidValidateAppBundleSize: 1 AndroidAppBundleSizeToValidate: 150 m_BuildTargetIcons: [] - m_BuildTargetPlatformIcons: [] + m_BuildTargetPlatformIcons: + - m_BuildTarget: iPhone + m_Icons: + - m_Textures: [] + m_Width: 180 + m_Height: 180 + m_Kind: 0 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 120 + m_Height: 120 + m_Kind: 0 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 167 + m_Height: 167 + m_Kind: 0 + m_SubKind: iPad + - m_Textures: [] + m_Width: 152 + m_Height: 152 + m_Kind: 0 + m_SubKind: iPad + - m_Textures: [] + m_Width: 76 + m_Height: 76 + m_Kind: 0 + m_SubKind: iPad + - m_Textures: [] + m_Width: 120 + m_Height: 120 + m_Kind: 3 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 80 + m_Height: 80 + m_Kind: 3 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 80 + m_Height: 80 + m_Kind: 3 + m_SubKind: iPad + - m_Textures: [] + m_Width: 40 + m_Height: 40 + m_Kind: 3 + m_SubKind: iPad + - m_Textures: [] + m_Width: 87 + m_Height: 87 + m_Kind: 1 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 58 + m_Height: 58 + m_Kind: 1 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 29 + m_Height: 29 + m_Kind: 1 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 58 + m_Height: 58 + m_Kind: 1 + m_SubKind: iPad + - m_Textures: [] + m_Width: 29 + m_Height: 29 + m_Kind: 1 + m_SubKind: iPad + - m_Textures: [] + m_Width: 60 + m_Height: 60 + m_Kind: 2 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 40 + m_Height: 40 + m_Kind: 2 + m_SubKind: iPhone + - m_Textures: [] + m_Width: 40 + m_Height: 40 + m_Kind: 2 + m_SubKind: iPad + - m_Textures: [] + m_Width: 20 + m_Height: 20 + m_Kind: 2 + m_SubKind: iPad + - m_Textures: [] + m_Width: 1024 + m_Height: 1024 + m_Kind: 4 + m_SubKind: App Store + - m_BuildTarget: Android + m_Icons: + - m_Textures: [] + m_Width: 432 + m_Height: 432 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 324 + m_Height: 324 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 216 + m_Height: 216 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 162 + m_Height: 162 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 108 + m_Height: 108 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 81 + m_Height: 81 + m_Kind: 2 + m_SubKind: + - m_Textures: [] + m_Width: 192 + m_Height: 192 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 144 + m_Height: 144 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 96 + m_Height: 96 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 72 + m_Height: 72 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 48 + m_Height: 48 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 36 + m_Height: 36 + m_Kind: 1 + m_SubKind: + - m_Textures: [] + m_Width: 192 + m_Height: 192 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 144 + m_Height: 144 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 96 + m_Height: 96 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 72 + m_Height: 72 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 48 + m_Height: 48 + m_Kind: 0 + m_SubKind: + - m_Textures: [] + m_Width: 36 + m_Height: 36 + m_Kind: 0 + m_SubKind: m_BuildTargetBatching: - m_BuildTarget: Standalone m_StaticBatching: 1 diff --git a/README.md b/README.md index c8de54a..badcaae 100644 --- a/README.md +++ b/README.md @@ -75,8 +75,8 @@ Assets     │   └── (snip)     └── Tests     ├── Editor -    │   └── AssetValidators -    │      ├── LevelValidator.cs +    │   └── AssetValidators // 「8.4 ValueSource」「10.1 Edit ModeテストでのSceneの使用」 +    │      ├── LevelValidator.cs     │      └── RaceValidator.cs     └── Runtime     └── Entities @@ -110,18 +110,18 @@ Assets 第11章 UPM パッケージのテスト -#### 埋め込みパッケージ +#### ローカルパッケージ ``` -Packages -└── com.nowsprinting.embedded-package-sample +LocalPackages +└── com.nowsprinting.local-package-sample ``` -#### ローカルパッケージ +#### 埋め込みパッケージ ``` -LocalPackages -└── com.nowsprinting.local-package-sample +Packages +└── com.nowsprinting.embedded-package-sample ``` ### UGUIExample @@ -160,6 +160,10 @@ Assets └── VisualRegressionExample ``` +> [!TIP] +> このテストを実行するには +> [Graphics Test Framework](https://docs.unity3d.com/Packages/com.unity.testframework.graphics@latest) +> パッケージをインストールする必要があります。 ## 備考