Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Assets/Scripts/Core/Ship/CrewMember.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using LMPro.DataStructures;
using UnityEngine;

[assembly: InternalsVisibleTo("Ships.Tests")]

namespace Core.Ship
{
[Serializable]
Expand Down Expand Up @@ -49,5 +52,10 @@ public void Kill()
IsAlive = false;
OnDied?.Invoke(this);
}

#if UNITY_INCLUDE_TESTS
internal int OnDiedSubscriberCountForTesting =>
OnDied?.GetInvocationList().Length ?? 0;
#endif
}
}
5 changes: 3 additions & 2 deletions Assets/Scripts/E2E/E2ETestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
using Ships.ModuleConnection;
using Ships.Modules;
using Ships.Systems.Sensing;
using Ships.Tests.TestHelpers;
using Ships.Tests.TestHelpers.Factories;
using Ships.Tests.TestHelpers.Mocks;
using UnityEngine;
using Zenject;
using ZLinq;
Expand Down Expand Up @@ -142,7 +143,7 @@ protected Team CreateTeam(string name, int layer)
protected AIShip CreateAIShip(string name, Team team, Vector2 position, bool withWeapons,
bool withEngines)
{
var shipGo = ModuleFactory.CreateGameObject(name, CreatedObjects);
var shipGo = ModuleFactory.CreateGameObject(name, CreatedObjects, Container);
shipGo.layer = team.Layer;
shipGo.transform.position = position;

Expand Down
14 changes: 14 additions & 0 deletions Assets/Scripts/ShipFactory/ShipModuleSO.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using System.Runtime.CompilerServices;
using UnityEngine;

[assembly: InternalsVisibleTo("ShipFactory.Tests")]

namespace ShipFactory
{
[CreateAssetMenu(fileName = "ShipModuleSO", menuName = "Ship Factory/ShipModuleSO")]
Expand All @@ -16,5 +19,16 @@ public class ShipModuleSO : ScriptableObject
public Vector2Int Dimensions => dimensions;
public string Name => partName;
public string Description => description;

#if UNITY_INCLUDE_TESTS
internal void ConfigureForTesting(string newPartName, string moduleDescription, Vector2Int moduleDimensions,
GameObject modulePrefab)
{
partName = newPartName;
description = moduleDescription;
dimensions = moduleDimensions;
prefab = modulePrefab;
}
#endif
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using Core.Ship;
using NSubstitute;
using NUnit.Framework;
Expand Down Expand Up @@ -81,25 +79,13 @@ private ShipModuleSOInstanceBundle CreateBundle(string name, ModuleType moduleTy
var moduleSO = ScriptableObject.CreateInstance<ShipModuleSO>();
_createdObjects.Add(moduleSO);

SetPrivateField(moduleSO, "partName", name);
SetPrivateField(moduleSO, "description", $"{name} description");
SetPrivateField(moduleSO, "dimensions", dimensions);
SetPrivateField(moduleSO, "prefab", go);
moduleSO.ConfigureForTesting(name, $"{name} description", dimensions, go);

var module = Substitute.For<IModule>();
module.Type.Returns(moduleType);

return new ShipModuleSOInstanceBundle(go, moduleSO, module);
}

private static void SetPrivateField(object target, string fieldName, object value)
{
var field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
if (field == null)
throw new InvalidOperationException($"Field '{fieldName}' not found on {target.GetType().Name}.");

field.SetValue(target, value);
}
}
}

1 change: 1 addition & 0 deletions Assets/Scripts/Ships/Modules/Cannon.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
using Zenject;

[assembly: InternalsVisibleTo("E2E")]
[assembly: InternalsVisibleTo("Ships.Tests")]

namespace Ships.Modules
{
Expand Down
21 changes: 8 additions & 13 deletions Assets/Scripts/Ships/Tests/CrewModuleTests.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using Core.Ship;
using NSubstitute;
using NUnit.Framework;
using Ships.Tests.TestHelpers;
using Ships.Tests.TestHelpers.Factories;
using Ships.Tests.TestHelpers.Fixtures;
using Ships.Tests.TestHelpers.Modules;
using UnityEngine;
using UnityEngine.TestTools;
using Object = UnityEngine.Object;
Expand Down Expand Up @@ -37,12 +38,6 @@ private TestModule CreateStandaloneModule(
return module;
}

private static Delegate GetOnDiedDelegate(CrewMember crew)
{
var field = typeof(CrewMember).GetField("OnDied", BindingFlags.Instance | BindingFlags.NonPublic);
return field?.GetValue(crew) as Delegate;
}

[Test]
public void AssignCrew_ReturnsTrue()
{
Expand Down Expand Up @@ -536,7 +531,7 @@ public void KillAllCrew_DoesNotLeakOnDiedSubscription()

module.KillAllCrew();

Assert.IsNull(GetOnDiedDelegate(crew),
Assert.AreEqual(0, crew.OnDiedSubscriberCountForTesting,
"Module should have unsubscribed from OnDied after KillAllCrew");
}

Expand Down Expand Up @@ -577,7 +572,7 @@ public void RemoveCrew_DoesNotLeakOnDiedSubscription()

module.RemoveCrew(crew);

Assert.IsNull(GetOnDiedDelegate(crew),
Assert.AreEqual(0, crew.OnDiedSubscriberCountForTesting,
"Module should have unsubscribed from OnDied after RemoveCrew");
}

Expand All @@ -594,9 +589,9 @@ public void KillRandomCrew_DoesNotLeakOnDiedSubscription()

module.KillRandomCrew(3);

Assert.IsNull(GetOnDiedDelegate(crew1), "crew1 OnDied should have no subscribers");
Assert.IsNull(GetOnDiedDelegate(crew2), "crew2 OnDied should have no subscribers");
Assert.IsNull(GetOnDiedDelegate(crew3), "crew3 OnDied should have no subscribers");
Assert.AreEqual(0, crew1.OnDiedSubscriberCountForTesting, "crew1 OnDied should have no subscribers");
Assert.AreEqual(0, crew2.OnDiedSubscriberCountForTesting, "crew2 OnDied should have no subscribers");
Assert.AreEqual(0, crew3.OnDiedSubscriberCountForTesting, "crew3 OnDied should have no subscribers");
}
}
}
26 changes: 9 additions & 17 deletions Assets/Scripts/Ships/Tests/ModuleConnectionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
using System.Collections.Generic;
using NUnit.Framework;
using Ships.Modules;
using Ships.Tests.TestHelpers;
using Ships.Tests.TestHelpers.Factories;
using Ships.Tests.TestHelpers.Fixtures;
using UnityEngine;
using UnityEngine.TestTools;
using ZLinq;
Expand Down Expand Up @@ -34,22 +35,13 @@ public IEnumerator UnrotatedModuleOnRight_ConnectsToCommandModule()
AssertModulesConnected(ship, command, engine);
}

private (Ship ship, Command command, Engine engine) CreateCommandWithEngineOnRight(float engineRotationZ)
private CommandWithEngineResult CreateCommandWithEngineOnRight(float engineRotationZ)
{
var shipGo = ModuleFactory.CreateGameObject("TestShip", CreatedObjects);

ModuleFactory.CreateCommandModule(shipGo.transform, Vector2.zero, Container, CreatedObjects,
ModulePixelSize, ModulePixelSize);
ModuleFactory.CreateEngineModule(shipGo.transform, new Vector2(ModuleSpacing, 0f), Container,
CreatedObjects, EngineMaxThrust, ModulePixelSize, ModulePixelSize, engineRotationZ);

var ship = ModuleFactory.WireShip<Ship>(shipGo, Container);
var command = shipGo.GetComponentInChildren<Command>();
var engine = shipGo.GetComponentInChildren<Engine>();

Container.InjectGameObject(shipGo);

return (ship, command, engine);
return ShipTestBuilder.CreateShip(Container, CreatedObjects)
.WithCommand("Command", Vector2.zero, ModulePixelSize, ModulePixelSize)
.WithEngineModule(new Vector2(ModuleSpacing, 0f), EngineMaxThrust, ModulePixelSize, ModulePixelSize,
engineRotationZ)
.BuildCommandWithEngineResult();
}

private static void AssertModulesConnected(Ship ship, Command command, Engine engine)
Expand All @@ -76,4 +68,4 @@ private static void AssertModulesConnected(Ship ship, Command command, Engine en
"Command module should have connection points to engine");
}
}
}
}
35 changes: 8 additions & 27 deletions Assets/Scripts/Ships/Tests/ModuleDestructionThresholdTests.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
using System.Collections;
using System.Collections.Generic;
using Core.Constants;
using Core.Ship;
using NUnit.Framework;
using Ships.Modules;
using Ships.Tests.TestHelpers;
using Ships.Tests.TestHelpers.Factories;
using Ships.Tests.TestHelpers.Fixtures;
using UnityEngine;
using UnityEngine.TestTools;
using Module = Ships.Modules.Module;

namespace Ships.Tests
{
Expand All @@ -27,26 +25,6 @@ public class ModuleDestructionThresholdTests : ShipTestBase
private static int PixelsToKeepAtOrAboveThreshold =>
Mathf.CeilToInt(TotalPixels * GameplayConstants.ModuleDestroyedBelowPixelRatio);

private (Ship ship, Module command, Module other) CreateTwoModuleShip()
{
var shipGo = ModuleFactory.CreateGameObject("TestShip", CreatedObjects);

var commandGo = ModuleFactory.CreateModuleBase("Command", shipGo.transform, Vector2.zero, 0f,
Container, CreatedObjects, ModuleSize, ModuleSize);
var command = commandGo.AddComponent<Command>();

var otherGo = ModuleFactory.CreateModuleBase("Module2", shipGo.transform, new Vector2(ModuleSize, 0), 0f,
Container, CreatedObjects, ModuleSize, ModuleSize);
var other = otherGo.AddComponent<TestModule>();
other.SetModuleType(ModuleType.Resources);

var ship = ModuleFactory.WireShip<Ship>(shipGo, Container);

Container.InjectGameObject(shipGo);

return (ship, command, other);
}

/// <summary>
/// Removes pixels in row-major order so the kept pixels stay one contiguous region
/// (no division/debris side effects).
Expand All @@ -68,7 +46,8 @@ private static List<Vector2Int> PixelsToRemoveKeeping(int pixelsToKeep)
[UnityTest]
public IEnumerator ModuleBelowPixelThreshold_IsDestroyed()
{
var (ship, _, other) = CreateTwoModuleShip();
var (ship, _, other) =
ShipTestFactory.CreateTwoModuleShip(Container, CreatedObjects);
yield return WaitForLifecycle();

other.PixelatedRigidbody.RemovePixels(PixelsToRemoveKeeping(PixelsToKeepJustBelowThreshold));
Expand All @@ -82,7 +61,8 @@ public IEnumerator ModuleBelowPixelThreshold_IsDestroyed()
[UnityTest]
public IEnumerator ModuleAtPixelThreshold_Survives()
{
var (ship, _, other) = CreateTwoModuleShip();
var (ship, _, other) =
ShipTestFactory.CreateTwoModuleShip(Container, CreatedObjects);
yield return WaitForLifecycle();

other.PixelatedRigidbody.RemovePixels(PixelsToRemoveKeeping(PixelsToKeepAtOrAboveThreshold));
Expand All @@ -95,7 +75,8 @@ public IEnumerator ModuleAtPixelThreshold_Survives()
[UnityTest]
public IEnumerator CommandModuleBelowPixelThreshold_DestroysShip()
{
var (ship, command, _) = CreateTwoModuleShip();
var (ship, command, _) =
ShipTestFactory.CreateTwoModuleShip(Container, CreatedObjects);
yield return WaitForLifecycle();

var shipGo = ship.gameObject;
Expand Down
37 changes: 8 additions & 29 deletions Assets/Scripts/Ships/Tests/ModuleJointLifecycleTests.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
using System.Collections;
using System.Collections.Generic;
using Core.Ship;
using NUnit.Framework;
using Ships.Modules;
using Ships.Tests.TestHelpers;
using Ships.Tests.TestHelpers.Factories;
using Ships.Tests.TestHelpers.Fixtures;
using UnityEngine;
using UnityEngine.TestTools;
using Module = Ships.Modules.Module;
using Object = UnityEngine.Object;

namespace Ships.Tests
Expand All @@ -20,32 +18,11 @@ namespace Ships.Tests
[TestFixture]
public class ModuleJointLifecycleTests : ShipTestBase
{
private const int ModuleSize = 5;

private (Ship ship, Module command, Module other) CreateTwoModuleShip()
{
var shipGo = ModuleFactory.CreateGameObject("TestShip", CreatedObjects);

var commandGo = ModuleFactory.CreateModuleBase("Command", shipGo.transform, Vector2.zero, 0f,
Container, CreatedObjects, ModuleSize, ModuleSize);
var command = commandGo.AddComponent<Command>();

var otherGo = ModuleFactory.CreateModuleBase("Module2", shipGo.transform, new Vector2(ModuleSize, 0), 0f,
Container, CreatedObjects, ModuleSize, ModuleSize);
var other = otherGo.AddComponent<TestModule>();
other.SetModuleType(ModuleType.Resources);

var ship = ModuleFactory.WireShip<Ship>(shipGo, Container);

Container.InjectGameObject(shipGo);

return (ship, command, other);
}

[UnityTest]
public IEnumerator InitializeModules_CalledRepeatedly_DoesNotDuplicateJoints()
{
var (ship, _, _) = CreateTwoModuleShip();
var (ship, _, _) =
ShipTestFactory.CreateTwoModuleShip(Container, CreatedObjects);
yield return WaitForLifecycle();

Assert.AreEqual(1, ship.GetComponentsInChildren<FixedJoint2D>(true).Length,
Expand All @@ -64,7 +41,8 @@ public IEnumerator InitializeModules_CalledRepeatedly_DoesNotDuplicateJoints()
[UnityTest]
public IEnumerator DestroyedModule_LeavesNoJointsOnRemainingModules()
{
var (_, command, other) = CreateTwoModuleShip();
var (_, command, other) =
ShipTestFactory.CreateTwoModuleShip(Container, CreatedObjects);
yield return WaitForLifecycle();

Debug.Log("mkay0");
Expand All @@ -81,7 +59,8 @@ public IEnumerator DestroyedModule_LeavesNoJointsOnRemainingModules()
[UnityTest]
public IEnumerator DisconnectedModule_LeavesNoJointsOnEitherBody()
{
var (_, command, other) = CreateTwoModuleShip();
var (_, command, other) =
ShipTestFactory.CreateTwoModuleShip(Container, CreatedObjects);
yield return WaitForLifecycle();

var commandGo = command.gameObject;
Expand Down
Loading
Loading