소스 정보
- 저장소
- rudironsoni/Synaxis
- 최근 소스 활동
- 2026년 3월 8일 14:59
- 감지된 SKILL.md 언어
- 영어
- 스타
- 2
- 포크
- 1
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/rudironsoni/Synaxis --skill dotnet-xunit명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
Routes .NET/C# work to domain skills. Loads coding-standards for code paths.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | dotnet-xunit |
| description | Authors xUnit v3 tests -- Facts, Theories, fixtures, parallelism, IAsyncLifetime. |
| metadata | {"short-description":".NET skill guidance for xunit tasks"} |
xUnit v3 testing framework features for .NET. Covers [Fact] and [Theory] attributes, test fixtures (IClassFixture,
ICollectionFixture), parallel execution configuration, IAsyncLifetime for async setup/teardown, custom assertions,
and xUnit analyzers. Includes v2 compatibility notes where behavior differs.
Version assumptions: xUnit v3 primary (.NET 8.0+ baseline). Where v3 behavior differs from v2, compatibility notes are provided inline. xUnit v2 remains widely used; many projects will encounter both versions during migration.
Prerequisites: Test project already scaffolded via [skill:dotnet-add-testing] with xUnit packages referenced. Run [skill:dotnet-version-detection] to confirm .NET 8.0+ baseline for xUnit v3 support.
Cross-references: [skill:dotnet-testing-strategy] for deciding what to test and how, [skill:dotnet-integration-testing] for combining xUnit with WebApplicationFactory and Testcontainers.
| Feature | xUnit v2 | xUnit v3 |
|---|---|---|
| Package | xunit (2.x) | xunit.v3 |
| Runner | xunit.runner.visualstudio | xunit.runner.visualstudio (3.x) |
| Async lifecycle | IAsyncLifetime | IAsyncLifetime (now returns ValueTask) |
| Assert package | Bundled | Separate xunit.v3.assert (or xunit.v3.assert.source for extensibility) |
| Parallelism default | Per-collection | Per-collection (same, but configurable per-assembly) |
| Timeout | Timeout property on [Fact] and [Theory] | Timeout property on [Fact] and [Theory] (unchanged) |
| Test output | ITestOutputHelper | ITestOutputHelper (unchanged) |
[ClassData] | Returns IEnumerable<object[]> | Returns IEnumerable<TheoryDataRow<T>> (strongly typed) |
[MemberData] | Returns IEnumerable<object[]> | Supports TheoryData<T> and TheoryDataRow<T> |
| Assertion messages | Optional string parameter on Assert methods | Removed in favor of custom assertions (v3.0); use Assert.Fail() for explicit messages |
v2 compatibility note: If migrating from v2, replace xunit package with xunit.v3. Most [Fact] and [Theory]
tests work without changes. The primary migration effort is in IAsyncLifetime (return type changes to ValueTask),
[ClassData] (strongly typed row format), and removed assertion message parameters.
[Fact] -- Single Test CaseUse [Fact] for tests with no parameters:
public class DiscountCalculatorTests
{
[Fact]
public void Apply_NegativePercentage_ThrowsArgumentOutOfRangeException()
{
var calculator = new DiscountCalculator();
var ex = Assert.Throws<ArgumentOutOfRangeException>(
() => calculator.Apply(100m, percentage: -5));
Assert.Equal("percentage", ex.ParamName);
}
[Fact]
public async Task ApplyAsync_ValidDiscount_ReturnsDiscountedPrice()
{
var calculator = new DiscountCalculator();
var result = await calculator.ApplyAsync(100m, percentage: 15);
Assert.Equal(85m, result);
}
}
```text
### `[Theory]` -- Parameterized Tests
Use `[Theory]` to run the same test logic with different inputs.
#### `[InlineData]`
Best for simple value types:
```csharp
[Theory]
[InlineData(100, 10, 90)] // 10% off 100 = 90
[InlineData(200, 25, 150)] // 25% off 200 = 150
[InlineData(50, 0, 50)] // 0% off = no change
[InlineData(100, 100, 0)] // 100% off = 0
public void Apply_VariousInputs_ReturnsExpectedPrice(
price, percentage, expected)
{
calculator = DiscountCalculator();
result = calculator.Apply(price, percentage);
Assert.Equal(expected, result);
}
```text
Best complex data shared datasets:
```csharp
{
TheoryData<Order, > ValidationCases => ()
{
{ Order { Items = [(, )], CustomerId = }, },
{ Order { Items = [], CustomerId = }, },
{ Order { Items = [(, )], CustomerId = }, },
};
[]
[]
{
validator = OrderValidator();
result = validator.IsValid(order);
Assert.Equal(expected, result);
}
}
```text
Best data shared across multiple test classes:
```csharp
: <<, , >>
{
IEnumerator<TheoryDataRow<, , >> GetEnumerator()
{
;
;
;
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
[]
[]
{
converter = CurrencyConverter();
rate = converter.GetRate(, to);
Assert.Equal(expectedRate, rate, precision: );
}
```text
---
Fixtures provide shared, expensive resources across tests maintaining test isolation.
{
ConnectionString { ; ; } = ;
{
ConnectionString = ;
ValueTask.CompletedTask;
}
{
ValueTask.CompletedTask;
}
}
: <>
{
DatabaseFixture _db;
{
_db = db;
}
[]
{
repo = OrderRepository(_db.ConnectionString);
result = repo.GetByIdAsync(KnownOrderId);
Assert.NotNull(result);
}
}
```text
**v2 compatibility note:** In xUnit v2, `IAsyncLifetime.InitializeAsync()` `DisposeAsync()` `Task`. In v3, they `ValueTask`. When migrating, change the types accordingly.
Use multiple test classes need the same expensive resource:
```csharp
[]
: <>
{
}
[]
{
DatabaseFixture _db;
{
_db = db;
}
[]
{
}
}
[]
{
DatabaseFixture _db;
{
_db = db;
}
}
```text
For per-test setup/teardown without a shared fixture:
```csharp
:
{
_tempDir = ;
{
_tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(_tempDir);
ValueTask.CompletedTask;
}
{
(Directory.Exists(_tempDir))
Directory.Delete(_tempDir, recursive: );
ValueTask.CompletedTask;
}
[]
{
filePath = Path.Combine(_tempDir, );
File.WriteAllTextAsync(filePath, );
processor = FileProcessor();
records = processor.ProcessAsync(filePath);
Assert.Equal(, records.Count);
}
}
```text
---
xUnit runs test classes within a collection sequentially but runs different collections parallel. Each test `[]` , .
###
####
:
```
[("", = )]
{ }
[]
{
}
```text
Create `xunit.runner.json` the test project root:
```json
{
: ,
: ,
: ,
:
}
```text
Ensure it copied to output:
```xml
<ItemGroup>
<Content Include= CopyToOutputDirectory= />
</ItemGroup>
```json
**v2 compatibility note:** In v2, configuration was via `xunit.runner.json` assembly attributes. v3 retains `xunit.runner.json` support the same property names.
---
Capture diagnostic output that appears test results:
```csharp
{
ITestOutputHelper _output;
{
_output = output;
}
[]
{
sw = Stopwatch.StartNew();
result = processor.ProcessBatchAsync(largeDataset);
sw.Stop();
_output.WriteLine();
Assert.True(sw.Elapsed < TimeSpan.FromSeconds());
}
}
```text
Bridge xUnit output to `Microsoft.Extensions.Logging` integration tests:
```csharp
:
{
ITestOutputHelper _output;
=> _output = output;
=>
XunitLogger(_output, categoryName);
{ }
}
{
IDisposable? BeginScope<TState>(TState state) TState : => ;
=> ;
{
output.WriteLine();
(exception )
output.WriteLine(exception.ToString());
}
}
```text
---
Create domain-specific assertions cleaner test code:
```csharp
{
{
Assert.NotNull(order);
(order.Status != expected)
{
Xunit.Sdk.EqualException.ForMismatchedValues(
expected, order.Status);
}
}
{
Assert.NotNull(order);
item = Assert.Single(order.Items, i => i.Sku == sku);
Assert.Equal(quantity, item.Quantity);
}
}
[]
{
order = Order();
order.Complete();
OrderAssert.HasStatus(order, OrderStatus.Completed);
}
```text
Group related assertions so all are evaluated even one fails:
```csharp
[]
{
order = OrderFactory.Create(request);
Assert.Multiple(
() => Assert.Equal(, order.CustomerId),
() => Assert.Equal(OrderStatus.Pending, order.Status),
() => Assert.NotEqual(Guid.Empty, order.Id),
() => Assert.NotEmpty(order.Items)
);
}
```text
**v2 compatibility note:** `Assert.Multiple` xUnit v3. In v2, use separate assertions -- the test stops at the first failure.
---
The `xunit.analyzers` package (included xUnit v3) catches common test authoring mistakes at compile time.
| Rule | Description | Severity |
|------|-------------|----------|
| `xUnit1004` | Test methods should be skipped | Info |
| `xUnit1012` | Null should be used type parameters | Warning |
| `xUnit1025` | `InlineData` should be unique within a `Theory` | Warning |
| `xUnit2000` | Constants literals should be the expected argument | Warning |
| `xUnit2002` | Do use check type | Warning |
| `xUnit2007` | Do use `` expression to check type | Warning |
| `xUnit2013` | Do use equality check to check collection size | Warning |
| `xUnit2017` | Do use `Contains()` to check exists a | Warning |
In `.editorconfig` test projects:
```ini
[]
dotnet_diagnostic.xUnit1004.severity = suggestion
```csharp
---
- **One fact per `[Fact]`, one concept per `[Theory]`.** If a `[Theory]` tests fundamentally different scenarios, split separate `[Fact]` methods.
- **Use `IClassFixture` expensive shared resources** within a single test . Use `ICollectionFixture` multiple classes share the same resource.
- **Do disable parallelism globally.** Instead, tests that share mutable state named collections.
- **Use `IAsyncLifetime` setup/teardown** instead of constructors `IDisposable`. Constructors cannot be , `IDisposable.Dispose()` does .
- **Keep test data close to the test.** Prefer `[InlineData]` simple cases. Use `[MemberData]` `[ClassData]` only data complex shared.
- **Enable xUnit analyzers** all test projects. They common mistakes that lead to -passing flaky tests.
---
**Do use constructor-injected `ITestOutputHelper` methods.** `ITestOutputHelper` per-test-instance; store it an instance field, a one.
**Do forget to make fixture classes ``.**
Primary approach: Use Serena symbol operations for efficient code navigation:
serena_find_symbol instead of text searchserena_get_symbols_overview for file organizationserena_find_referencing_symbols for impact analysisserena_replace_symbol_body for clean modificationsWhen to use Serena vs traditional tools:
Example workflow:
# Instead of:
Read: src/Services/OrderService.cs
Grep: "public void ProcessOrder"
# Use:
serena_find_symbol: "OrderService/ProcessOrder"
serena_get_symbols_overview: "src/Services/OrderService.cs"