102 lines
4.1 KiB
C#
102 lines
4.1 KiB
C#
|
|
using NUnit.Framework;
|
||
|
|
using UnityEngine;
|
||
|
|
using UnityEditor;
|
||
|
|
|
||
|
|
/// <summary>
|
||
|
|
/// EerieVillage BT5-Dev 2단계 — Player 근거리 공격 체계 EditMode 테스트.
|
||
|
|
/// Prefab 자산의 컴포넌트 구성이 기획 04 §5-1 (근거리 공격 1종) 을 충족하는지 검증.
|
||
|
|
/// Play 모드 실행 불요 — prefab YAML 직렬화 상태를 직접 검증하여 회귀 방지.
|
||
|
|
/// </summary>
|
||
|
|
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<GameObject>(PlayerPrefabPath);
|
||
|
|
Assert.IsNotNull(prefab, $"Player.prefab not found at {PlayerPrefabPath}");
|
||
|
|
|
||
|
|
var hitbox = prefab.GetComponent<Platformer.Mechanics.AttackHitbox>();
|
||
|
|
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<GameObject>(PlayerPrefabPath);
|
||
|
|
Assert.IsNotNull(prefab, $"Player.prefab not found at {PlayerPrefabPath}");
|
||
|
|
|
||
|
|
var health = prefab.GetComponent<Platformer.Mechanics.Health>();
|
||
|
|
Assert.IsNotNull(health, "Player.prefab 에 Health 컴포넌트 누락 (템플릿 기본).");
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void Player_Prefab_Has_PlayerController_Component()
|
||
|
|
{
|
||
|
|
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(PlayerPrefabPath);
|
||
|
|
Assert.IsNotNull(prefab);
|
||
|
|
|
||
|
|
var controller = prefab.GetComponent<Platformer.Mechanics.PlayerController>();
|
||
|
|
Assert.IsNotNull(controller, "Player.prefab 에 PlayerController 컴포넌트 누락.");
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void AttackHitbox_Default_Damage_Is_One()
|
||
|
|
{
|
||
|
|
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(PlayerPrefabPath);
|
||
|
|
var hitbox = prefab.GetComponent<Platformer.Mechanics.AttackHitbox>();
|
||
|
|
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<GameObject>(PlayerPrefabPath);
|
||
|
|
var hitbox = prefab.GetComponent<Platformer.Mechanics.AttackHitbox>();
|
||
|
|
Assert.IsNotNull(hitbox);
|
||
|
|
|
||
|
|
Assert.Greater(hitbox.activeDuration, 0f,
|
||
|
|
"activeDuration 가 0 이하면 OverlapBox 판정이 즉시 종료되어 공격 무효.");
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void Enemy_Prefab_Has_Health_Component()
|
||
|
|
{
|
||
|
|
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(EnemyPrefabPath);
|
||
|
|
Assert.IsNotNull(prefab, $"Enemy.prefab not found at {EnemyPrefabPath}");
|
||
|
|
|
||
|
|
var health = prefab.GetComponent<Platformer.Mechanics.Health>();
|
||
|
|
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<GameObject>(EnemyPrefabPath);
|
||
|
|
var health = prefab.GetComponent<Platformer.Mechanics.Health>();
|
||
|
|
Assert.IsNotNull(health);
|
||
|
|
|
||
|
|
Assert.AreEqual(1, health.maxHP,
|
||
|
|
"일반 적 기본 maxHP 1 (코어 룰 7 정합, 첫 세팅).");
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void Enemy_Prefab_Has_EnemyController_Component()
|
||
|
|
{
|
||
|
|
var prefab = AssetDatabase.LoadAssetAtPath<GameObject>(EnemyPrefabPath);
|
||
|
|
var controller = prefab.GetComponent<Platformer.Mechanics.EnemyController>();
|
||
|
|
Assert.IsNotNull(controller,
|
||
|
|
"EnemyDeath 체인에 EnemyController 필수 (AttackHitbox.Update 에서 Schedule<EnemyDeath>().enemy = enemy).");
|
||
|
|
}
|
||
|
|
}
|