Skip to content

Commit 2365f88

Browse files
committed
Update tests.md
1 parent bd3c5f5 commit 2365f88

File tree

1 file changed

+77
-160
lines changed

1 file changed

+77
-160
lines changed

steering_docs/dotnet-tech/tests.md

Lines changed: 77 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ read_documentation("https://docs.aws.amazon.com/[service]/latest/[relevant-page]
2121
**FAILURE TO COMPLETE KNOWLEDGE BASE CONSULTATION WILL RESULT IN INCORRECT CODE STRUCTURE**
2222

2323
## Purpose
24-
Generate integration test suites using MSTest framework to validate complete scenario workflows against real AWS services.
24+
Generate integration test suites using xUnit framework to validate complete scenario workflows against real AWS services.
2525

2626
## Requirements
2727
- **Integration Tests Only**: Focus on end-to-end scenario testing, not unit tests
2828
- **Real AWS Services**: Tests run against actual AWS infrastructure
29-
- **Proper Attributes**: Use MSTest attributes for test categorization
29+
- **Proper Attributes**: Use xUnit attributes for test categorization
3030
- **Async Testing**: Use async Task for async test methods
3131
- **Resource Cleanup**: Ensure proper cleanup of AWS resources after tests
3232

@@ -40,7 +40,7 @@ dotnetv4/{Service}/Tests/
4040
**CRITICAL:**
4141
-**Integration tests ONLY** - no separate unit tests for wrapper methods
4242
-**All tests in one project** - no separate IntegrationTests project
43-
-**Use MSTest framework** - not xUnit
43+
-**Use xUnit framework** - not MSTest
4444
-**Test against real AWS** - not mocks
4545

4646
## Test Project Setup
@@ -59,10 +59,16 @@ dotnetv4/{Service}/Tests/
5959
</PropertyGroup>
6060

6161
<ItemGroup>
62-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
63-
<PackageReference Include="MSTest.TestAdapter" Version="3.1.1" />
64-
<PackageReference Include="MSTest.TestFramework" Version="3.1.1" />
65-
<PackageReference Include="coverlet.collector" Version="6.0.0" />
62+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0" />
63+
<PackageReference Include="xunit" Version="2.9.3" />
64+
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
65+
<PrivateAssets>all</PrivateAssets>
66+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
67+
</PackageReference>
68+
<PackageReference Include="coverlet.collector" Version="6.0.4">
69+
<PrivateAssets>all</PrivateAssets>
70+
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
71+
</PackageReference>
6672
<PackageReference Include="AWSSDK.{Service}" Version="3.7.401" />
6773
<PackageReference Include="AWSSDK.{ServiceDataAPI}" Version="3.7.401" />
6874
</ItemGroup>
@@ -81,7 +87,7 @@ dotnetv4/{Service}/Tests/
8187
```
8288

8389
**Key Changes:**
84-
- ✅ Use MSTest packages instead of xUnit
90+
- ✅ Use xUnit packages (not MSTest)
8591
- ✅ Target .NET 8.0 with latest language version
8692
- ✅ Use latest AWS SDK package versions
8793
- ✅ Reference Actions project only (no Scenarios reference needed)
@@ -92,176 +98,86 @@ dotnetv4/{Service}/Tests/
9298
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
9399
// SPDX-License-Identifier: Apache-2.0
94100
95-
using System;
96101
using System.Threading.Tasks;
97102
using Amazon.{Service};
98103
using Amazon.{ServiceDataAPI};
99-
using Microsoft.VisualStudio.TestTools.UnitTesting;
100104
using {Service}Actions;
105+
using Xunit;
101106

102107
namespace {Service}Tests;
103108

104109
/// <summary>
105110
/// Integration tests for Amazon {Service} operations.
106111
/// These tests require actual AWS credentials and will create real AWS resources.
107112
/// </summary>
108-
[TestClass]
109113
public class {Service}IntegrationTests
110114
{
111-
private static {Service}Wrapper? _{service}Wrapper;
112-
private static string? _testResourceIdentifier;
113-
private const string TestDatabaseName = "dev";
114-
private const string TestUsername = "testuser";
115-
private const string TestPassword = "TestPassword123!";
116-
117-
[ClassInitialize]
118-
public static void ClassInitialize(TestContext context)
115+
/// <summary>
116+
/// Verifies the scenario with an integration test. No exceptions should be thrown.
117+
/// </summary>
118+
/// <returns>Async task.</returns>
119+
[Fact]
120+
[Trait("Category", "Integration")]
121+
public async Task TestScenarioIntegration()
119122
{
120-
// Initialize clients
121-
var {service}Client = new Amazon{Service}Client();
122-
var {service}DataClient = new Amazon{ServiceDataAPI}Client();
123-
_{service}Wrapper = new {Service}Wrapper({service}Client, {service}DataClient);
124-
125-
// Generate unique resource identifier
126-
_testResourceIdentifier = $"test-resource-{DateTime.Now:yyyyMMddHHmmss}";
127-
128-
Console.WriteLine($"Integration tests will use resource: {_testResourceIdentifier}");
129-
}
123+
// Arrange
124+
{Service}Basics.{Service}Basics.IsInteractive = false;
130125

131-
[ClassCleanup]
132-
public static async Task ClassCleanup()
133-
{
134-
// Clean up any remaining test resources
135-
if (_{service}Wrapper != null && !string.IsNullOrEmpty(_testResourceIdentifier))
136-
{
137-
try
138-
{
139-
Console.WriteLine($"Cleaning up test resource: {_testResourceIdentifier}");
140-
await _{service}Wrapper.DeleteResourceAsync(_testResourceIdentifier);
141-
Console.WriteLine("Test resource cleanup initiated.");
142-
}
143-
catch (Exception ex)
144-
{
145-
Console.WriteLine($"Warning: Failed to cleanup test resource: {ex.Message}");
146-
}
147-
}
126+
// Act
127+
{Service}Basics.{Service}Basics.Wrapper = new {Service}Wrapper(
128+
new Amazon{Service}Client(),
129+
new Amazon{ServiceDataAPI}Client());
130+
131+
await {Service}Basics.{Service}Basics.RunScenarioAsync();
132+
133+
// Assert - if we get here without exceptions, the test passes
148134
}
149135
}
150136
```
151137

152138
**Key Changes:**
153139
- ✅ Use file-scoped namespaces
154-
- ✅ Use MSTest attributes ([TestClass], [TestMethod], [ClassInitialize], [ClassCleanup])
140+
- ✅ Use xUnit attributes ([Fact], [Trait])
155141
- ✅ No mocking - test against real AWS services
156-
- ✅ Include proper resource cleanup in ClassCleanup
142+
- ✅ Test runs the complete scenario end-to-end
143+
- ✅ Set IsInteractive = false for non-interactive test execution
157144

158145
## Integration Test Patterns
159146

160-
### Basic Integration Test
161-
```csharp
162-
[TestMethod]
163-
[TestCategory("Integration")]
164-
public async Task DescribeResources_Integration_ReturnsResourceList()
165-
{
166-
// Act
167-
var resources = await _{service}Wrapper!.DescribeResourcesAsync();
147+
### Integration Test Pattern
148+
The integration test should run the complete scenario end-to-end:
168149

169-
// Assert
170-
Assert.IsNotNull(resources);
171-
// Note: We don't assert specific count since other resources might exist
172-
Console.WriteLine($"Found {resources.Count} existing resources.");
173-
}
174-
```
175-
176-
### Full Workflow Integration Test
177150
```csharp
178-
[TestMethod]
179-
[TestCategory("Integration")]
180-
[TestCategory("LongRunning")]
181-
public async Task {Service}FullWorkflow_Integration_CompletesSuccessfully()
182-
{
183-
// This test runs the complete {Service} workflow
184-
// Note: This test can take 10-15 minutes to complete
185-
186-
try
187-
{
188-
Console.WriteLine("Starting {Service} full workflow integration test...");
189-
190-
// Step 1: Create resource
191-
Console.WriteLine($"Creating resource: {_testResourceIdentifier}");
192-
var createdResource = await _{service}Wrapper!.CreateResourceAsync(
193-
_testResourceIdentifier!,
194-
TestDatabaseName,
195-
TestUsername,
196-
TestPassword);
197-
198-
Assert.IsNotNull(createdResource);
199-
Assert.AreEqual(_testResourceIdentifier, createdResource.Identifier);
200-
Console.WriteLine("Resource creation initiated successfully.");
201-
202-
// Step 2: Wait for resource to become available
203-
Console.WriteLine("Waiting for resource to become available...");
204-
await WaitForResourceAvailable(_testResourceIdentifier!, TimeSpan.FromMinutes(20));
205-
206-
// Step 3: Perform operations
207-
Console.WriteLine("Performing operations...");
208-
var result = await _{service}Wrapper.PerformOperationAsync(_testResourceIdentifier!);
209-
Assert.IsNotNull(result);
210-
Console.WriteLine("Operations completed successfully.");
211-
212-
Console.WriteLine("Full workflow integration test completed successfully!");
213-
}
214-
finally
215-
{
216-
// Clean up - Delete resource
217-
if (!string.IsNullOrEmpty(_testResourceIdentifier))
218-
{
219-
Console.WriteLine($"Deleting test resource: {_testResourceIdentifier}");
220-
try
221-
{
222-
var deletedResource = await _{service}Wrapper!.DeleteResourceAsync(_testResourceIdentifier);
223-
Assert.IsNotNull(deletedResource);
224-
Console.WriteLine("Resource deletion initiated successfully.");
225-
}
226-
catch (Exception ex)
227-
{
228-
Console.WriteLine($"Failed to delete resource: {ex.Message}");
229-
throw;
230-
}
231-
}
232-
}
233-
}
234-
235151
/// <summary>
236-
/// Wait for a resource to become available with timeout.
152+
/// Verifies the scenario with an integration test. No exceptions should be thrown.
237153
/// </summary>
238-
/// <param name="resourceIdentifier">The resource identifier.</param>
239-
/// <param name="timeout">Maximum time to wait.</param>
240-
private async Task WaitForResourceAvailable(string resourceIdentifier, TimeSpan timeout)
154+
/// <returns>Async task.</returns>
155+
[Fact]
156+
[Trait("Category", "Integration")]
157+
public async Task TestScenarioIntegration()
241158
{
242-
var startTime = DateTime.UtcNow;
243-
var endTime = startTime.Add(timeout);
159+
// Arrange
160+
{Service}Basics.{Service}Basics.IsInteractive = false;
244161

245-
while (DateTime.UtcNow < endTime)
246-
{
247-
var resources = await _{service}Wrapper!.DescribeResourcesAsync(resourceIdentifier);
248-
249-
if (resources.Count > 0 && resources[0].Status == "available")
250-
{
251-
Console.WriteLine($"Resource {resourceIdentifier} is now available!");
252-
return;
253-
}
254-
255-
var elapsed = DateTime.UtcNow - startTime;
256-
Console.WriteLine($"Waiting for resource... Elapsed time: {elapsed:mm\\:ss}");
257-
258-
await Task.Delay(TimeSpan.FromSeconds(30)); // Wait 30 seconds between checks
259-
}
162+
// Act
163+
{Service}Basics.{Service}Basics.Wrapper = new {Service}Wrapper(
164+
new Amazon{Service}Client(),
165+
new Amazon{ServiceDataAPI}Client());
260166

261-
throw new TimeoutException($"Resource {resourceIdentifier} did not become available within {timeout.TotalMinutes} minutes.");
167+
await {Service}Basics.{Service}Basics.RunScenarioAsync();
168+
169+
// Assert - if we get here without exceptions, the test passes
262170
}
263171
```
264172

173+
**Key Points:**
174+
- ✅ Use `[Fact]` attribute for test methods
175+
- ✅ Use `[Trait("Category", "Integration")]` for categorization
176+
- ✅ Set `IsInteractive = false` to run without user input
177+
- ✅ Create real AWS clients (not mocked)
178+
- ✅ Call the scenario's `RunScenarioAsync()` method
179+
- ✅ Test passes if no exceptions are thrown
180+
265181
## Test Execution Commands
266182

267183
### All Tests
@@ -281,35 +197,36 @@ dotnet test dotnetv4/{Service}/Tests/{Service}Tests.csproj --filter "TestCategor
281197

282198
## Test Requirements Checklist
283199
-**Test project file created** with proper dependencies
284-
-**MSTest framework** (not xUnit)
200+
-**xUnit framework** (not MSTest)
285201
-**Integration tests only** (no unit tests with mocks)
286-
-**Proper MSTest attributes** (`[TestCategory("Integration")]`)
202+
-**Proper xUnit attributes** (`[Fact]`, `[Trait("Category", "Integration")]`)
287203
-**Test against real AWS services** (not mocks)
288-
-**Proper resource cleanup** in ClassCleanup method
204+
-**Test runs complete scenario** via `RunScenarioAsync()`
289205
-**Async test methods** using `async Task`
290206
-**File-scoped namespaces** for modern C# style
291207

292208
## Integration Test Focus
293209

294-
### Primary Test: Complete Workflow Integration
210+
### Primary Test: Complete Scenario Integration
295211
The main integration test should:
296-
-**Run the entire workflow** from start to finish
212+
-**Run the entire scenario** from start to finish via `RunScenarioAsync()`
297213
-**Test against real AWS services** (not mocks)
298-
-**Create and clean up resources** properly
299-
-**Handle long-running operations** with appropriate timeouts
300-
-**Use TestCategory attributes** for test organization
214+
-**Set IsInteractive = false** for non-interactive execution
215+
-**Create real AWS clients** (not mocked)
216+
-**Use xUnit attributes** (`[Fact]`, `[Trait]`) for test organization
217+
-**Pass if no exceptions** are thrown during execution
301218

302-
### Test Structure Priority
303-
1. **Full Workflow Integration Test** - Most important, tests complete workflow
304-
2. **Basic Operation Tests** - Test individual operations against real AWS
305-
3. **Resource Lifecycle Tests** - Test create, read, update, delete operations
219+
### Test Structure
220+
- **Single Integration Test** - Tests the complete scenario workflow
221+
- **No separate unit tests** - Focus on end-to-end integration only
222+
- **No mocking** - Use real AWS clients and services
306223

307224
## Common Test Failures to Avoid
308225
-**Using mocks instead of real AWS services** in integration tests
309-
-**Missing MSTest attributes** for integration tests
310-
-**Not cleaning up resources** in ClassCleanup
226+
-**Missing xUnit attributes** (`[Fact]`, `[Trait]`) for integration tests
227+
-**Not setting IsInteractive = false** for non-interactive execution
311228
-**Forgetting to set AWS region** in test clients
312-
-**Not handling long-running operations** with timeouts
313229
-**Missing proper async/await patterns** in test methods
314-
-**Using xUnit instead of MSTest** framework
315-
-**Creating separate IntegrationTests project** instead of using Tests project
230+
-**Using MSTest instead of xUnit** framework
231+
-**Creating separate IntegrationTests project** instead of using Tests project
232+
-**Not referencing the Scenarios project** when testing scenarios

0 commit comments

Comments
 (0)