dotnet-testing-xunit-project-setup
npx skills add https://github.com/kevintsengtw/dotnet-testing-agent-skills --skill dotnet-testing-xunit-project-setup
Agent 安装分布
Skill 文档
xUnit æ¸¬è©¦å°æ¡è¨å®æå
é©ç¨æ å¢
ç¶è¢«è¦æ±å·è¡ä»¥ä¸ä»»åæï¼è«ä½¿ç¨æ¤æè½ï¼
- å»ºç«æ°ç xUnit æ¸¬è©¦å°æ¡
- è¨å® .NET æ¸¬è©¦å°æ¡çµæ§
- é ç½® xUnit ç¸ä¾å¥ä»¶è NuGet å¥ä»¶
- è¦åæ¸¬è©¦å°æ¡çè³æå¤¾çµç¹
- è¨å®ç¨å¼ç¢¼è¦èçæ¶éå·¥å ·
- çè§£æ¸¬è©¦å°æ¡ç csproj è¨å®
å°æ¡çµæ§æä½³å¯¦è¸
建è°çè§£æ±ºæ¹æ¡çµæ§
MyProject/
âââ src/ # 主ç¨å¼ç¢¼ç®é
â âââ MyProject.Core/
â âââ MyProject.Core.csproj
â âââ Calculator.cs
â âââ Services/
â âââ Models/
âââ tests/ # 測試ç¨å¼ç¢¼ç®é
â âââ MyProject.Core.Tests/
â âââ MyProject.Core.Tests.csproj
â âââ CalculatorTests.cs
â âââ Services/
â âââ Models/
âââ MyProject.sln
çµæ§ååï¼
- src è tests åé¢ï¼æ¸ æ¥ååçç¢ç¨å¼ç¢¼è測試ç¨å¼ç¢¼
- å½åæ
£ä¾ï¼æ¸¬è©¦å°æ¡å稱çº
{䏻尿¡å稱}.Tests - ç®éå°æï¼æ¸¬è©¦å°æ¡çè³æå¤¾çµæ§æå°æä¸»å°æ¡ççµæ§
- ä¸å°ä¸æ å°ï¼æ¯å䏻尿¡ææå°æçæ¸¬è©¦å°æ¡
å»ºç« xUnit æ¸¬è©¦å°æ¡
æ¹æ³ä¸ï¼ä½¿ç¨ .NET CLIï¼æ¨è¦ï¼
æ¥é© 1ï¼å»ºç«è§£æ±ºæ¹æ¡èå°æ¡
# 建ç«è§£æ±ºæ¹æ¡
dotnet new sln -n MyProject
# 建ç«ä¸»å°æ¡ï¼é¡å¥åº«ï¼
dotnet new classlib -n MyProject.Core -o src/MyProject.Core
# å»ºç«æ¸¬è©¦å°æ¡ï¼xUnit ç¯æ¬ï¼
dotnet new xunit -n MyProject.Core.Tests -o tests/MyProject.Core.Tests
# å°å°æ¡å å
¥è§£æ±ºæ¹æ¡
dotnet sln add src/MyProject.Core/MyProject.Core.csproj
dotnet sln add tests/MyProject.Core.Tests/MyProject.Core.Tests.csproj
# 建ç«å°æ¡åèï¼æ¸¬è©¦å°æ¡åè䏻尿¡ï¼
dotnet add tests/MyProject.Core.Tests/MyProject.Core.Tests.csproj reference src/MyProject.Core/MyProject.Core.csproj
æ¥é© 2ï¼å®è£ç¨å¼ç¢¼è¦èçå·¥å ·
# åæå°æ¸¬è©¦å°æ¡ç®é
cd tests/MyProject.Core.Tests
# å®è£ coverlet.collectorï¼ç¨æ¼æ¶éç¨å¼ç¢¼è¦èçï¼
dotnet add package coverlet.collector
æ¹æ³äºï¼ä½¿ç¨ Visual Studio
-
建ç«è§£æ±ºæ¹æ¡
- File â New â Project
- 鏿ãBlank Solutionã
- å½åçºå°æ¡å稱
-
å å ¥ä¸»å°æ¡
- å³éµè§£æ±ºæ¹æ¡ â Add â New Project
- 鏿ãClass Libraryã
- å½åçº
MyProject.Core
-
å å ¥æ¸¬è©¦å°æ¡
- å³éµè§£æ±ºæ¹æ¡ â Add â New Project
- æå°ä¸¦é¸æãxUnit Test Projectã
- å½åçº
MyProject.Core.Tests
-
è¨å®å°æ¡åè
- å³éµæ¸¬è©¦å°æ¡ â Add â Project Reference
- å¾é¸ä¸»å°æ¡
xUnit æ¸¬è©¦å°æ¡ç csproj è¨å®
æ¨æº xUnit æ¸¬è©¦å°æ¡ csproj
è«åèåç®éä¸ç templates/xunit-test-project.csproj ç¯æ¬æªæ¡ã
æ ¸å¿ç¸ä¾å¥ä»¶èªªæï¼
-
xunitï¼2.9.3+ï¼
- xUnit æ¸¬è©¦æ¡æ¶çæ ¸å¿å¥ä»¶
- æä¾
[Fact]ã[Theory]çæ¸¬è©¦å±¬æ§ - å
å«
Asserté¡å¥èæ·è¨æ¹æ³
-
xunit.runner.visualstudioï¼3.0.0+ï¼
- Visual Studio Test Explorer æ´å
- è®æ¸¬è©¦è½å¨ VS CodeãVisual StudioãRider ä¸è¢«æ¢ç´¢èå·è¡
- æ¯æ´æ¸¬è©¦çµæçå³æé¡¯ç¤º
-
Microsoft.NET.Test.Sdkï¼17.12.0+ï¼
- .NET 測試平å°ç SDK
- è®
dotnet testæä»¤è½å¤ å·è¡æ¸¬è©¦ - æ¯æ´æ¸¬è©¦çµæå ±åèæ¸¬è©¦æ¢ç´¢
-
coverlet.collectorï¼6.0.3+ï¼
- ç¨å¼ç¢¼è¦èçæ¶éå·¥å ·
- è
dotnet testæ´å - ç¢çè¦èçå ±åï¼æ¯æ´ CoberturaãOpenCover çæ ¼å¼ï¼
éè¦ csproj è¨å®é ç®
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
è¨å®èªªæï¼
IsPackable=falseï¼æ¸¬è©¦å°æ¡ä¸æè¢«æå æ NuGet å¥ä»¶IsTestProject=trueï¼æç¢ºæ¨è¨çºæ¸¬è©¦å°æ¡ï¼è®å·¥å ·èå¥Nullable=enableï¼åç¨å¯çº Null çåèå奿ª¢æ¥
測試é¡å¥åºæ¬çµæ§
æ¨æºæ¸¬è©¦é¡å¥ç¯æ¬
namespace MyProject.Core.Tests;
public class CalculatorTests
{
private readonly Calculator _calculator;
// 建æ§å½å¼ï¼æ¯å測試å·è¡åé½æè¢«å¼å«
public CalculatorTests()
{
_calculator = new Calculator();
}
}
測試çå½é±æï¼éè¦æ¦å¿µï¼
xUnit çæ¸¬è©¦é颿©å¶ï¼
- æ¯åæ¸¬è©¦æ¹æ³é½æåµå»ºæ°ç測試é¡å¥å¯¦ä¾
- 建æ§å½å¼ï¼å¨æ¯åæ¸¬è©¦æ¹æ³å·è¡å被å¼å«
- æ¸¬è©¦æ¹æ³ï¼å·è¡æ¸¬è©¦é輯
- Dispose()ï¼å¦æå¯¦ä½
IDisposableï¼å¨æ¯åæ¸¬è©¦æ¹æ³å·è¡å¾è¢«å¼å«
å·è¡é åºç¯ä¾ï¼
å·è¡ Test1ï¼
â 建æ§å½å¼ â Test1 æ¹æ³ â Dispose()
å·è¡ Test2ï¼
â 建æ§å½å¼ â Test2 æ¹æ³ â Dispose()
é確ä¿äº 測試éé¢ï¼ç¬¦å FIRST ååç I (Independent)ã
å·è¡æ¸¬è©¦
ä½¿ç¨ .NET CLI
# å»ºç½®å°æ¡
dotnet build
# å·è¡æææ¸¬è©¦
dotnet test
# å·è¡æ¸¬è©¦ä¸¦æ¶éç¨å¼ç¢¼è¦èç
dotnet test --collect:"XPlat Code Coverage"
# å·è¡ç¹å®æ¸¬è©¦å°æ¡
dotnet test tests/MyProject.Core.Tests/MyProject.Core.Tests.csproj
# å·è¡æ¸¬è©¦ä¸¦ç¢ç詳細輸åº
dotnet test --verbosity detailed
å¨ IDE ä¸å·è¡
VS Codeï¼éå®è£ C# Dev Kitï¼
- å®è£ C# Dev Kit
- éå Test Explorerï¼æ¸¬è©¦ç¸½ç®¡ï¼
- é»ææ¸¬è©¦æçææ¾æéå·è¡
Visual Studio
- éå Test Explorerï¼æ¸¬è©¦ â Test Explorerï¼
- 黿ãRun Allãå·è¡æææ¸¬è©¦
- å¯ä»¥å³éµå®ä¸æ¸¬è©¦å·è¡æåµé¯
JetBrains Rider
- æ¸¬è©¦æ¹æ³ææåºç¾ç¶ è²å·è¡å示
- 黿å·è¡æåµé¯æ¸¬è©¦
- ä½¿ç¨ Unit Tests è¦çªç®¡ç測試
å°æ¡åèè¨å®åå
åèæ¹åè¦å
æ¸¬è©¦å°æ¡ â 䏻尿¡ â
æ£ç¢º
䏻尿¡ â æ¸¬è©¦å°æ¡ â é¯èª¤
æ¸¬è©¦å°æ¡æè©²åè䏻尿¡ï¼ä½ä¸»å°æ¡çµå°ä¸æåèæ¸¬è©¦å°æ¡ã
è¨å®å°æ¡åè
# è®æ¸¬è©¦å°æ¡åè䏻尿¡
dotnet add tests/MyProject.Core.Tests/MyProject.Core.Tests.csproj reference src/MyProject.Core/MyProject.Core.csproj
å¨ csproj 䏿ç¢çï¼
<ItemGroup>
<ProjectReference Include="..\..\src\MyProject.Core\MyProject.Core.csproj" />
</ItemGroup>
é²éï¼å¤åæ¸¬è©¦å°æ¡ççµç¹
ç¶å°æ¡è®å¤§æï¼å¯è½éè¦å¤åæ¸¬è©¦å°æ¡ï¼
MyProject/
âââ src/
â âââ MyProject.Core/
â âââ MyProject.Web/
â âââ MyProject.Infrastructure/
âââ tests/
â âââ MyProject.Core.Tests/ # å®å
測試
â âââ MyProject.Web.Tests/ # Web 層測試
â âââ MyProject.Infrastructure.Tests/ # åºç¤è¨æ½æ¸¬è©¦
â âââ MyProject.Integration.Tests/ # æ´å測試
âââ MyProject.sln
å½åæ £ä¾å»ºè°ï¼
*.Tests– å®å 測試*.Integration.Tests– æ´å測試*.Acceptance.Tests– 驿¶æ¸¬è©¦*.Performance.Tests– æè½æ¸¬è©¦
實éå·¥ä½å°æ¡çå½åè¦ç¯
å¨å¯¦éçå·¥ä½å°æ¡ä¸ï¼å»ºè°ä½¿ç¨æ´æç¢ºçå½åæ ¼å¼ä¾å忏¬è©¦é¡åï¼
æ¨è¦çå½åæ ¼å¼ï¼
MyProject/
âââ src/
â âââ MyProject.Core/
â âââ MyProject.WebApi/
âââ tests/
â âââ MyProject.Core.Test.Unit/ # å®å
æ¸¬è©¦ï¼æç¢ºæ¨ç¤ºï¼
â âââ MyProject.WebApi.Test.Unit/ # WebApi å®å
測試
â âââ MyProject.WebApi.Test.Integration/ # WebApi æ´å測試
âââ MyProject.sln
å½åè¦åï¼
-
å®å 測試ï¼
{å°æ¡å稱}.Test.Unit- ç¯ä¾ï¼
MyProject.Core.Test.Unit - ç¹æ§ï¼ä¸ä¾è³´å¤é¨è³æºï¼è³æåº«ãAPIãæªæ¡ç³»çµ±çï¼
- å·è¡é度ï¼å¿«éï¼æ¯«ç§ç´ï¼
- ç¯ä¾ï¼
-
æ´å測試ï¼
{å°æ¡å稱}.Test.Integration- ç¯ä¾ï¼
MyProject.WebApi.Test.Integration - ç¹æ§ï¼æ¸¬è©¦å¤åå ä»¶çæ´åï¼å¯è½ä¾è³´å¤é¨è³æº
- å·è¡é度ï¼è¼æ ¢ï¼ç§ç´ï¼
- ç¯ä¾ï¼
é種å½åçåªå¢ï¼
-
æ¸ æ°åº¦ï¼ä¸ç¼å°±è½å辨測試é¡å
-
å·è¡çç¥ï¼å¯ä»¥å¨ CI/CD ä¸åéæ®µå·è¡
# å¿«éåé¥ï¼åªå·è¡å®å 測試 dotnet test --filter "FullyQualifiedName~.Test.Unit" # 宿´é©èï¼å·è¡æ´å測試 dotnet test --filter "FullyQualifiedName~.Test.Integration" -
ç¸ä¾æ§ç®¡çï¼æ´å測試å¯ä»¥æä¸åçå¥ä»¶ç¸ä¾ï¼å¦ Testcontainersï¼
-
åéåä½ï¼æ°æå¡è½å¿«éçè§£å°æ¡çµæ§
CLI 建ç«ç¯ä¾ï¼
# 建ç«å®å
æ¸¬è©¦å°æ¡
dotnet new xunit -n MyProject.Core.Test.Unit -o tests/MyProject.Core.Test.Unit
dotnet add tests/MyProject.Core.Test.Unit reference src/MyProject.Core
# å»ºç«æ´åæ¸¬è©¦å°æ¡
dotnet new xunit -n MyProject.WebApi.Test.Integration -o tests/MyProject.WebApi.Test.Integration
dotnet add tests/MyProject.WebApi.Test.Integration reference src/MyProject.WebApi
ð¡ æç¤ºï¼éç¶æ¬ç¯ä¾ä¸çºäºç°¡å說æä½¿ç¨
.Testsæ ¼å¼ï¼ä½å¨å¯¦éå°æ¡ä¸å¼·ç建è°ä½¿ç¨.Test.Unitå.Test.Integrationéç¨®æ´æç¢ºçæ ¼å¼ã
常è¦åé¡èè§£æ±ºæ¹æ¡
Q1: 測試æ¢ç´¢å¤±æï¼Test Explorer çä¸å°æ¸¬è©¦ï¼
æª¢æ¥æ¸ å®ï¼
- 確èªå·²å®è£
xunit.runner.visualstudioå¥ä»¶ - 確èªå·²å®è£
Microsoft.NET.Test.Sdkå¥ä»¶ - å·è¡
dotnet buildéæ°å»ºç½® - éå IDE æéæ°è¼å ¥ Test Explorer
Q2: 測試å¯ä»¥å¨ CLI å·è¡ä½å¨ IDE ä¸ç¡æ³å·è¡ï¼
è§£æ±ºæ¹æ¡ï¼
- ç¢ºèª IDE å·²å®è£ç¸éæ´å å¥ä»¶ï¼VS Code éè¦ C# Dev Kitï¼
- æ¸
é¤å¿«åï¼åªé¤
bin/åobj/è³æå¤¾å¾éæ°å»ºç½® - 檢æ¥
.csprojä¸çIsTestProjectå±¬æ§æ¯å¦çºtrue
Q3: å¦ä½å¨æ¸¬è©¦å°æ¡ä¸ä½¿ç¨ Internal é¡å¥ï¼
å¨ä¸»å°æ¡ç .csproj æ AssemblyInfo.cs ä¸å å
¥ï¼
[assembly: InternalsVisibleTo("MyProject.Core.Tests")]
æå¨ csproj ä¸ï¼
<ItemGroup>
<InternalsVisibleTo Include="MyProject.Core.Tests" />
</ItemGroup>
ç¯æ¬æªæ¡
è«åèåç®éä¸çç¯æ¬æªæ¡ä»¥å¿«é建ç«å°æ¡ï¼
templates/project-structure.md– 宿´çå°æ¡çµæ§ç¯ä¾templates/xunit-test-project.csproj– xUnit æ¸¬è©¦å°æ¡ç csproj ç¯æ¬
æª¢æ¥æ¸ å®
å»ºç« xUnit æ¸¬è©¦å°æ¡æï¼è«ç¢ºèªä»¥ä¸é ç®ï¼
- æ¸¬è©¦å°æ¡å½åçº
{䏻尿¡å稱}.Tests - æ¸¬è©¦å°æ¡ä½æ¼
tests/ç®éä¸ - å·²å®è£
xunitãxunit.runner.visualstudioãMicrosoft.NET.Test.Sdkå¥ä»¶ - å·²å®è£
coverlet.collectorç¨æ¼ç¨å¼ç¢¼è¦èç - æ¸¬è©¦å°æ¡å·²åè䏻尿¡
-
IsPackableè¨çºfalse -
IsTestProjectè¨çºtrue - å¯ä»¥å·è¡
dotnet testæå - IDE ç Test Explorer å¯ä»¥æ¢ç´¢å°æ¸¬è©¦
åèè³æº
åå§æç«
æ¬æè½å §å®¹æç èªãèæ´¾è»é«å·¥ç¨å¸«ç測試修練 – 30 å¤©ææ°ãç³»åæç« ï¼
-
Day 02 – xUnit æ¡æ¶æ·±åº¦è§£æ
- éµäººè³½æç« ï¼https://ithelp.ithome.com.tw/articles/10373952
- ç¯ä¾ç¨å¼ç¢¼ï¼https://github.com/kevintsengtw/30Days_in_Testing_Samples/tree/main/day02
-
Day 03 – xUnit é²éåè½èæ¸¬è©¦è³æç®¡ç
- éµäººè³½æç« ï¼https://ithelp.ithome.com.tw/articles/10374064
- ç¯ä¾ç¨å¼ç¢¼ï¼https://github.com/kevintsengtw/30Days_in_Testing_Samples/tree/main/day03
宿¹æä»¶
ç¸éæè½
unit-test-fundamentals– å®å 測試åºç¤è FIRST ååtest-naming-conventions– 測試å½åè¦ç¯code-coverage-analysis– ç¨å¼ç¢¼è¦èçåæ