GitHub Copilot instructions for building .NET applications following Resolute project conventions. Enforces .NET 10.0 standards, consistent state models, and xUnit testing patterns.
Development conventions for building .NET applications with GitHub Copilot, based on the Resolute New Year's Resolution Tracker project by ardalis.
When creating or modifying .NET projects in this workspace:
1. **Target .NET 10.0** - All projects must target .NET 10.0 as specified in global.json (SDK version 10.0.0)
2. **Use Centralized Package Management**
- Define all NuGet package versions in `Directory.Packages.props`
- Never specify versions directly in individual `.csproj` files
- Always reference the centralized version from Directory.Packages.props
3. **Use Centralized Build Properties**
- Define common MSBuild properties in `Directory.Build.props`
- Apply settings consistently across all projects
- Include properties for nullable reference types, warnings as errors, etc.
4. **Enforce Code Style with .editorconfig**
- Every repository must have an `.editorconfig` at the root
- If missing, create one from: `https://github.com/ardalis/CleanArchitecture/blob/main/.editorconfig`
- Enforce consistent formatting, naming conventions, and code style rules
Never design models that can represent invalid or inconsistent states. Models should be self-validating through their structure.
**Bad Example:**
```csharp
public class Resolution
{
public bool IsCompleted { get; set; }
public DateTime? CompletedDate { get; set; }
}
```
This allows inconsistent states:
**Good Example:**
```csharp
public class Resolution
{
public DateTime? CompletedDate { get; set; }
public bool IsCompleted => CompletedDate.HasValue;
}
```
The `IsCompleted` property is now computed from `CompletedDate`, making inconsistent states impossible.
All test projects must follow these strict conventions:
**Arrange-Act-Assert Pattern**
Every test method must follow this three-phase structure, separated by blank lines, with NO comments:
```csharp
[Fact]
public void CreateOrder_ReturnsOrder_GivenValidRequest()
{
var service = new OrderService();
var request = new CreateOrderRequest { ProductId = 1, Quantity = 2 };
var result = service.CreateOrder(request);
Assert.NotNull(result);
Assert.Equal(1, result.ProductId);
}
```
**Test Folders Mirror Source Structure**
**Test Class Naming**
Name test classes for the class AND method being tested. Do NOT add a "Tests" suffix.
Format: `{ClassName}_{MethodName}.cs`
Examples:
**Test Method Naming**
Use descriptive names following this pattern:
`{Action}_{ExpectedResult}_Given{Condition}`
Examples:
```csharp
// File: Resolute.Core.Tests/Services/ResolutionService_MarkComplete.cs
using NSubstitute;
using Xunit;
namespace Resolute.Core.Tests.Services;
public class ResolutionService_MarkComplete
{
[Fact]
public void MarkComplete_SetsCompletedDate_GivenIncompleteResolution()
{
var repository = Substitute.For<IResolutionRepository>();
var service = new ResolutionService(repository);
var resolution = new Resolution { Id = 1, Title = "Test" };
service.MarkComplete(resolution);
Assert.NotNull(resolution.CompletedDate);
Assert.True(resolution.IsCompleted);
}
[Fact]
public void MarkComplete_ThrowsInvalidOperationException_GivenAlreadyCompletedResolution()
{
var repository = Substitute.For<IResolutionRepository>();
var service = new ResolutionService(repository);
var resolution = new Resolution
{
Id = 1,
Title = "Test",
CompletedDate = DateTime.UtcNow
};
var exception = Assert.Throws<InvalidOperationException>(
() => service.MarkComplete(resolution)
);
Assert.Equal("Resolution is already completed", exception.Message);
}
}
```
Follow these conventions to ensure:
When GitHub Copilot generates code in this workspace, it will automatically apply these conventions to new classes, tests, and project files.
Leave a review
No reviews yet. Be the first to review this skill!
# Download SKILL.md from killerskills.ai/api/skills/resolute-net-development-guide/raw