본문으로 건너뛰기
cccskills
무료GitHub에 공개

dotnet-testing-awesome-assertions-guide

Using AwesomeAssertions for fluent and readable test assertion skill. Used when writing clear assertions, comparing objects, validating collections, handling complex comparisons. Covers Should(), BeEquivalentTo(), Contain(), ThrowAsync() and complete API. Keywords: assertions, awesome assertions, fluent assertions, assertion, fluent assertion, Should(), Be(), BeEquivalentTo, Contain, ThrowAsync, NotBeNull, object comparison, collection validation, exception assertion, AwesomeAssertions, FluentAssertions, fluent syntax

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

설치 방법 보기

포함된 파일(1)

  • SKILL.md10.3 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

Source: kevintsengtw/dotnet-testing-agent-skills (MIT). Ported into dotnet-agent-harness.

AwesomeAssertions Fluent Assertion Guide

This skill provides a complete guide for writing high-quality test assertions using AwesomeAssertions, covering basic syntax, advanced techniques, and best practices.

Applicable Scenarios

Use this skill when asked to perform the following tasks:

  • Write clear, highly readable test assertions
  • Compare complex objects or collection contents
  • Verify exception throwing and messages
  • Use fluent syntax (Should/Be/Contain) for test validation
  • Replace native Assert with AwesomeAssertions

About AwesomeAssertions

AwesomeAssertions is a community fork version of FluentAssertions, using Apache 2.0 license, completely free with no commercial usage restrictions.

Core Features

  • Fully Free: Apache 2.0 license, suitable for commercial projects
  • Fluent Syntax: Supports natural language style method chaining
  • Rich Assertions: Covers objects, collections, strings, numbers, exceptions, and various other types
  • Excellent Error Messages: Provides detailed and easy-to-understand failure information
  • High Performance: Optimized implementation ensures test execution efficiency
  • Extensible: Supports custom Assertion methods

Relationship with FluentAssertions

AwesomeAssertions is a community fork of FluentAssertions, main differences:

ItemFluentAssertionsAwesomeAssertions
LicenseCommercial projects require paymentApache 2.0 (completely free)
NamespaceFluentAssertionsAwesomeAssertions
API CompatibilityOriginalHighly compatible
Community SupportOfficial maintenanceCommunity maintenance

Installation and Setup

NuGet Package Installation

# .NET CLI
dotnet add package AwesomeAssertions

# Package Manager Console
Install-Package AwesomeAssertions
```text

### csproj Setup (Recommended)

```xml
<ItemGroup>
  <PackageReference Include="AwesomeAssertions" Version="9.1.0" PrivateAssets="all" />
</ItemGroup>
```text

### Namespace Import

```csharp
using AwesomeAssertions;
using Xunit;
```text

---

## Core Assertions Syntax

All Assertions start with `.Should()`, combined with fluent method chaining.

| Category | Common Methods | Description |
|------|----------|------|
| **Object** | `NotBeNull()`, `BeOfType<T>()`, `BeEquivalentTo()` | Null, type, equality checks |
| **String** | `Contain()`, `StartWith()`, `MatchRegex()`, `BeEquivalentTo()` | Content, patterns, case-insensitive comparison |
| **Number** | `BeGreaterThan()`, `BeInRange()`, `BeApproximately()` | Comparison, range, floating point precision |
| **Collection** | `HaveCount()`, `Contain()`, `BeEquivalentTo()`, `AllSatisfy()` | Count, content, order, conditions |
| **Exception** | `Throw<T>()`, `NotThrow()`, `WithMessage()`, `WithInnerException()` | Exception types, messages, nested exceptions |
| **Async** | `ThrowAsync<T>()`, `CompleteWithinAsync()` | Async exceptions and completion validation |

> Full syntax examples and code please refer to [references/core-assertions-syntax.md](references/core-assertions-syntax.md)

---

## Advanced Techniques: Complex Object Comparison

Use `BeEquivalentTo()` with `options` for deep object comparison:

- **Exclude properties**: `options.Excluding(u => u.Id)` — exclude auto-generated fields
- **Dynamic exclusion**: `options.Excluding(ctx => ctx.Path.EndsWith("At"))` — exclude by pattern
- **Circular references**: `options.IgnoringCyclicReferences().WithMaxRecursionDepth(10)`

---

## Advanced Techniques: Custom Assertions Extension

Create domain-specific extension methods, like `product.Should().BeValidProduct()`, and reusable exclusion extensions like `ExcludingAuditFields()`.

Refer to [templates/custom-assertions-template.cs](templates/custom-assertions-template.cs) for complete implementation.

> Full examples please refer to [references/complex-object-assertions.md](references/complex-object-assertions.md)

---

## Performance Optimization Strategies

- **Large data**: First use `HaveCount()` for quick count check, then sample validation (avoid full `BeEquivalentTo`)
- **Selective comparison**: Use anonymous objects + `ExcludingMissingMembers()` to only validate key properties

```csharp
// Selective property comparison — only validate key fields
order.Should().BeEquivalentTo(new
{
    CustomerId = 123,
    TotalAmount = 999.99m,
    Status = "Pending"
}, options => options.ExcludingMissingMembers());
```text

---

## Best Practices and Team Standards

### Test Naming Conventions

Follow `Method_Scenario_ExpectedResult` pattern (e.g., `CreateUser_WithValidEmail_ShouldReturnEnabledUser`).

### Error Message Optimization

Add `because` string in assertions to provide clear failure context:

```csharp
result.IsSuccess.Should().BeFalse("because negative payment amounts are not allowed");
```text

### AssertionScope Usage

Use `AssertionScope` to collect multiple failure messages, display all problems at once:

```csharp
using (new AssertionScope())
{
    user.Should().NotBeNull("User creation should not fail");
    user.Id.Should().BeGreaterThan(0, "User should have valid ID");
    user.Email.Should().NotBeNullOrEmpty("Email is required");
}
```text

---

## Common Scenarios and Solutions

| Scenario | Key Technique |
|------|----------|
| API response validation | `BeEquivalentTo()` + `Including()` selective comparison |
| Database entity validation | `BeEquivalentTo()` + `Excluding()` exclude auto-generated fields |
| Event validation | Subscribe to capture events then validate properties one by one |

> Full code examples please refer to [references/common-scenarios.md](references/common-scenarios.md)

---

## Troubleshooting

### Problem 1: BeEquivalentTo fails but objects look the same

**Reason**: May contain auto-generated fields or timestamps

**Solution**:

```csharp
// Exclude dynamic fields
actual.Should().BeEquivalentTo(expected, options => options
    .Excluding(x => x.Id)
    .Excluding(x => x.CreatedAt)
    .Excluding(x => x.UpdatedAt)
);
```text

### Problem 2: Collection order different causes failure

**Reason**: Collection order is different

**Solution**:

```csharp
// Use BeEquivalentTo ignore order
actual.Should().BeEquivalentTo(expected); // Does not check order

// Or explicitly specify need to check order
actual.Should().Equal(expected); // Checks order
```text

### Problem 3: Floating point comparison fails

**Reason**: Floating point precision issues

**Solution**:

```csharp
// Use precision tolerance
actualValue.Should().BeApproximately(expectedValue, 0.001);
```text

---

## When to Use This Skill

### Applicable Scenarios

Write unit tests or integration tests
Need to validate complex object structures
Compare API responses or database entities
Need clear failure messages
Establish domain-specific testing standards

### Not Applicable Scenarios

Performance testing (use dedicated benchmarking tools)
Load testing (use K6, JMeter, etc.)
UI testing (use Playwright, Selenium)

---

## Integration with Other Skills

### Integration with unit-test-fundamentals

First use `unit-test-fundamentals` to establish test structure, then use this skill to write assertions:

```csharp
[Fact]
public void Calculator_Add_TwoPositiveNumbers_ShouldReturnSum()
{
    // Arrange - follow 3A Pattern
    var calculator = new Calculator();

    // Act
    var result = calculator.Add(2, 3);

    // Assert - use AwesomeAssertions
    result.Should().Be(5);
}
```text

### Integration with test-naming-conventions

Use `test-naming-conventions` naming conventions, combined with this skill's assertions:

```csharp
[Fact]
public void CreateUser_WithValidData_ShouldReturnEnabledUser()
{
    var user = userService.CreateUser("test@example.com");

    user.Should().NotBeNull()
        .And.BeOfType<User>();
    user.IsActive.Should().BeTrue();
}
```text

### Integration with xunit-project-setup

Install and use AwesomeAssertions in projects created with `xunit-project-setup`.

---

## Reference Resources

### Original Articles

This skill content is extracted from "Old School Software Engineer's Testing Practice - 30 Day Challenge" series:

- **Day 04 - AwesomeAssertions Basic Application and Practical Techniques**
  - Ironman Article: https://ithelp.ithome.com.tw/articles/10374188
  - Sample Code: https://github.com/kevintsengtw/30Days_in_Testing_Samples/tree/main/day04

- **Day 05 - AwesomeAssertions Advanced Techniques and Complex Scenario Applications**
  - Ironman Article: https://ithelp.ithome.com.tw/articles/10374425
  - Sample Code: https://github.com/kevintsengtw/30Days_in_Testing_Samples/tree/main/day05

### Official Resources

- **AwesomeAssertions GitHub**: https://github.com/AwesomeAssertions/AwesomeAssertions
- **AwesomeAssertions Official Documentation**: https://awesomeassertions.org/

### Related Articles

- **Fluent Assertions License Change Discussion**: https://www.dotblogs.com.tw/mrkt/2025/04/19/152408

---

## Summary

AwesomeAssertions provides powerful and readable assertion syntax, an important tool for writing high-quality tests. Through:

1. **Fluent Syntax**: Makes test code more readable
2. **Rich Assertions**: Covers various data types
3. **Custom Extensions**: Establish domain-specific assertions
4. **Performance Optimization**: Handle large data scenarios
5. **Completely Free**: Apache 2.0 license with no commercial restrictions

Remember: Good assertions not only validate results but clearly express expected behavior and provide useful diagnostic information when failing.

Refer to [templates/assertion-examples.cs](templates/assertion-examples.cs) for more practical examples.

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Patterns and techniques for evaluating and improving AI agent outputs.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

rudironsoni/Synaxis22026년 3월 17일 업데이트

Comprehensive AI prompt engineering safety review and improvement prompt. Analyzes prompts for safety, bias, security vulnerabilities, and effectiveness while providing detailed improvement recommendations.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

rudironsoni/Synaxis22026년 3월 17일 업데이트

Use when user requests research requiring multiple sources, comprehensive analysis, or synthesis across topics - technical research, domain knowledge gathering, market analysis, or learning about complex subjects

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

rudironsoni/Synaxis22026년 3월 17일 업데이트

deep-wiki

무료

AI-powered wiki generation for code repositories with commands, agents, and skills

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

rudironsoni/Synaxis22026년 3월 17일 업데이트

Use when building .NET 10 or C# 14 applications; when using minimal APIs, modular monolith patterns, or feature folders; when implementing HTTP resilience, Options pattern, Channels, or validation; when seeing outdated patterns like old extension method syntax

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

rudironsoni/Synaxis22026년 3월 17일 업데이트

Implements accessible .NET UI. SemanticProperties, ARIA, AutomationPeer, testing per platform.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

rudironsoni/Synaxis22026년 3월 17일 업데이트

rudironsoni의 스킬 모두 보기

이 스킬의 문제 신고