This document describes the testing infrastructure for the Tracebit CLI project.
The solution contains three test projects:
Location: Tracebit.Cli.Tests/
Purpose: Fast, isolated tests for individual components and functions.
Location: Tracebit.Cli.Integration.Tests/
Purpose: Tests that verify components work correctly together with real dependencies.
- Uses WireMock.Net for HTTP mocking
- Temporary file system for file operations
Location: Tracebit.Cli.E2E.Tests/
Purpose: Tests that execute the compiled CLI binary as a user would.
- Tests complete user workflows
- Cross-platform testing (Windows, Linux, macOS)
- Tests error handling and user experience
dotnet test# Unit tests only
dotnet test Tracebit.Cli.Tests/Tracebit.Cli.Tests.csproj
# Integration tests only
dotnet test Tracebit.Cli.Integration.Tests/Tracebit.Cli.Integration.Tests.csproj
# E2E tests only
dotnet test Tracebit.Cli.E2E.Tests/Tracebit.Cli.E2E.Tests.csprojdotnet test --collect:"XPlat Code Coverage"dotnet test --filter "FullyQualifiedName~Tracebit.Cli.Tests.Commands.UtilsTestsusing FluentAssertions;
using Moq;
using Xunit;
namespace Tracebit.Cli.Tests.State;
public class StateManagerTests
{
[Fact]
public void AddAwsCredential_NewCredential_AddsToList()
{
var stateManager = new StateManager();
var credentials = TestDataBuilder.BuildAwsCredentials();
var result = stateManager.AddAwsCredential(
"test-cred",
null,
credentials
);
result.Should().NotBeNull();
result.Name.Should().Be("test-cred");
result.Type.Should().Be("aws");
stateManager.AwsCredentials.Should().ContainSingle();
}
}using FluentAssertions;
using Xunit;
namespace Tracebit.Cli.Integration.Tests.FileSystem;
public class StateManagerFileTests : BaseIntegrationTest
{
[Fact]
public async Task SaveAsync_PersistsToFile()
{
var stateFile = GetTempFilePath("state.json");
// ... setup StateManager with temp file
await stateManager.SaveAsync(CancellationToken.None);
File.Exists(stateFile).Should().BeTrue();
var content = await File.ReadAllTextAsync(stateFile);
content.Should().Contain("\"Credentials\":");
}
}using FluentAssertions;
using Xunit;
namespace Tracebit.Cli.E2E.Tests.Workflows;
public class AuthWorkflowTests
{
[Fact]
public async Task Auth_Status_WithoutCredentials_ShowsHelpfulMessage()
{
var result = await CliTestHelper.ExecuteAsync("auth status");
result.ExitCode.Should().Be(1);
result.StandardOutput.Should().Contain("not yet logged into Tracebit");
result.StandardOutput.Should().Contain("auth");
}
}- Test Naming: Use descriptive names following the pattern
MethodName_Scenario_ExpectedBehavior - Arrange-Act-Assert: Structure tests clearly with these three sections
- Isolation: Each test should be independent and not rely on other tests
- Cleanup: Use
IDisposablefor test fixtures that need cleanup - Fast Tests: Unit tests should run in milliseconds
- Deterministic: Tests should not be flaky or depend on timing
- Readable: Use FluentAssertions for clear, readable assertions