ThreeKingdomsSlingshot/Assets/Tests/PlayMode/LoadingScreenTests.cs

182 lines
9.3 KiB
C#
Raw Normal View History

using System.Collections;
using System.Globalization;
using NUnit.Framework;
using TKS.OutGame;
using UnityEngine;
using UnityEngine.TestTools;
using UnityEngine.UI;
namespace TKS.Tests
{
/// <summary>
/// 로딩·리소스 다운로드 화면(PD 2026-11-13 · 두 경우) — 다운로드 세트(배경 + 위 타이틀 로고 + 조운·병졸 + 진행률·용량) / 로딩 세트(검은 화면 + 유비·관우·장비 말 타고 질주 · 심플).
/// ① 표 runner 줄 수만큼 달리는 그림 · 프레임 ≥ 2 · 시간이 지나면 프레임이 바뀜(제자리 반복) ② 캔버스 층(P41): 루트 Static · 바 채움·무리·먼지 = Frame · 글자 = Event
/// ③ 진행률(0~1) → 바 채움·% 글자 · 용량(바이트) → 「12.4 MB / 48.0 MB」 · 부드럽게 따라감 ④ 먼지가 나옴 ⑤ 모드를 바꾸면 그 세트로 다시 만듦(같은 객체 · 값 유지) ⑥ Hide.
/// 기대 문구·줄 수는 표 Resources/UI/loading_screen.csv 에서 세트별로 읽는다(C45).
/// </summary>
public class LoadingScreenTests
{
Camera cam;
[SetUp]
public void SetUp()
{
LoadingTable.Reload();
cam = new GameObject("TestCam").AddComponent<Camera>();
cam.orthographic = true;
}
[TearDown]
public void TearDown()
{
LoadingScreen.HideCurrent();
if (cam != null) Object.Destroy(cam.gameObject);
}
static UiRate RateOf(Transform t)
{
var c = t.GetComponentInParent<Canvas>(true);
Assert.IsNotNull(c, t.name + ": 캔버스 없음");
var tag = c.GetComponent<UiLayerInfo>();
Assert.IsNotNull(tag, c.name + ": 등급 표시 없음");
return tag.rate;
}
/// <summary>a 가 b 보다 계층 순서상 먼저(= uGUI 에서 뒤에 그려짐)인지 · 공통 조상 아래 형제 순서로 판정.</summary>
static bool DrawnBefore(Transform a, Transform b)
{
var pa = new System.Collections.Generic.List<Transform>();
for (var t = a; t != null; t = t.parent) pa.Insert(0, t);
var pb = new System.Collections.Generic.List<Transform>();
for (var t = b; t != null; t = t.parent) pb.Insert(0, t);
int i = 0;
while (i < pa.Count && i < pb.Count && pa[i] == pb[i]) i++;
if (i >= pa.Count || i >= pb.Count) return false; // 한쪽이 다른 쪽의 조상
return pa[i].GetSiblingIndex() < pb[i].GetSiblingIndex();
}
/// <summary>세트 하나의 공통 검사(달리는 무리 · 층 · 먼지 · 상태 문구).</summary>
static IEnumerator CheckSet(LoadingScreen ls, string set)
{
Assert.AreEqual(set, ls.Set);
var rows = LoadingTable.All("runner", set);
Assert.Greater(rows.Count, 0, set + ": 표에 runner 줄 없음");
Assert.AreEqual(rows.Count, ls.Runners.Count, set + ": 표 runner 줄 수 = 화면 그림 수");
foreach (var r in ls.Runners)
{
Assert.GreaterOrEqual(r.Frames.Length, 2, r.name + ": 프레임 2 장 이상");
Assert.AreEqual(UiRate.Frame, RateOf(r.transform), r.name + ": 매 프레임 그림은 Frame 캔버스");
}
Assert.AreEqual(UiRate.Static, ls.RootCanvas.GetComponent<UiLayerInfo>().rate, "루트 = Static");
Assert.IsNotNull(ls.Fill, set + ": 표 fill 줄");
Assert.AreEqual(Image.Type.Filled, ls.Fill.type);
Assert.AreEqual(UiRate.Frame, RateOf(ls.Fill.transform), "바 채움 = Frame");
Assert.IsNotNull(ls.StatusText, set + ": 상태 문구");
Assert.AreEqual(UiRate.Event, RateOf(ls.StatusText.transform), "상태 글자 = Event");
Assert.AreEqual(LoadingTable.First("text", "status", set).text, ls.StatusText.text);
foreach (var c in ls.GetComponentsInChildren<Canvas>(false))
if (c != ls.RootCanvas)
Assert.IsFalse(c.overrideSorting, c.name + ": 중첩 캔버스 overrideSorting 끔");
Assert.AreEqual(LoadingTable.All("logo", set).Count > 0, ls.Logo != null, set + ": 로고 줄 ↔ 화면");
Assert.AreEqual(LoadingTable.All("dust", set).Count, ls.Dusts.Count, set + ": 표 dust 줄 수");
// 먼지 = 무리 전부의 뒤(앞 말 먼지가 뒤 말 다리를 덮지 않음 · QA r3 M1)
foreach (var d in ls.Dusts)
foreach (var r in ls.Runners)
Assert.IsTrue(DrawnBefore(d.transform, r.transform), set + ": 먼지 " + d.name + " 가 " + r.name + " 보다 먼저(뒤에) 그려짐");
// 제자리 반복 — 시간이 지나면 프레임이 바뀜
var lead = ls.Runners[ls.Runners.Count - 1];
int f0 = lead.Index;
var s0 = lead.Img.sprite;
yield return new WaitForSecondsRealtime(0.25f);
Assert.AreNotEqual(f0, lead.Index, set + ": 프레임이 넘어감");
Assert.AreNotSame(s0, lead.Img.sprite);
if (ls.Dusts.Count > 0)
{
yield return new WaitForSecondsRealtime(1.0f);
int alive = 0;
foreach (var d in ls.Dusts) alive += d.Alive;
Assert.Greater(alive, 0, set + ": 먼지가 나옴");
Assert.AreEqual(UiRate.Frame, RateOf(ls.Dusts[0].transform), "먼지 = Frame");
}
}
[UnityTest]
public IEnumerator Download_LogoRunnersProgressSize()
{
var ls = LoadingScreen.Show(cam, LoadingMode.Download);
yield return null;
yield return CheckSet(ls, LoadingScreen.SetOf(LoadingMode.Download));
Assert.IsNotNull(ls.Logo, "다운로드 = 위 타이틀 로고(PD 2026-11-13)");
Assert.IsNotNull(ls.Logo.sprite, "로고 그림");
var pct = LoadingTable.First("text", "percent", ls.Set);
ls.SetProgress(0.5f, true);
Assert.AreEqual(0.5f, ls.Fill.fillAmount, 1e-4f);
Assert.AreEqual(string.Format(CultureInfo.InvariantCulture, pct.text, 50), ls.PercentText.text);
ls.SetDownload(13002342L, 50331648L, true); // 12.4 MB / 48.0 MB
var size = LoadingTable.First("text", "size", ls.Set);
Assert.AreEqual(string.Format(CultureInfo.InvariantCulture, size.text, "12.4 MB", "48.0 MB"), ls.SizeText.text);
Assert.AreEqual(13002342.0 / 50331648.0, ls.Fill.fillAmount, 1e-4);
Assert.AreEqual(string.Format(CultureInfo.InvariantCulture, pct.text, 25), ls.PercentText.text);
ls.SetProgress(1f);
Assert.Less(ls.Shown, 1f, "목표로 바로 뛰지 않고 따라감");
float before = ls.Shown;
yield return new WaitForSecondsRealtime(0.2f);
Assert.Greater(ls.Shown, before, "보이는 진행률이 목표 쪽으로 움직임");
Assert.LessOrEqual(ls.Shown, 1f);
ls.Hide();
yield return null;
Assert.IsNull(LoadingScreen.Current);
}
[UnityTest]
public IEnumerator Loading_SimpleBlack_ThreeRiders_ModeSwitch()
{
var ls = LoadingScreen.Show(cam, LoadingMode.Loading);
yield return null;
yield return CheckSet(ls, LoadingScreen.SetOf(LoadingMode.Loading));
Assert.AreEqual(3, LoadingTable.All("runner", ls.Set).Count, "로딩 = 유비·관우·장비 3기(PD 2026-11-13)");
var bg = ls.transform.Find("Bg");
Assert.IsNotNull(bg, "배경 판(누름 막기)");
Assert.IsNull(bg.GetComponent<Image>().sprite, "로딩 = 배경 그림 없음(검은 화면)");
Assert.Less(bg.GetComponent<Image>().color.grayscale, 0.05f, "검정");
Assert.IsNull(ls.Logo, "로딩 = 로고 없음");
Assert.IsNull(ls.SizeText, "로딩 = 용량 줄 없음");
// 모드 바꾸기 = 같은 객체에서 그 세트로 다시 만듦 · 진행률 유지
ls.SetProgress(0.4f, true);
ls.SetMode(LoadingMode.Download);
yield return null;
Assert.AreSame(ls, LoadingScreen.Current);
Assert.AreEqual(LoadingScreen.SetOf(LoadingMode.Download), ls.Set);
Assert.AreEqual(LoadingTable.All("runner", ls.Set).Count, ls.Runners.Count);
Assert.AreEqual(0.4f, ls.Fill.fillAmount, 1e-4f, "진행률 유지");
ls.SetMode(LoadingMode.Loading);
yield return null;
Assert.AreEqual(3, ls.Runners.Count);
Assert.AreEqual(0, CountInactive(ls.transform), "이전 세트 자식은 다음 프레임에 지워짐");
Assert.IsNull(ls.transform.Find("Logo"), "다운로드 세트 로고가 남지 않음");
}
static int CountInactive(Transform t)
{
int n = 0;
for (int i = 0; i < t.childCount; i++)
if (!t.GetChild(i).gameObject.activeSelf)
n++;
return n;
}
[Test]
public void Bytes_Format()
{
Assert.AreEqual("12.4 MB", LoadingScreen.Bytes(13002342L));
Assert.AreEqual("48.0 MB", LoadingScreen.Bytes(50331648L));
Assert.AreEqual("1.5 GB", LoadingScreen.Bytes(1610612736L));
Assert.AreEqual("50 KB", LoadingScreen.Bytes(51200L));
}
}
}