112 lines
4.1 KiB
C#
112 lines
4.1 KiB
C#
using System;
|
|||
|
|
using System.Collections.Generic;
|
||
|
|
using Bogatyri.World;
|
||
|
|
using NUnit.Framework;
|
||
|
|
|
||
|
|
// Тесты модулей без Unity-сцены. Запуск: Window -> General -> Test Runner -> EditMode -> Run All.
|
||
|
|
// Список тестов, которые команда решила добавить (план от 19.10.2026), -- в Docs/Modules/README.md.
|
||
|
|
public class ModuleTests
|
||
|
|
{
|
||
|
|
[SetUp]
|
||
|
|
public void ResetCore()
|
||
|
|
{
|
||
|
|
GameServices.Clear();
|
||
|
|
EventBus.Clear();
|
||
|
|
SaveRegistry.Clear();
|
||
|
|
}
|
||
|
|
|
||
|
|
// ---------------- Армия: один солдат не может быть в двух местах ----------------
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void ArmyMath_TakeProportional_NeverDoubleCountsOrLosesSoldiers()
|
||
|
|
{
|
||
|
|
var rnd = new Random(1);
|
||
|
|
for (int run = 0; run < 2000; run++)
|
||
|
|
{
|
||
|
|
var troops = new int[4];
|
||
|
|
int total = 0;
|
||
|
|
for (int i = 0; i < 4; i++) { troops[i] = rnd.Next(0, 50); total += troops[i]; }
|
||
|
|
if (total == 0) continue;
|
||
|
|
|
||
|
|
int count = rnd.Next(1, total + 1);
|
||
|
|
int[] taken = ArmyMath.TakeProportional(troops, count);
|
||
|
|
|
||
|
|
int sum = 0;
|
||
|
|
for (int i = 0; i < 4; i++)
|
||
|
|
{
|
||
|
|
Assert.That(taken[i], Is.InRange(0, troops[i]), "нельзя взять больше, чем есть в типе");
|
||
|
|
sum += taken[i];
|
||
|
|
}
|
||
|
|
Assert.AreEqual(count, sum, "в поход уходит ровно столько, сколько просили");
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void ArmyMath_TakeMoreThanExists_ReturnsNull()
|
||
|
|
{
|
||
|
|
Assert.IsNull(ArmyMath.TakeProportional(new[] { 1, 1, 0, 0 }, 3));
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void ArmyMath_SplitSurvivors_ReturnsExactlySurvivors()
|
||
|
|
{
|
||
|
|
int[] back = ArmyMath.SplitSurvivors(new[] { 10, 5, 0, 1 }, 9);
|
||
|
|
int sum = 0;
|
||
|
|
foreach (var b in back) { Assert.GreaterOrEqual(b, 0); sum += b; }
|
||
|
|
Assert.AreEqual(9, sum);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ---------------- Боевая система ----------------
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void Battle_MoreSoldiersWins_TieGoesToDefender()
|
||
|
|
{
|
||
|
|
var battle = new BattleSystem();
|
||
|
|
Assert.IsTrue(battle.Resolve(new BattleRequest { Attackers = 30, Defenders = 20 }).Victory);
|
||
|
|
Assert.IsFalse(battle.Resolve(new BattleRequest { Attackers = 20, Defenders = 20 }).Victory);
|
||
|
|
Assert.AreEqual(20, battle.Resolve(new BattleRequest { Attackers = 30, Defenders = 20 }).Survivors);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ---------------- Глобальный мир: поход до конца, в том числе офлайн ----------------
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void World_MarchResolvesAndReturns_EvenAfterLongOffline()
|
||
|
|
{
|
||
|
|
var world = new WorldSimulation(WorldMapLayout.CreateDefault(), new BattleSystem());
|
||
|
|
MarchData march = world.StartMarch("p", WorldMapLayout.PlayerCityId, WorldMapLayout.BossCastleId, 30, 0, out string error);
|
||
|
|
Assert.IsNotNull(march, error);
|
||
|
|
|
||
|
|
var events = new List<WorldEvent>();
|
||
|
|
world.Advance(3_600_000, events); // игра была закрыта час
|
||
|
|
|
||
|
|
Assert.AreEqual(2, events.Count, "бой и возвращение за один вызов");
|
||
|
|
Assert.AreEqual(WorldEventType.BattleResolved, events[0].Type);
|
||
|
|
Assert.AreEqual(WorldEventType.MarchReturned, events[1].Type);
|
||
|
|
Assert.AreEqual(0, world.Marches.Count);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ---------------- Ядро ----------------
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void EventBus_FailingSubscriberDoesNotBreakOthers()
|
||
|
|
{
|
||
|
|
int delivered = 0;
|
||
|
|
Exception caught = null;
|
||
|
|
EventBus.OnHandlerError = e => caught = e;
|
||
|
|
EventBus.Subscribe<MarchReturnedEvent>(_ => throw new InvalidOperationException("boom"));
|
||
|
|
EventBus.Subscribe<MarchReturnedEvent>(_ => delivered++);
|
||
|
|
|
||
|
|
EventBus.Publish(new MarchReturnedEvent { Survivors = 5 });
|
||
|
|
|
||
|
|
Assert.AreEqual(1, delivered);
|
||
|
|
Assert.IsNotNull(caught);
|
||
|
|
}
|
||
|
|
|
||
|
|
[Test]
|
||
|
|
public void GameServices_MissingModule_ThrowsClearError()
|
||
|
|
{
|
||
|
|
Assert.Throws<InvalidOperationException>(() => GameServices.Get<IArmy>());
|
||
|
|
Assert.IsFalse(GameServices.TryGet(out IArmy _));
|
||
|
|
}
|
||
|
|
}
|