testing

YosrBennagra's avatarfrom YosrBennagra

Unified testing strategy for the .NET 8 WPF widget host app - domain unit tests, ViewModel tests, integration tests, and test infrastructure. Use when writing tests for entities, ViewModels, repositories, or setting up test harnesses.

⭐0stars🔀0forks📁View on GitHub🕐Updated Jan 11, 2026

When & Why to Use This Skill

This Claude skill provides a comprehensive and unified testing strategy specifically designed for .NET 8 WPF applications. It establishes clear patterns and infrastructure for domain logic validation, ViewModel behavior testing, and repository integration, ensuring high-quality code through a structured 'Definition of Done' and standardized naming conventions.

Use Cases

  • Case 1: Implementing deterministic unit tests for domain entities and business logic to ensure core invariants and validation rules are consistently met.
  • Case 2: Testing WPF ViewModels and UI commands using specialized test harnesses to verify state transitions and property changes without requiring a full WPF runtime.
  • Case 3: Creating robust integration tests for data access layers using isolated in-memory or temporary databases to validate repository CRUD operations and migrations.
  • Case 4: Standardizing test infrastructure and naming conventions across a development team to maintain a clean, scalable, and professional test suite.
nametesting
descriptionUnified testing strategy for the .NET 8 WPF widget host app - domain unit tests, ViewModel tests, integration tests, and test infrastructure. Use when writing tests for entities, ViewModels, repositories, or setting up test harnesses.

Testing

Overview

Comprehensive testing strategy covering domain logic, UI behavior, and data access with clear patterns for each layer.

Test Project Structure

Project Focus Dependencies
3SC.Domain.Tests Entities, value objects, domain logic Domain only
3SC.UI.Tests ViewModels, commands, converters UI + mocks
3SC.Infrastructure.Tests Repositories, data access Infrastructure + test DB

1. Domain Tests

Scope

  • Entity invariants and behavior
  • Value object equality and validation
  • Domain service logic
  • Pure application use cases

Rules

  • No infrastructure dependencies
  • No UI dependencies
  • Deterministic (no DateTime.Now, no random)
  • Fast (< 1 second per test)

Patterns

[Fact]
public void Widget_WithNullName_ThrowsArgumentException()
{
    Assert.Throws<ArgumentException>(() => new Widget(null!, "key"));
}

2. ViewModel Tests (UI Tests)

Scope

  • Command execution and can-execute
  • Observable property changes
  • State transitions
  • Validation logic

Rules

  • Use NoOp/mock service implementations
  • No WPF runtime dependency
  • Test via WidgetTestHarness when services needed

Patterns

[Fact]
public void Command_WhenExecuted_UpdatesProperty()
{
    var vm = new MyViewModel(new FakeService());
    vm.SomeCommand.Execute(null);
    Assert.True(vm.IsCompleted);
}

3. Integration Tests (Data Tests)

Scope

  • Repository CRUD operations
  • Query behavior
  • Migration validation
  • Transaction handling

Rules

  • Isolated DB per test (in-memory or temp file)
  • Migrations applied before tests
  • Explicit data seeding (no shared fixtures)
  • Proper cleanup in Dispose

Patterns

public class WidgetRepositoryTests : IDisposable
{
    private readonly AppDbContext _context;
    
    public WidgetRepositoryTests()
    {
        _context = DbTestFactory.CreateInMemory();
    }
    
    [Fact]
    public async Task Add_PersistsWidget()
    {
        var repo = new WidgetRepository(_context);
        await repo.AddAsync(new Widget("Test", "key"));
        Assert.Single(await repo.GetAllAsync());
    }
    
    public void Dispose() => _context.Dispose();
}

Definition of Done (DoD)

Domain Tests

  • New domain logic has corresponding unit tests
  • Tests cover happy path + at least one edge/error case
  • Tests are deterministic
  • Tests run in under 1 second each

ViewModel Tests

  • Commands tested for execute and can-execute behavior
  • State changes tested through observable property assertions
  • Test harness updated when new services are added

Integration Tests

  • Each test gets isolated DB instance
  • Migrations applied automatically before tests
  • Repository tests cover CRUD + edge cases
  • Tests clean up resources in Dispose

Test Infrastructure

WidgetTestHarness

Located in 3SC.UI.Tests/WidgetTestHarness.cs - provides NoOp implementations of all widget services for isolated ViewModel testing.

DbTestFactory

Located in 3SC.Infrastructure.Tests/DbTestFactory.cs - creates isolated in-memory or file-based test databases.


Naming Conventions

{MethodName}_{Scenario}_{ExpectedResult}

Examples:

  • GetById_WithValidId_ReturnsWidget
  • Add_WithDuplicateKey_ThrowsException
  • Execute_WhenDisabled_DoesNotRun

Anti-Patterns

  • ❌ Tests depending on other tests' data
  • ❌ Shared mutable state across tests
  • ❌ Testing private methods directly
  • ❌ Fragile UI selectors in ViewModel tests
  • ❌ DateTime.Now or Random in tests