using NUnit.Framework; using UnityEngine; using UnityEditor; /// /// EerieVillage BT5-Dev 2단계 — Player 근거리 공격 체계 EditMode 테스트. /// Prefab 자산의 컴포넌트 구성이 기획 04 §5-1 (근거리 공격 1종) 을 충족하는지 검증. /// Play 모드 실행 불요 — prefab YAML 직렬화 상태를 직접 검증하여 회귀 방지. /// public class PlayerAttackTests { const string PlayerPrefabPath = "Assets/Prefabs/Player.prefab"; const string EnemyPrefabPath = "Assets/Prefabs/Enemy.prefab"; [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(); Assert.IsNotNull(hitbox, "Player.prefab에 AttackHitbox 컴포넌트가 누락. " + "BT5-Dev 2단계 재위임 집행분 (2026-04-23) 이 prefab YAML 에 반영되어야 함."); } [Test] public void Player_Prefab_Has_Health_Component() { var prefab = AssetDatabase.LoadAssetAtPath(PlayerPrefabPath); Assert.IsNotNull(prefab, $"Player.prefab not found at {PlayerPrefabPath}"); var health = prefab.GetComponent(); Assert.IsNotNull(health, "Player.prefab 에 Health 컴포넌트 누락 (템플릿 기본)."); } [Test] public void Player_Prefab_Has_PlayerController_Component() { var prefab = AssetDatabase.LoadAssetAtPath(PlayerPrefabPath); Assert.IsNotNull(prefab); var controller = prefab.GetComponent(); Assert.IsNotNull(controller, "Player.prefab 에 PlayerController 컴포넌트 누락."); } [Test] public void AttackHitbox_Default_Damage_Is_One() { var prefab = AssetDatabase.LoadAssetAtPath(PlayerPrefabPath); var hitbox = prefab.GetComponent(); Assert.IsNotNull(hitbox); Assert.AreEqual(1, hitbox.damage, "기본 대미지 1 (기획 04 §5-1, Phase 3-B 튠 전 파일럿 값)."); } [Test] public void AttackHitbox_Active_Duration_Is_Positive() { var prefab = AssetDatabase.LoadAssetAtPath(PlayerPrefabPath); var hitbox = prefab.GetComponent(); Assert.IsNotNull(hitbox); Assert.Greater(hitbox.activeDuration, 0f, "activeDuration 가 0 이하면 OverlapBox 판정이 즉시 종료되어 공격 무효."); } [Test] public void Enemy_Prefab_Has_Health_Component() { var prefab = AssetDatabase.LoadAssetAtPath(EnemyPrefabPath); Assert.IsNotNull(prefab, $"Enemy.prefab not found at {EnemyPrefabPath}"); var health = prefab.GetComponent(); Assert.IsNotNull(health, "Enemy.prefab 에 Health 컴포넌트 누락. " + "BT5-Dev 2단계 재위임 집행분 (2026-04-23) 이 prefab YAML 에 반영되어야 함. " + "Health 없으면 AttackHitbox.Update 의 Decrement 호출이 불가 → EnemyDeath 체인 미발동."); } [Test] public void Enemy_Prefab_Health_MaxHP_Is_One() { var prefab = AssetDatabase.LoadAssetAtPath(EnemyPrefabPath); var health = prefab.GetComponent(); Assert.IsNotNull(health); Assert.AreEqual(1, health.maxHP, "일반 적 기본 maxHP 1 (코어 룰 7 정합, 첫 세팅)."); } [Test] public void Enemy_Prefab_Has_EnemyController_Component() { var prefab = AssetDatabase.LoadAssetAtPath(EnemyPrefabPath); var controller = prefab.GetComponent(); Assert.IsNotNull(controller, "EnemyDeath 체인에 EnemyController 필수 (AttackHitbox.Update 에서 Schedule().enemy = enemy)."); } }