Skip to content

Add generic stack creation methods to CdkTestHelper#4

Merged
ncipollina merged 1 commit into
mainfrom
feature/generic-stack-creation
Jul 3, 2025
Merged

Add generic stack creation methods to CdkTestHelper#4
ncipollina merged 1 commit into
mainfrom
feature/generic-stack-creation

Conversation

@ncipollina

Copy link
Copy Markdown
Contributor

Summary

Enhanced CdkTestHelper with generic methods that enable direct creation of custom stack types, eliminating the need for workarounds when testing custom Stack implementations.

Problem Solved

Previously, users with custom stack types (like InfraStack, LightsaberStackProps, etc.) had to use workarounds:

// Old workaround - creates unused base stack
var (app, _) = CdkTestHelper.CreateTestStack("unused-name", props);
var infraStack = new InfraStack(app, "real-name", customProps);

Now they can create custom stacks directly:

// New direct approach - clean and type-safe
var infraStack = CdkTestHelper.CreateTestStackMinimal<InfraStack>("test-stack", customProps);

Changes Made

✨ New Generic Methods

  1. CreateTestStack<TStack>(string stackName, IStackProps stackProps)

    • Creates custom stack types using Activator.CreateInstance with reflection
    • Returns (App app, TStack stack) for advanced scenarios
    • Generic constraint: where TStack : Stack
  2. CreateTestStackMinimal<TStack>(string stackName, IStackProps stackProps)

    • Creates custom stack types with app created internally
    • Returns TStack stack for simplified usage
    • Uses the full generic method internally

🔧 Technical Implementation

  • Reflection-based instantiation: Uses Activator.CreateInstance to create stack types
  • Type safety: Generic constraints ensure only Stack types can be used
  • Standard constructor pattern: Works with any stack that follows (App, string, IStackProps) constructor
  • Strongly-typed returns: Full IntelliSense support for custom stack properties

🧪 Comprehensive Test Coverage

  1. CdkTestHelper_ShouldCreateGenericStackType

    • Tests full generic method with app and stack return
    • Verifies custom stack type instantiation and properties
  2. CdkTestHelper_ShouldCreateGenericStackTypeMinimal

    • Tests minimal generic method (app created internally)
    • Validates custom stack functionality and environment settings
  3. CdkTestHelper_ShouldWorkWithGenericStackAndConstructs

    • End-to-end integration test
    • Custom stack → construct addition → template generation
    • Verifies the complete workflow works seamlessly
  4. TestCustomStack helper class

    • Demonstrates proper custom stack implementation
    • Has custom properties to verify instantiation works correctly

📚 Documentation Updates

README.md

  • New section: "Testing Custom Stack Types" with real-world examples
  • Benefits breakdown: No workarounds, type safety, clean code, real-world ready
  • Usage examples: Shows before/after patterns for clarity

CLAUDE.md

  • Updated testing helpers documentation: Added generic methods to method list
  • New generic stack creation section: Implementation details and usage patterns
  • Technical guidance: Reflection usage and constructor pattern requirements

Real-World Usage Examples

Custom Infrastructure Stack

[Fact]
public void InfraStack_ShouldDeployCorrectly()
{
    var props = new InfraStackProps
    {
        Env = new Environment { Account = "123456789012", Region = "us-east-1" },
        Context = new InfraContext { DatabaseName = "test-db" },
        Tags = new Dictionary<string, string> { { "Environment", "test" } }
    };

    var infraStack = CdkTestHelper.CreateTestStackMinimal<InfraStack>("test-infra", props);
    var template = Template.FromStack(infraStack);
    
    // Test your infrastructure with full type safety
    template.ShouldHaveLambdaFunction("api-function");
    // Access custom stack properties
    infraStack.DatabaseCluster.Should().NotBeNull();
}

LightsaberStackProps Example

[Fact]
public void LightsaberStack_ShouldCreateLambdas()
{
    var context = new EnvironmentContext
    {
        Env = new Environment { Account = "123456789012", Region = "us-east-1" },
        BucketName = "test-bucket",
        FunctionName = "lightsaber-function"
    };
    
    var props = new LightsaberStackProps { Env = context.Env, Context = context };
    
    var stack = CdkTestHelper.CreateTestStackMinimal<LightsaberStack>("test-stack", props);
    var template = Template.FromStack(stack);
    
    // Test with your actual stack type
    template.ShouldHaveLambdaFunction("lightsaber-function-test");
}

Benefits

Eliminates Workarounds: No more unused base stacks
Type Safety: Full IntelliSense and compile-time checking
Clean Testing Code: Reduces boilerplate while maintaining power
Real-World Ready: Works with any custom Stack implementation
Backward Compatible: All existing code continues to work
Well Tested: Comprehensive test coverage including integration scenarios

Test Plan

  • Generic methods create custom stack types correctly
  • Type constraints work properly (only Stack types allowed)
  • Custom stack properties are accessible and functional
  • Integration with constructs and template generation works
  • All existing tests continue to pass
  • Documentation is clear and includes real-world examples

This enhancement makes the testing helpers significantly more practical for real-world CDK projects with custom stack implementations!

🤖 Generated with Claude Code

## Summary
- Added generic methods to create custom stack types directly without workarounds
- Enhanced testing flexibility for projects with custom Stack implementations
- Updated documentation with comprehensive examples and usage patterns

## Changes Made

### ✨ New Generic Methods
- **`CreateTestStack<TStack>(string, IStackProps)`**: Creates custom stack types using reflection
- **`CreateTestStackMinimal<TStack>(string, IStackProps)`**: Creates custom stack types with app created internally

### 🔧 Technical Implementation
- Uses `Activator.CreateInstance` with reflection for stack instantiation
- Generic constraint: `where TStack : Stack` ensures type safety
- Returns strongly-typed stack instances for full IntelliSense support

### 🧪 Comprehensive Test Coverage
- **`CdkTestHelper_ShouldCreateGenericStackType`**: Tests full generic method functionality
- **`CdkTestHelper_ShouldCreateGenericStackTypeMinimal`**: Tests minimal generic method
- **`CdkTestHelper_ShouldWorkWithGenericStackAndConstructs`**: End-to-end integration test
- **`TestCustomStack`**: Test helper class demonstrating custom stack implementation

### 📚 Documentation Updates
- **README.md**: Added new section "Testing Custom Stack Types" with real-world examples
- **CLAUDE.md**: Updated testing helpers documentation and added generic stack creation guidance

## Problem Solved

**Before** (workaround required):
```csharp
var (app, _) = CdkTestHelper.CreateTestStack("unused-name", props);
var infraStack = new InfraStack(app, "real-name", props);  // Manual instantiation
```

**After** (direct custom stack creation):
```csharp
var infraStack = CdkTestHelper.CreateTestStackMinimal<InfraStack>("test-stack", props);
```

## Benefits
✅ **No Workarounds**: Create custom stack types directly
✅ **Type Safety**: Strongly-typed stack instances with full IntelliSense
✅ **Clean Code**: Eliminates boilerplate while maintaining flexibility
✅ **Real-World Ready**: Works with any custom stack implementation (LightsaberStackProps, etc.)
✅ **Backward Compatible**: All existing code continues to work unchanged

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
@ncipollina
ncipollina requested a review from Copilot July 3, 2025 21:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Enhanced testing utilities to allow direct creation of custom CDK stack types via generics, accompanied by new tests and documentation updates.

  • Added two generic methods (CreateTestStack<TStack> and CreateTestStackMinimal<TStack>) to CdkTestHelper
  • Introduced unit and integration tests covering the new generic helpers
  • Updated README and CLAUDE documentation to explain and demonstrate generic stack creation

Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
test/.../TestingHelpersTests.cs Added tests for the generic stack helpers and included a TestCustomStack helper class
src/.../CdkTestHelper.cs Implemented CreateTestStack<TStack> and CreateTestStackMinimal<TStack> methods
README.md Documented generic stack creation with examples
CLAUDE.md Updated testing helpers list to include generic methods
Comments suppressed due to low confidence (1)

test/LayeredCraft.Cdk.Constructs.Tests/Testing/TestingHelpersTests.cs:394

  • [nitpick] Since TestCustomStack is a helper for tests, consider suffixing with Tests or placing it in a dedicated Helpers namespace/file to clearly distinguish it from production stack implementations.
public class TestCustomStack : Amazon.CDK.Stack

}

// Test helper class for generic stack testing
public class TestCustomStack : Amazon.CDK.Stack

Copilot AI Jul 3, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TestCustomStack helper class is declared at the top level without a namespace and shares the test file with your test cases. Consider moving it into its own file and/or adding an appropriate namespace to avoid potential naming collisions and improve clarity.

Copilot uses AI. Check for mistakes.
@ncipollina
ncipollina merged commit dfd78e6 into main Jul 3, 2025
1 check passed
@ncipollina
ncipollina deleted the feature/generic-stack-creation branch July 3, 2025 22:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants