Loading...
Loading...
Specialized skill for .NET unit testing fundamentals and FIRST principles. Use this skill when you need to create unit tests, understand testing fundamentals, learn the 3A Pattern, or master testing best practices. Covers FIRST principles, AAA Pattern, Fact/Theory, test pyramid, etc. Keywords: unit test, unit testing, test fundamentals, FIRST principle, 3A pattern, AAA pattern, Arrange Act Assert, Fact, Theory, InlineData, how to write tests, testing best practices, creating unit tests
npx skill4agent add kevintsengtw/dotnet-testing-agent-skills dotnet-testing-unit-test-fundamentals[Fact] // Fast: No dependency on external resources, executes quickly
public void Add_Input1And2_ShouldReturn3()
{
// In-memory operation only, no I/O or network latency
var calculator = new Calculator();
var result = calculator.Add(1, 2);
Assert.Equal(3, result);
}[Fact] // Independent: Each test creates a new instance
public void Increment_StartFrom0_ShouldReturn1()
{
var counter = new Counter(); // Each test creates a new instance, unaffected by other tests
counter.Increment();
Assert.Equal(1, counter.Value);
}[Fact] // Repeatable: Produces the same result every execution
public void Increment_MultipleExecutions_ShouldProduceConsistentResults()
{
var counter = new Counter();
counter.Increment();
counter.Increment();
counter.Increment();
// This test will produce the same result every time it runs
Assert.Equal(3, counter.Value);
}[Fact] // Self-Validating: Explicit verification
public void IsValidEmail_InputValidEmail_ShouldReturnTrue()
{
var emailHelper = new EmailHelper();
var result = emailHelper.IsValidEmail("test@example.com");
Assert.True(result); // Clear pass or fail
}[Fact]
public void Add_InputNegativeAndPositiveNumbers_ShouldReturnCorrectResult()
{
// Arrange - Prepare test data and dependent objects
var calculator = new Calculator();
const int a = -5;
const int b = 3;
const int expected = -2;
// Act - Execute the method under test
var result = calculator.Add(a, b);
// Assert - Verify if the result meets expectations
Assert.Equal(expected, result);
}| Block | Responsibility | Notes |
|---|---|---|
| Arrange | Prepare test data, objects, and Mocks | Use |
| Act | Execute the method under test | Usually only one line, calling the tested method |
| Assert | Verify the result | Each test should only verify one behavior |
[MethodUnderTest]_[TestScenario]_[ExpectedBehavior]| Method Name | Description |
|---|---|
| Test normal input |
| Test boundary conditions |
| Test exception cases |
| Test invalid input |
| Test return value |
💡 Tip: Using Chinese names for tests makes test reports more readable, especially during team communication.
[Fact]
public void Add_Input0And0_ShouldReturn0()
{
var calculator = new Calculator();
var result = calculator.Add(0, 0);
Assert.Equal(0, result);
}[Theory]
[InlineData(1, 2, 3)]
[InlineData(-1, 1, 0)]
[InlineData(0, 0, 0)]
[InlineData(100, -50, 50)]
public void Add_InputVariousNumberCombinations_ShouldReturnCorrectResult(int a, int b, int expected)
{
var calculator = new Calculator();
var result = calculator.Add(a, b);
Assert.Equal(expected, result);
}[Theory]
[InlineData("invalid-email")]
[InlineData("@example.com")]
[InlineData("test@")]
[InlineData("test.example.com")]
public void IsValidEmail_InputInvalidEmailFormats_ShouldReturnFalse(string invalidEmail)
{
var emailHelper = new EmailHelper();
var result = emailHelper.IsValidEmail(invalidEmail);
Assert.False(result);
}[Fact]
public void Divide_Input10And0_ShouldThrowDivideByZeroException()
{
// Arrange
var calculator = new Calculator();
const decimal dividend = 10m;
const decimal divisor = 0m;
// Act & Assert
var exception = Assert.Throws<DivideByZeroException>(
() => calculator.Divide(dividend, divisor)
);
// Verify exception message
Assert.Equal("Divisor cannot be zero", exception.Message);
}Solution/
├── src/
│ └── MyProject/
│ ├── Calculator.cs
│ └── MyProject.csproj
└── tests/
└── MyProject.Tests/
├── CalculatorTests.cs
└── MyProject.Tests.csproj<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<Using Include="Xunit" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\MyProject\MyProject.csproj" />
</ItemGroup>
</Project>| Assertion Method | Purpose |
|---|---|
| Verify equality |
| Verify inequality |
| Verify condition is true |
| Verify condition is false |
| Verify object is null |
| Verify object is not null |
| Verify specific exception is thrown |
| Verify collection is empty |
| Verify collection contains item |