Version: 1.0 | Target: Developers | Updated: February 2026
| Type | Speed | Dependencies | Use For |
|---|---|---|---|
| Unit | Fast (<100ms) | Mocked | Single components |
| Integration | Medium (<5s) | Real/Mixed | Component interaction |
| Performance | Varies | Real | Performance validation |
<ProjectReference Include="..\ACATCore.Tests.Shared\ACATCore.Tests.Shared.csproj" />
<PackageReference Include="Moq" Version="4.20.72" />[TestClass]
public class MyTests : BaseTest { }[TestMethod]
[TestCategory("Unit")]
public void Method_Scenario_ExpectedBehavior()
{
// Arrange
var mock = MockHelper.CreateMockLogger<MyClass>();
var sut = new MyClass(mock.Object);
// Act
var result = sut.DoWork();
// Assert
Assert.IsNotNull(result);
MockHelper.VerifyLoggerCalled(mock, LogLevel.Information);
}[TestMethod]
[TestCategory("Integration")]
public void Integration_Scenario_ExpectedBehavior()
{
using (var workspace = new TestWorkspace("MyTest"))
{
// Arrange
workspace.CreateFile("config.json", "{}");
var service = new MyService(workspace.WorkspaceRoot);
// Act
var result = service.Process();
// Assert
Assert.IsTrue(workspace.FileExists("output.txt"));
}
}[TestMethod]
[TestCategory("Performance")]
public void Performance_LargeDataset_CompletesQuickly()
{
var data = TestDataGenerator.RandomList(() => new Item(), 10000);
AssertCompletesWithin(() =>
{
processor.ProcessAll(data);
}, TimeSpan.FromSeconds(1), "10K items in <1s");
}// Simple mock
var mock = MockHelper.CreateMockLogger<MyClass>();
// Capturing mock
var messages = new List<string>();
var mock = MockHelper.CreateCapturingLogger<MyClass>(messages);
// Strict mock (throws on unexpected calls)
var mock = MockHelper.CreateStrictMock<IMyInterface>();// Setup
mock.Setup(x => x.Method(It.IsAny<string>())).Returns("result");
// Verify
MockHelper.VerifyLoggerCalled(mock, LogLevel.Information);
MockHelper.VerifyLoggerCalledWithMessage(mock, "expected");
mock.Verify(x => x.Method("value"), Times.Once);string name = TestDataGenerator.RandomString(10);
int value = TestDataGenerator.RandomInt(1, 100);
bool flag = TestDataGenerator.RandomBool();
string guid = TestDataGenerator.RandomGuid();
string item = TestDataGenerator.RandomItem("A", "B", "C");
var list = TestDataGenerator.RandomList(() => new Item(), 10);public class MyDataBuilder : TestDataBuilder<MyData>
{
private string _name = "Default";
public MyDataBuilder WithName(string name)
{
_name = name;
return this;
}
public override MyData Build()
{
return new MyData { Name = _name };
}
public override void Reset()
{
_name = "Default";
}
}
// Usage
var data = new MyDataBuilder().WithName("Test").Build();AssertHelper.CollectionContainsExactly(items, "A", "B", "C");
AssertHelper.CollectionContainsAll(items, "A", "B");
AssertHelper.CollectionDoesNotContain(items, "X", "Y");AssertHelper.StringContains(text, "substring");
AssertHelper.StringDoesNotContain(text, "bad");
AssertHelper.StringStartsWith(text, "prefix");
AssertHelper.StringEndsWith(text, "suffix");AssertHelper.InRange(value, 1, 100);
AssertHelper.DoubleClose(actual, expected, 0.001);
AssertHelper.DateTimeClose(actual, expected, TimeSpan.FromSeconds(1));AssertHelper.All(items, x => x.IsValid);
AssertHelper.Any(items, x => x.IsSpecial);
AssertHelper.None(items, x => x.IsDeleted);AssertThrows<ArgumentNullException>(() => Method(null));
AssertNoThrow(() => Method(validArg));
AssertCompletesWithin(() => LongOperation(), TimeSpan.FromSeconds(5));// Automatic TestDirectory created/cleaned up
string file = CreateTempFile("test.txt", "content");
string dir = CreateTempDirectory("subdir");using (var workspace = new TestWorkspace("TestName"))
{
// Create
workspace.CreateDirectory("configs");
workspace.CreateFile("configs/settings.json", "{}");
// Check
bool exists = workspace.FileExists("configs/settings.json");
// Read
string content = workspace.ReadFile("configs/settings.json");
// Get path
string fullPath = workspace.GetPath("configs");
// List files
var files = workspace.GetFiles("*.json");
// Auto cleanup on dispose
}WriteTestInfo("Important information");
WriteTestDebug("Debug details");
WriteTestWarning("Warning message");// Stopwatch automatically started
var elapsed = Stopwatch.ElapsedMilliseconds;
// Measure specific operation
var duration = MeasureTime(() => Operation());# All tests
dotnet test
# Specific project
dotnet test Libraries/ACATCore.Tests.Logging/
# By category
dotnet test --filter "TestCategory=Unit"
dotnet test --filter "TestCategory=Integration"
# By name
dotnet test --filter "FullyQualifiedName~ActuatorSettings"
# Detailed output
dotnet test --logger "console;verbosity=detailed"
# Specific configuration
dotnet test --configuration Release- Open Test Explorer:
Test → Test Explorer(Ctrl+E, T) - Build solution:
Ctrl+Shift+B - Run All: Click "Run All" button
- Run Selected: Right-click → Run Selected Tests
- Debug: Right-click → Debug Selected Tests
Pattern: [Component].Tests.[Category]
ACATCore.Tests.LoggingACATCore.Tests.ConfigurationACATCore.Tests.Integration
Pattern: [ComponentName]Tests
ActuatorSettingsTestsLoggingInfrastructureTestsConfigurationServiceTests
Pattern: [Method]_[Scenario]_[ExpectedBehavior]
LoadConfiguration_ValidFile_ReturnsConfigurationValidateSettings_EmptyList_ThrowsExceptionSerializeJson_DefaultSettings_ProducesValidJson
[TestCategory("Unit")] // Fast, isolated unit tests
[TestCategory("Integration")] // Component interaction tests
[TestCategory("Performance")] // Performance validation tests
[TestCategory("Smoke")] // Quick smoke testsFilter by category:
dotnet test --filter "TestCategory=Unit"
dotnet test --filter "TestCategory=Integration"// Shared state between tests
private static Data _data;
// Tests depending on order
[TestMethod] public void Test1() { /* modifies state */ }
[TestMethod] public void Test2() { /* depends on Test1 */ }
// No assertions
[TestMethod] public void Test() { Method(); } // No assert!
// Testing multiple things
[TestMethod] public void TestEverything() { /* 20 assertions */ }// Each test creates its own data
[TestMethod] public void Test1()
{
var data = CreateTestData();
// test code
}
// Independent tests
[TestMethod] public void Method_Scenario1_Behavior1() { }
[TestMethod] public void Method_Scenario2_Behavior2() { }
// Clear assertions
[TestMethod]
public void Method_Scenario_ExpectedBehavior()
{
var result = Method();
Assert.AreEqual(expected, result, "Clear message");
}
// Test one thing
[TestMethod]
public void LoadConfig_ValidFile_ReturnsConfiguration()
{
var config = loader.Load("valid.json");
Assert.IsNotNull(config);
}Comprehensive Guides:
- TESTING_INFRASTRUCTURE.md - Full infrastructure guide
- TESTING_MIGRATION_GUIDE.md - Migration guide
- ACATCore.Tests.Shared README - Library docs
Examples:
- ExampleTests.cs - Usage examples
- TESTING_GUIDE.md - Configuration tests
Project Docs:
- QUICK_START_INTEGRATION_TESTS.md - Quick start
- INDEX.md - Consolidated documentation index
- Inherit BaseTest - Automatic setup/cleanup
- Use TestWorkspace - Isolated file operations
- Mock dependencies - Fast, reliable tests
- Test one thing - Single responsibility
- Clear names - Self-documenting tests
- Add categories - Enable filtering
- Write tests first - TDD approach
- Keep tests fast - Quick feedback loop
Questions? See comprehensive docs above or contact ACAT dev team.
Issues? Check Troubleshooting section.
Last Updated: February 2026 | Version: 1.0