# Testing Patterns **Analysis Date:** 2026-05-18 ## Test Framework **Runner:** - NUnit 3.13.3 — `NcProgramManager.Tests/packages.config` - NUnit3TestAdapter 4.2.1 — VS/dotnet test runner integration - Config: `NcProgramManager.Tests/nunit.runsettings` **Assertion Library:** - NUnit fluent API: `Assert.That(actual, Is.True)`, `Is.EqualTo()`, `Is.InstanceOf()` **Mocking:** - Moq 4.18.4 for interface mocking - Castle.Core 5.1.1 (Moq dependency) - Custom delegates for `ref` parameter workaround (Moq limitation with P/Invoke refs) - Example: `NcProgramManager.Tests/Unit/FanucMachineTests.cs` **Run Commands:** ```bash # Standard NUnit runner or VS Test Explorer dotnet test NcProgramManager.Tests/NcProgramManager.Tests.csproj # Or via Dockerfile: docker build -f Dockerfile.test . ``` ## Test File Organization **Location:** - All tests in `NcProgramManager.Tests/` (separate project) - Unit tests: `NcProgramManager.Tests/Unit/` - Integration tests: `NcProgramManager.Tests/Integration/` - Stubs: `NcProgramManager.Tests/Integration/Stubs/` **Naming:** - Unit: `{Subject}Tests.cs` — `NcProgramValidatorTests.cs`, `FanucMachineTests.cs` - Integration: `{Subject}IntegrationTests.cs` — `HeidenhainMachineIntegrationTests.cs` - Stubs: `{Protocol}ServerStub.cs` — `FtpServerStub.cs`, `Lsv2ServerStub.cs` ## Test Structure **Fixture Pattern:** ```csharp [TestFixture] public class NcProgramValidatorTests { [SetUp] public void SetUp() { ... } [Test] public void MethodName_Condition_ExpectedResult() { // arrange // act // assert (NUnit fluent) } } ``` **Parameterized Tests:** ```csharp [TestCase(CncManufacturer.Fanuc)] [TestCase(CncManufacturer.Siemens)] [TestCase(CncManufacturer.Heidenhain)] [TestCase(CncManufacturer.Mitsubishi)] public void Validate_TabCharacter_ReturnsWarning(CncManufacturer m) { ... } ``` Example: `NcProgramManager.Tests/Unit/NcProgramValidatorTests.cs` **Async Tests:** - No `async Task` test methods — use `.GetAwaiter().GetResult()` to block - Example: `NcProgramManager.Tests/Integration/HeidenhainMachineIntegrationTests.cs` **Test Categories:** ```csharp [Category("Integration")] // marks integration tests ``` ## Mocking **Interface mocking via Moq:** ```csharp var mockDialect = new Mock(); mockDialect.Setup(d => d.Connect(...)).Returns(...); var machine = new FanucMachine(config, mockDialect.Object); ``` Example: `NcProgramManager.Tests/Unit/FanucMachineTests.cs` **Reflection-based state injection (for bypassing protected fields):** ```csharp // Set internal connection state without real hardware typeof(FanucMachine) .GetField("_state", BindingFlags.NonPublic | BindingFlags.Instance) .SetValue(machine, ConnectionState.Connected); ``` Example: `NcProgramManager.Tests/Unit/FanucMachineTests.cs` **What to mock:** - Protocol interfaces: `IFocasDialect`, `ILsv2Client`, `ISiemensFtpClient`, `IMitsubishiFtpClient` - Licensing: `IMachineFingerprint`, `ILicenseValidator` ## In-Process Protocol Stubs **FtpServerStub** (`NcProgramManager.Tests/Integration/Stubs/FtpServerStub.cs`): - Minimal FTP server for Siemens/Mitsubishi integration testing - In-memory file store: `Dictionary Files` - Supported commands: USER, PASS, CWD, TYPE, PASV, LIST, NLST, RETR, STOR, DELE - Usage: Start before test, inject port into machine config **Lsv2ServerStub** (`NcProgramManager.Tests/Integration/Stubs/Lsv2ServerStub.cs`): - Minimal LSV2 TCP server for Heidenhain integration testing - Implements LSV2 framing (STX, SIZE, CMD, data, CRC) - Thread-per-client architecture ## Ignored Tests **FOCAS DLL-dependent tests marked `[Ignore]`:** - All tests requiring actual `Fwlib32.dll` calls are ignored - Reason: Cannot mock static P/Invoke calls; DLL requires real Fanuc hardware on Windows - Example: `NcProgramManager.Tests/Unit/FanucMachineTests.cs` **Pattern for skipping:** ```csharp [Test] [Ignore("Requires Fanuc FOCAS DLL and real hardware")] public void ConnectAsync_ValidConfig_Connects() { ... } ``` ## Coverage Approach **Well-covered:** - `NcProgramValidator` — universal rules + all 4 manufacturers, 30+ test cases - `NcProgramManager.Tests/Unit/NcProgramValidatorTests.cs` - `FanucProgram` parsing — `FanucProgramParsingTests.cs` - `IsoProgramFormatter` — `IsoProgramFormatterTests.cs` - `CncMachineFactory` dispatch — `CncMachineFactoryTests.cs` - `LicenseValidator` — 6 unit tests via internal ctor injection — `LicenseValidatorTests.cs` **Partially covered (blocked by hardware):** - `FanucMachine` connect/read/write — FOCAS tests `[Ignore]`d - Heidenhain/Siemens/Mitsubishi machines — integration tests use stubs **Not covered:** - `MachineFingerprint` (WMI, Windows-only, no mocked tests) - `LicenseFile` parsing edge cases - `Program.cs` CLI orchestration (no CLI-level tests) --- *Testing analysis: 2026-05-18* *Update when test framework or patterns change*