using System.Collections.Generic; using NUnit.Framework; using UnityEngine; namespace TKS.Tests { /// /// 시나리오 이벤트 표(2026-11-12 · 개발 요청서 C1·C2) 데이터 검사 — 전장 설명 = 스테이지와 1:1 · 50자 이하 · 본문 폰트에 없는 글자 없음 / /// 보스 등장 행 = 보스 스테이지의 보스 무장과 1:1 · 대사 ≤ bubble_max_chars / 연출 값 표 읽기 오류 0. /// public class ScenarioDataTests { const string BadGlyphs = "—「」…"; // 넥슨 Lv1 고딕에 없는 글자(기획 검사와 같은 목록) static BalanceConfig Cfg() { var c = Resources.Load("BalanceConfig"); Assert.IsNotNull(c, "Resources/BalanceConfig 없음"); return c; } [Test] public void StageStory_OnePerStage_ShortAndFontSafe() { ScenarioData.Reload(); var cfg = Cfg(); int n = 0; foreach (var kv in ScenarioData.AllDesc) n++; Assert.AreEqual(cfg.stages.Length, n, "전장 설명 행 수 ≠ 스테이지 수"); foreach (var s in cfg.stages) { string d = ScenarioData.Desc(s.chapter, s.stage); Assert.IsNotEmpty(d, s.chapter + "-" + s.stage + " 전장 설명 없음"); Assert.LessOrEqual(d.Length, 50, s.chapter + "-" + s.stage + " 50자 초과"); Assert.AreEqual(-1, d.IndexOfAny(BadGlyphs.ToCharArray()), s.chapter + "-" + s.stage + " 폰트 없는 글자"); } Assert.AreEqual(0, ScenarioData.Errors.Count, string.Join("\n", ScenarioData.Errors.ToArray())); } [Test] public void BossIntro_MatchesBossGenerals_LinesFit() { ScenarioData.Reload(); var cfg = Cfg(); int maxChars = Mathf.RoundToInt(ScenarioData.Cfg("bubble_max_chars")); Assert.Greater(maxChars, 0, "bubble_max_chars 없음"); int rows = 0; foreach (var s in cfg.stages) { var want = new List(); foreach (var e in s.enemies) if (e.isBoss) want.Add(e.art); var got = new List(); foreach (var b in ScenarioData.Bosses(s.chapter, s.stage)) { got.Add(b.id); Assert.IsNotEmpty(b.title, s.chapter + "-" + s.stage + " 칭호 없음"); Assert.IsNotEmpty(b.line, s.chapter + "-" + s.stage + " 대사 없음"); Assert.LessOrEqual(b.line.Length, maxChars, s.chapter + "-" + s.stage + " 대사 " + b.line.Length + "자"); rows++; } want.Sort(); got.Sort(); CollectionAssert.AreEqual(want, got, s.chapter + "-" + s.stage + " 보스 행 ≠ 보스 무장"); } Assert.AreEqual(ScenarioData.AllBosses.Count, rows, "보스 등장 표에 없는 스테이지 행이 있음"); } [Test] public void IntroConfig_ReadsWithoutErrors() { ScenarioData.Reload(); foreach (var k in new[] { "warn_sec", "focus_move_sec", "cutin_hold_sec", "bubble_char_per_sec", "return_sec", "replay_mode" }) Assert.IsTrue(ScenarioData.HasCfg(k), "연출 값 키 없음: " + k); Assert.AreEqual(0, ScenarioData.Errors.Count, string.Join("\n", ScenarioData.Errors.ToArray())); } } }