From ccf5c1cf1e6329b658cdf56059495e650a32c7e7 Mon Sep 17 00:00:00 2001 From: swrring Date: Thu, 23 Apr 2026 23:50:20 +0900 Subject: [PATCH] =?UTF-8?q?auto:=202026-04-23=2023:50=20=C2=B7=20scene:=20?= =?UTF-8?q?SampleScene=20=C2=B7=207=20files?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...Enemy.prefab.bak_20260423_2334.prefab.meta | 7 +++ ...layer.prefab.bak_20260423_2334.prefab.meta | 7 +++ Assets/Tests.meta | 8 +++ Assets/Tests/Editor.meta | 8 +++ .../EerieVillage.Tests.Editor.asmdef.meta | 7 +++ Assets/Tests/Editor/PlayerAttackTests.cs | 58 +++++++++++++++---- Assets/Tests/Editor/PlayerAttackTests.cs.meta | 2 + 7 files changed, 86 insertions(+), 11 deletions(-) create mode 100644 Assets/Prefabs/Enemy.prefab.bak_20260423_2334.prefab.meta create mode 100644 Assets/Prefabs/Player.prefab.bak_20260423_2334.prefab.meta create mode 100644 Assets/Tests.meta create mode 100644 Assets/Tests/Editor.meta create mode 100644 Assets/Tests/Editor/EerieVillage.Tests.Editor.asmdef.meta create mode 100644 Assets/Tests/Editor/PlayerAttackTests.cs.meta diff --git a/Assets/Prefabs/Enemy.prefab.bak_20260423_2334.prefab.meta b/Assets/Prefabs/Enemy.prefab.bak_20260423_2334.prefab.meta new file mode 100644 index 0000000..9281aae --- /dev/null +++ b/Assets/Prefabs/Enemy.prefab.bak_20260423_2334.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5d1f69485eb8e2b4db40eb9214a5e509 +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Prefabs/Player.prefab.bak_20260423_2334.prefab.meta b/Assets/Prefabs/Player.prefab.bak_20260423_2334.prefab.meta new file mode 100644 index 0000000..265fdca --- /dev/null +++ b/Assets/Prefabs/Player.prefab.bak_20260423_2334.prefab.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3d8b54c71c06ca5459e229a72131fb6d +PrefabImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Tests.meta b/Assets/Tests.meta new file mode 100644 index 0000000..16b168b --- /dev/null +++ b/Assets/Tests.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: cd426253ef84977439ab24888e4b8eb4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Tests/Editor.meta b/Assets/Tests/Editor.meta new file mode 100644 index 0000000..268e4e9 --- /dev/null +++ b/Assets/Tests/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c52452b409b057746a10436cbfc9e04b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Tests/Editor/EerieVillage.Tests.Editor.asmdef.meta b/Assets/Tests/Editor/EerieVillage.Tests.Editor.asmdef.meta new file mode 100644 index 0000000..6a9fffa --- /dev/null +++ b/Assets/Tests/Editor/EerieVillage.Tests.Editor.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4e0b3a471538c044b8615276aaa65ba0 +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Tests/Editor/PlayerAttackTests.cs b/Assets/Tests/Editor/PlayerAttackTests.cs index faa16ad..06ce921 100644 --- a/Assets/Tests/Editor/PlayerAttackTests.cs +++ b/Assets/Tests/Editor/PlayerAttackTests.cs @@ -1,3 +1,4 @@ +using System.Linq; using NUnit.Framework; using UnityEngine; using UnityEditor; @@ -6,19 +7,48 @@ using UnityEditor; /// EerieVillage BT5-Dev 2단계 — Player 근거리 공격 체계 EditMode 테스트. /// Prefab 자산의 컴포넌트 구성이 기획 04 §5-1 (근거리 공격 1종) 을 충족하는지 검증. /// Play 모드 실행 불요 — prefab YAML 직렬화 상태를 직접 검증하여 회귀 방지. +/// +/// 2026-04-23 개정: Platformer.* 네임스페이스 직접 참조 제거 (Scripts/ 하위에 asmdef 부재로 +/// 테스트 어셈블리가 Assembly-CSharp 를 참조 불가한 구조 — reflection 기반으로 전환). /// public class PlayerAttackTests { const string PlayerPrefabPath = "Assets/Prefabs/Player.prefab"; const string EnemyPrefabPath = "Assets/Prefabs/Enemy.prefab"; + // Platformer.* 는 Assembly-CSharp 에 속함. 테스트 어셈블리에서 직접 타입 참조 불가하므로 + // GetComponents() + GetType().FullName 매칭으로 검증. + const string AttackHitboxType = "Platformer.Mechanics.AttackHitbox"; + const string HealthType = "Platformer.Mechanics.Health"; + const string PlayerControllerType = "Platformer.Mechanics.PlayerController"; + const string EnemyControllerType = "Platformer.Mechanics.EnemyController"; + + static Component FindComponentByFullName(GameObject go, string fullName) + { + if (go == null) return null; + return go.GetComponents() + .FirstOrDefault(c => c != null && c.GetType().FullName == fullName); + } + + static object GetFieldOrProperty(object obj, string memberName) + { + if (obj == null) return null; + var t = obj.GetType(); + var field = t.GetField(memberName, + System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); + if (field != null) return field.GetValue(obj); + var prop = t.GetProperty(memberName, + System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); + return prop?.GetValue(obj); + } + [Test] public void Player_Prefab_Has_AttackHitbox_Component() { var prefab = AssetDatabase.LoadAssetAtPath(PlayerPrefabPath); Assert.IsNotNull(prefab, $"Player.prefab not found at {PlayerPrefabPath}"); - var hitbox = prefab.GetComponent(); + var hitbox = FindComponentByFullName(prefab, AttackHitboxType); Assert.IsNotNull(hitbox, "Player.prefab에 AttackHitbox 컴포넌트가 누락. " + "BT5-Dev 2단계 재위임 집행분 (2026-04-23) 이 prefab YAML 에 반영되어야 함."); @@ -30,7 +60,7 @@ public class PlayerAttackTests var prefab = AssetDatabase.LoadAssetAtPath(PlayerPrefabPath); Assert.IsNotNull(prefab, $"Player.prefab not found at {PlayerPrefabPath}"); - var health = prefab.GetComponent(); + var health = FindComponentByFullName(prefab, HealthType); Assert.IsNotNull(health, "Player.prefab 에 Health 컴포넌트 누락 (템플릿 기본)."); } @@ -40,7 +70,7 @@ public class PlayerAttackTests var prefab = AssetDatabase.LoadAssetAtPath(PlayerPrefabPath); Assert.IsNotNull(prefab); - var controller = prefab.GetComponent(); + var controller = FindComponentByFullName(prefab, PlayerControllerType); Assert.IsNotNull(controller, "Player.prefab 에 PlayerController 컴포넌트 누락."); } @@ -48,10 +78,12 @@ public class PlayerAttackTests public void AttackHitbox_Default_Damage_Is_One() { var prefab = AssetDatabase.LoadAssetAtPath(PlayerPrefabPath); - var hitbox = prefab.GetComponent(); + var hitbox = FindComponentByFullName(prefab, AttackHitboxType); Assert.IsNotNull(hitbox); - Assert.AreEqual(1, hitbox.damage, + var damage = GetFieldOrProperty(hitbox, "damage"); + Assert.IsNotNull(damage, "AttackHitbox.damage 필드/프로퍼티 접근 불가"); + Assert.AreEqual(1, System.Convert.ToInt32(damage), "기본 대미지 1 (기획 04 §5-1, Phase 3-B 튠 전 파일럿 값)."); } @@ -59,10 +91,12 @@ public class PlayerAttackTests public void AttackHitbox_Active_Duration_Is_Positive() { var prefab = AssetDatabase.LoadAssetAtPath(PlayerPrefabPath); - var hitbox = prefab.GetComponent(); + var hitbox = FindComponentByFullName(prefab, AttackHitboxType); Assert.IsNotNull(hitbox); - Assert.Greater(hitbox.activeDuration, 0f, + var duration = GetFieldOrProperty(hitbox, "activeDuration"); + Assert.IsNotNull(duration, "AttackHitbox.activeDuration 필드/프로퍼티 접근 불가"); + Assert.Greater(System.Convert.ToSingle(duration), 0f, "activeDuration 가 0 이하면 OverlapBox 판정이 즉시 종료되어 공격 무효."); } @@ -72,7 +106,7 @@ public class PlayerAttackTests var prefab = AssetDatabase.LoadAssetAtPath(EnemyPrefabPath); Assert.IsNotNull(prefab, $"Enemy.prefab not found at {EnemyPrefabPath}"); - var health = prefab.GetComponent(); + var health = FindComponentByFullName(prefab, HealthType); Assert.IsNotNull(health, "Enemy.prefab 에 Health 컴포넌트 누락. " + "BT5-Dev 2단계 재위임 집행분 (2026-04-23) 이 prefab YAML 에 반영되어야 함. " + @@ -83,10 +117,12 @@ public class PlayerAttackTests public void Enemy_Prefab_Health_MaxHP_Is_One() { var prefab = AssetDatabase.LoadAssetAtPath(EnemyPrefabPath); - var health = prefab.GetComponent(); + var health = FindComponentByFullName(prefab, HealthType); Assert.IsNotNull(health); - Assert.AreEqual(1, health.maxHP, + var maxHP = GetFieldOrProperty(health, "maxHP"); + Assert.IsNotNull(maxHP, "Health.maxHP 필드/프로퍼티 접근 불가"); + Assert.AreEqual(1, System.Convert.ToInt32(maxHP), "일반 적 기본 maxHP 1 (코어 룰 7 정합, 첫 세팅)."); } @@ -94,7 +130,7 @@ public class PlayerAttackTests public void Enemy_Prefab_Has_EnemyController_Component() { var prefab = AssetDatabase.LoadAssetAtPath(EnemyPrefabPath); - var controller = prefab.GetComponent(); + var controller = FindComponentByFullName(prefab, EnemyControllerType); Assert.IsNotNull(controller, "EnemyDeath 체인에 EnemyController 필수 (AttackHitbox.Update 에서 Schedule().enemy = enemy)."); } diff --git a/Assets/Tests/Editor/PlayerAttackTests.cs.meta b/Assets/Tests/Editor/PlayerAttackTests.cs.meta new file mode 100644 index 0000000..44e9a02 --- /dev/null +++ b/Assets/Tests/Editor/PlayerAttackTests.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: d1dde48bf06739747a199e6d45b3fd18 \ No newline at end of file