Built Word Documents (.docx):
Spensara Overview (.docx)
Capability Assessment (.docx)
Brink POS Ingestion Analysis (.docx)
The Borg Ingestion Architecture (.docx)
Categories
Agent Tooling (71)
Automation workflows, orchestration references, and developer tooling guides.
- .agents/skills/agent-browser/references/authentication.md
- .agents/skills/agent-browser/references/commands.md
- .agents/skills/agent-browser/references/profiling.md
- .agents/skills/agent-browser/references/proxy-support.md
- .agents/skills/agent-browser/references/session-management.md
- .agents/skills/agent-browser/references/snapshot-refs.md
- .agents/skills/agent-browser/references/video-recording.md
- .agents/skills/agent-browser/SKILL.md
- .agents/skills/aspire-deployment/references/aws.md
- .agents/skills/aspire-deployment/references/azure.md
- .agents/skills/aspire-deployment/references/cicd.md
- .agents/skills/aspire-deployment/references/docker-compose.md
- .agents/skills/aspire-deployment/references/javascript.md
- .agents/skills/aspire-deployment/references/kubernetes.md
- .agents/skills/aspire-deployment/references/preflight.md
- .agents/skills/aspire-deployment/SKILL.md
- .agents/skills/aspire-monitoring/references/diagnostics-bridge.md
- .agents/skills/aspire-monitoring/references/monitoring.md
- .agents/skills/aspire-monitoring/references/playwright-handoff.md
- .agents/skills/aspire-monitoring/SKILL.md
- .agents/skills/aspire-orchestration/references/agent-workflows.md
- .agents/skills/aspire-orchestration/references/app-commands.md
- .agents/skills/aspire-orchestration/references/detection.md
- .agents/skills/aspire-orchestration/references/resource-management.md
- .agents/skills/aspire-orchestration/references/safety-guardrails.md
- .agents/skills/aspire-orchestration/SKILL.md
- .agents/skills/aspire/references/aspire-13-3-breaking-changes.md
- .agents/skills/aspire/SKILL.md
- .agents/skills/aspireify/references/apphost-wiring.md
- .agents/skills/aspireify/references/csharp-authoring.md
- .agents/skills/aspireify/references/docker-compose.md
- .agents/skills/aspireify/references/full-solution-apphosts.md
- .agents/skills/aspireify/references/javascript-apps.md
- .agents/skills/aspireify/references/opentelemetry.md
- .agents/skills/aspireify/references/scan-and-propose.md
- .agents/skills/aspireify/references/service-defaults.md
- .agents/skills/aspireify/references/typescript-authoring.md
- .agents/skills/aspireify/references/validation.md
- .agents/skills/aspireify/SKILL.md
- .agents/skills/caveman-compress/README.md
- .agents/skills/caveman-compress/SECURITY.md
- .agents/skills/caveman-compress/SKILL.md
- .agents/skills/caveman-help/README.md
- .agents/skills/caveman-help/SKILL.md
- .agents/skills/caveman-stats/README.md
- .agents/skills/caveman-stats/SKILL.md
- .agents/skills/caveman/README.md
- .agents/skills/caveman/SKILL.md
- .agents/skills/csharp-developer/SKILL.md
- .agents/skills/dotnet-inspect/SKILL.md
- .agents/skills/efcore-data-layer/SKILL.md
- .agents/skills/git/SKILL.md
- .agents/skills/microsoft-code-reference/SKILL.md
- .agents/skills/microsoft-docs/SKILL.md
- .agents/skills/microsoft-skill-creator/references/skill-templates.md
- .agents/skills/microsoft-skill-creator/SKILL.md
- .agents/skills/skill-creator/references/output-patterns.md
- .agents/skills/skill-creator/references/workflows.md
- .agents/skills/skill-creator/SKILL.md
- .agents/skills/tunit-testing/references/aspire-integration.md
- .agents/skills/tunit-testing/references/aspnetcore-integration.md
- .agents/skills/tunit-testing/references/assertions.md
- .agents/skills/tunit-testing/references/data-driven.md
- .agents/skills/tunit-testing/references/infrastructure-and-troubleshooting.md
- .agents/skills/tunit-testing/references/lifecycle-hooks.md
- .agents/skills/tunit-testing/SKILL.md
- AGENTS.md
- backend/AGENTS.md
- backend/tests/AGENTS.md
- Front/AGENT.md
- opencode.jsonc
Data-Driven Testing
Comprehensive guide to data-driven testing patterns in TUnit.
Table of Contents
Basic Arguments
Use [Arguments(...)] for compile-time constant values:
csharp
[Test]
[Arguments(2, 3, 5)]
[Arguments(10, 20, 30)]
[Arguments(-1, 1, 0)]
public async Task Add_WithNumbers_ReturnsSum(int a, int b, int expected)
{
var result = Calculator.Add(a, b);
await Assert.That(result).IsEqualTo(expected);
}With Display Names
csharp
[Test]
[Arguments(1, 1, 2, DisplayName = "One plus one equals two")]
[Arguments(0, 0, 0, DisplayName = "Zero plus zero equals zero")]
[Arguments(-1, 1, 0, DisplayName = "Negative and positive cancel out")]
public async Task Addition(int a, int b, int expected)
{
await Assert.That(a + b).IsEqualTo(expected);
}Display names support parameter substitution:
csharp
[Arguments(2, 3, 5, DisplayName = "Adding $a + $b = $expected")]
[Arguments(10, 5, 15, DisplayName = "$arg1 + $arg2 = $arg3")]With Categories
csharp
[Test]
[Arguments(100, 50, Categories = new[] { "LargeNumbers", "Performance" })]
[Arguments(1, 1, Categories = new[] { "SmallNumbers", "Smoke" })]
public async Task CategorizedTests(int a, int b)
{
await Assert.That(a + b).IsGreaterThan(0);
}Skipping Test Cases
csharp
[Test]
[Arguments("Chrome", "120")]
[Arguments("Firefox", "121")]
[Arguments("Safari", "17", Skip = "Safari testing not available in CI")]
public async Task BrowserTest(string browser, string version)
{
// Test implementation
}Method Data Sources
For dynamic data or complex objects, use [MethodDataSource]:
Simple Objects
csharp
public record AdditionTestData(int Value1, int Value2, int ExpectedResult);
public static class TestDataSources
{
public static IEnumerable<Func<AdditionTestData>> AdditionData()
{
yield return () => new AdditionTestData(1, 2, 3);
yield return () => new AdditionTestData(2, 2, 4);
yield return () => new AdditionTestData(5, 5, 10);
}
}
public class CalculatorTests
{
[Test]
[MethodDataSource(typeof(TestDataSources), nameof(TestDataSources.AdditionData))]
public async Task Add_WithTestData_ReturnsExpected(AdditionTestData data)
{
var result = Calculator.Add(data.Value1, data.Value2);
await Assert.That(result).IsEqualTo(data.ExpectedResult);
}
}Important: Return Func<T> (not just T) to ensure each test gets a fresh instance.
Using Tuples
csharp
public static class TestDataSources
{
public static IEnumerable<Func<(int, int, int)>> AdditionData()
{
yield return () => (1, 2, 3);
yield return () => (2, 2, 4);
yield return () => (5, 5, 10);
}
}
[Test]
[MethodDataSource(typeof(TestDataSources), nameof(TestDataSources.AdditionData))]
public async Task Add_WithTuples_ReturnsSum(int a, int b, int expected)
{
var result = Calculator.Add(a, b);
await Assert.That(result).IsEqualTo(expected);
}Same-Class Data Source
If the data source is in the same class, omit the type parameter:
csharp
public class CalculatorTests
{
public static IEnumerable<Func<(int, int, int)>> AdditionData()
{
yield return () => (1, 2, 3);
yield return () => (2, 2, 4);
}
[Test]
[MethodDataSource(nameof(AdditionData))]
public async Task Add_ReturnsSum(int a, int b, int expected)
{
var result = Calculator.Add(a, b);
await Assert.That(result).IsEqualTo(expected);
}
}Async Data Sources
Use IAsyncEnumerable<T> for async data loading (e.g., from database or API):
csharp
public record AsyncTestData(int Id, string Name, DateTime CreatedAt);
public static class AsyncDataSources
{
public static async IAsyncEnumerable<Func<AsyncTestData>> GetAsyncData(
[EnumeratorCancellation] CancellationToken ct = default)
{
for (int i = 1; i <= 3; i++)
{
ct.ThrowIfCancellationRequested();
// Simulate async data loading
await Task.Delay(10, ct);
yield return () => new AsyncTestData(
Id: i,
Name: $"Item_{i}",
CreatedAt: DateTime.UtcNow.AddDays(-i)
);
}
}
}
[Test]
[MethodDataSource(typeof(AsyncDataSources), nameof(AsyncDataSources.GetAsyncData))]
public async Task TestWithAsyncData(AsyncTestData data)
{
await Assert.That(data.Id).IsGreaterThan(0);
await Assert.That(data.Name).StartsWith("Item_");
}Test Case Metadata
Use TestDataRow for rich metadata on data-driven tests:
csharp
public static IEnumerable<TestDataRow<int, int, int>> AdditionData()
{
yield return new TestDataRow<int, int, int>(1, 2, 3)
{
DisplayName = "Simple addition",
Categories = new[] { "Basic" }
};
yield return new TestDataRow<int, int, int>(100, 200, 300)
{
DisplayName = "Large numbers",
Categories = new[] { "Performance" }
};
yield return new TestDataRow<int, int, int>(int.MaxValue, 1, int.MinValue)
{
DisplayName = "Overflow scenario",
Skip = "Not handling overflow yet"
};
}
[Test]
[MethodDataSource(nameof(AdditionData))]
public async Task Add_WithMetadata(int a, int b, int expected)
{
var result = Calculator.Add(a, b);
await Assert.That(result).IsEqualTo(expected);
}Matrix Testing
Test all combinations of multiple data sets:
csharp
public class MatrixTests
{
public static IEnumerable<int> Numbers() => new[] { 1, 2, 3 };
public static IEnumerable<string> Operations() => new[] { "add", "subtract" };
[Test]
[MatrixData(nameof(Numbers), nameof(Operations))]
public async Task CombinationTest(int number, string operation)
{
// Tests all combinations:
// (1, "add"), (1, "subtract"), (2, "add"), (2, "subtract"), (3, "add"), (3, "subtract")
await Assert.That(number).IsGreaterThan(0);
await Assert.That(operation).IsNotEmpty();
}
}Common Patterns
Testing HTTP Status Codes
csharp
public static IEnumerable<Func<(string, int)>> EndpointTestData()
{
yield return () => ("/alerts", 200);
yield return () => ("/alerts/123", 200);
yield return () => ("/alerts/invalid", 404);
yield return () => ("/unauthorized", 401);
}
[Test]
[MethodDataSource(nameof(EndpointTestData))]
public async Task Endpoint_ReturnsExpectedStatus(string path, int expectedStatus)
{
var client = Factory.CreateClient();
var response = await client.GetAsync(path);
await Assert.That((int)response.StatusCode).IsEqualTo(expectedStatus);
}Testing Validation Rules
csharp
public record ValidationTestCase(string Input, bool IsValid, string? ErrorMessage);
public static IEnumerable<Func<ValidationTestCase>> ValidationData()
{
yield return () => new ValidationTestCase("valid@email.com", true, null);
yield return () => new ValidationTestCase("invalid", false, "Invalid email format");
yield return () => new ValidationTestCase("", false, "Email is required");
}
[Test]
[MethodDataSource(nameof(ValidationData))]
public async Task Validate_Email(ValidationTestCase testCase)
{
var result = EmailValidator.Validate(testCase.Input);
await Assert.That(result.IsValid).IsEqualTo(testCase.IsValid);
if (!testCase.IsValid)
{
await Assert.That(result.ErrorMessage).IsEqualTo(testCase.ErrorMessage);
}
}Database Test Data
csharp
public static async IAsyncEnumerable<Func<UserTestData>> GetUserTestData(
[EnumeratorCancellation] CancellationToken ct = default)
{
// Load from database or API
var users = await LoadTestUsersAsync(ct);
foreach (var user in users)
{
yield return () => new UserTestData(user.Id, user.Name, user.Email);
}
}
[Test]
[MethodDataSource(nameof(GetUserTestData))]
public async Task User_CanBeProcessed(UserTestData userData)
{
await using var scope = Factory.Server.Services.CreateAsyncScope();
var userService = scope.ServiceProvider.GetRequiredService<IUserService>();
var result = await userService.ProcessUserAsync(userData.Id);
await Assert.That(result).IsNotNull();
}Complex Request/Response Testing
csharp
public record ApiTestCase(
string Description,
object RequestBody,
int ExpectedStatus,
Action<object?>? ResponseValidator = null
);
public static IEnumerable<Func<ApiTestCase>> CreateAlertTestCases()
{
yield return () => new ApiTestCase(
"Valid alert creation",
new CreateAlertRequest { Name = "Test", Threshold = 100 },
201,
response => {
var alert = response as AlertResponse;
Assert.That(alert).IsNotNull();
Assert.That(alert!.Name).IsEqualTo("Test");
}
);
yield return () => new ApiTestCase(
"Missing required fields",
new CreateAlertRequest { Name = "" },
400,
null
);
}
[Test]
[MethodDataSource(nameof(CreateAlertTestCases))]
public async Task CreateAlert_TestCase(ApiTestCase testCase)
{
var client = Factory.CreateClient();
var response = await client.PostAsJsonAsync("/alerts", testCase.RequestBody);
await Assert.That((int)response.StatusCode).IsEqualTo(testCase.ExpectedStatus);
if (testCase.ResponseValidator != null)
{
var content = await response.Content.ReadFromJsonAsync<object>();
testCase.ResponseValidator(content);
}
}Best Practices
- Use
Func<T>for reference types - Ensures each test gets a fresh instance - Keep test data centralized - Put data sources in shared classes or same test class
- Use meaningful display names - Makes test reports readable
- Apply categories strategically - Enable selective test execution
- Skip intelligently - Document why tests are skipped
- Prefer tuples for simple cases - Avoid creating types for trivial data
- Use async sources for I/O - Don't block on async operations
- Test edge cases - Include boundary values, nulls, empty collections