dotnet-testing
npx skills add https://github.com/kevintsengtw/dotnet-testing-agent-skills --skill dotnet-testing
Agent 安装分布
Skill 文档
.NET 測試åºç¤æè½ç¸½è¦½
ð¤ AI Agent éè¦æç¤º
ç¶æ¨ï¼AI Agentï¼è¢«è¼å ¥æ¤å ¥å£ skill æï¼è«å é±è®ä»¥ä¸æå¼ï¼
ð æ¬æè½çå®ä½
æ¬æªæ¡æ¯ãå°èªä¸å¿ãï¼ç¨æ¼å¹«å©æ¾å°æ£ç¢ºçåæè½ã
æ¨ç任忝
- â æ ¹æä½¿ç¨è éæ±å¹é å°æçåæè½
- â
使ç¨
Skilltool è¼å ¥å ·é«çåæè½ - â è®åæè½æä¾å°æ¥ç測試æå¼
ç¦æ¢è¡çº
- â ä¸è¦å¨æ¬å ¥å£ skill ä¸ç´æ¥æä¾æ¸¬è©¦ç¨å¼ç¢¼
- â ä¸è¦å¨æ²æè¼å ¥åæè½çæ æ³ä¸éå§å¯¦ä½æ¸¬è©¦
- â ä¸è¦è·³éåæè½ç´æ¥æä¾ãä¸è¬æ§ã測試建è°
ð¯ å¿«éæè½å°ç §è¡¨ï¼AI Agent å¿ è®ï¼
使ç¨è æå°çééµå â æè¼å ¥çåæè½
æå¸¸ç¨æè½ï¼å¿ é çè¨ï¼
| 使ç¨è 說… | è¼å ¥æä»¤ | ç¨é說æ |
|---|---|---|
| Validatorãé©èå¨ãCreateUserValidator | /skill dotnet-testing-fluentvalidation-testing |
FluentValidation 測試 |
| Mockãæ¨¡æ¬ãIRepositoryãIService | /skill dotnet-testing-nsubstitute-mocking |
模æ¬å¤é¨ä¾è³´ |
| AutoFixtureãæ¸¬è©¦è³æçæ | /skill dotnet-testing-autofixture-basics |
èªåç¢çæ¸¬è©¦è³æ |
| æ·è¨ãShould()ãBeEquivalentTo | /skill dotnet-testing-awesome-assertions-guide |
æµæ¢æ·è¨ï¼å¿ å¸ï¼ |
| DateTimeãæé測試ãTimeProvider | /skill dotnet-testing-datetime-testing-timeprovider |
æéç¸é測試 |
| Fileãæªæ¡ç³»çµ±ãIFileSystem | /skill dotnet-testing-filesystem-testing-abstractions |
æªæ¡ç³»çµ±æ¸¬è©¦ |
| Bogusãåè³æãFaker | /skill dotnet-testing-bogus-fake-data |
æ¬çè³æçæ |
| Builder PatternãWithXxx | /skill dotnet-testing-test-data-builder-pattern |
Test Data Builder |
| 深層æ¯å°ãDTO æ¯å°ãExcluding | /skill dotnet-testing-complex-object-comparison |
è¤éç©ä»¶æ¯å° |
åºç¤å ¥éæè½
| 使ç¨è 說… | è¼å ¥æä»¤ | ç¨é說æ |
|---|---|---|
| å¾é¶éå§ã測試åºç¤ãFIRST åå | /skill dotnet-testing-unit-test-fundamentals |
å®å 測試åºç¤ |
| 測試å½åãå¦ä½å½å測試 | /skill dotnet-testing-test-naming-conventions |
å½åè¦ç¯ |
| å»ºç«æ¸¬è©¦å°æ¡ãxUnit è¨å® | /skill dotnet-testing-xunit-project-setup |
å°æ¡å»ºç½® |
é²éæè½çµå
| 使ç¨è 說… | è¼å ¥æä»¤ | ç¨é說æ |
|---|---|---|
| AutoFixture + Bogus | /skill dotnet-testing-autofixture-bogus-integration |
èªåå+æ¬çè³æ |
| AutoFixture + NSubstitute | /skill dotnet-testing-autofixture-nsubstitute-integration |
èªåå»ºç« Mock |
| AutoDataãTheory 測試 | /skill dotnet-testing-autodata-xunit-integration |
忏忏¬è©¦ |
| 測試輸åºãITestOutputHelper | /skill dotnet-testing-test-output-logging |
測試æ¥èª |
| è¦èçãCoverlet | /skill dotnet-testing-code-coverage-analysis |
ç¨å¼ç¢¼è¦èç |
â ï¸ ä½¿ç¨æµç¨ç¯ä¾
â æ£ç¢ºæµç¨
使ç¨è
ï¼è«å¹«æå»ºç« CreateUserValidator çæ¸¬è©¦
AIï¼ææ³¨æå°æ¨éè¦æ¸¬è©¦ Validatorãæ ¹æå¿«éå°ç
§è¡¨ï¼
ææè©²è¼å
¥ dotnet-testing-fluentvalidation-testing skillã
[ä½¿ç¨ Skill tool è¼å
¥åæè½]
AIï¼ç¾å¨æç
§ FluentValidation Testing skill çæå¼çºæ¨å»ºç«æ¸¬è©¦...
â é¯èª¤æµç¨
使ç¨è
ï¼è«å¹«æå»ºç« CreateUserValidator çæ¸¬è©¦
AIï¼å¥½çï¼æä¾å¯«æ¸¬è©¦...ï¼ç´æ¥éå§å¯«ç¨å¼ç¢¼ï¼æ²æè¼å
¥åæè½ï¼
ð 宿´æè½æ¸ å®
å¦éæ¥ç宿´ç 19 ååºç¤æè½æ¸ å®ãè©³ç´°æ±ºçæ¨¹ãå¸ç¿è·¯å¾å»ºè°ï¼è«ç¹¼çºé±è®æ¬æªæ¡å¾çºå §å®¹ã
人é¡éç¼è åèï¼å¦éå¿«éæ¥æ¾ï¼è«æ¥ç SKILLS_QUICK_INDEX.md
é©ç¨æ å¢
ç¶æ¨éå°ä»¥ä¸æ æ³æï¼ææå婿¨æ¾å°æ£ç¢ºçæè½ï¼
- åéå§å¸ç¿ .NET 測試ï¼ä¸ç¥å¾ä½ä¸æ
- æ³çºç¾æå°æ¡å»ºç«æ¸¬è©¦ï¼éè¦å®æ´æå¼
- éè¦æ¹å測試å質ï¼å°æ¾æä½³å¯¦è¸
- éå°ç¹å®æ¸¬è©¦å ´æ¯ï¼ä¸ç¢ºå®è©²ç¨åªåå·¥å ·
- æ³äºè§£æ¸¬è©¦è³æçæãæ·è¨ã模æ¬çæè¡
- 叿æå測試å¯è®æ§èç¶è·æ§
- éè¦èçæéãæªæ¡ç³»çµ±çç¹æ®æ¸¬è©¦å ´æ¯
å¿«éæ±ºç樹
ææè©²å¾åªè£¡éå§ï¼
æ å¢ 1ï¼å®å ¨æ°æï¼å¾æªå¯«é測試
æ¨è¦å¸ç¿è·¯å¾ï¼
dotnet-testing-unit-test-fundamentals– çè§£ FIRST ååè 3A Patterndotnet-testing-test-naming-conventions– å¸ç¿å½åè¦ç¯dotnet-testing-xunit-project-setup– 建ç«ç¬¬ä¸åæ¸¬è©¦å°æ¡
çºä»éº¼é樣å¸ï¼
- FIRST ååæ¯æææ¸¬è©¦çåºç¤ï¼å å»ºç«æ£ç¢ºçè§å¿µ
- å½åè¦ç¯è®æ¸¬è©¦æè®æç¶è·
- 實éåæå»ºç«å°æ¡ï¼å°çè«è½åçºå¯¦è¸
æ å¢ 2ï¼æå¯«åºç¤æ¸¬è©¦ï¼ä½æ¸¬è©¦è³ææºåå¾éº»ç ©
æ¨è¦æè½ï¼æä¸æçµåï¼ï¼
é¸é
A – èªåååªå
â dotnet-testing-autofixture-basics
é©åï¼éè¦å¤§éæ¸¬è©¦è³æãæ¸å°æ¨£æ¿ç¨å¼ç¢¼
é¸é
B – æ¬çè³æåªå
â dotnet-testing-bogus-fake-data
é©åï¼éè¦ç實æçæ¸¬è©¦è³æï¼å§åãå°åãEmail çï¼
é¸é
C – èªææ¸
æ°åªå
â dotnet-testing-test-data-builder-pattern
é©åï¼éè¦é«å¯è®æ§ãæç¢ºè¡¨é測試æå
é¸é
D – å
©è
å
¼å
·
â dotnet-testing-autofixture-basics + dotnet-testing-autofixture-bogus-integration
é©åï¼åæéè¦èªåå忬çè³æ
æ å¢ 3ï¼æå¤é¨ä¾è³´ï¼è³æåº«ãAPIãç¬¬ä¸æ¹æåï¼éè¦æ¨¡æ¬
æ¨è¦æè½çµåï¼
dotnet-testing-nsubstitute-mocking– NSubstitute Mock æ¡æ¶åºç¤dotnet-testing-autofixture-nsubstitute-integration– ï¼å¯é¸ï¼æ´å AutoFixture è NSubstitute
使éè¦ç¬¬äºåæè½ï¼
- 妿æ¨å·²ç¶å¨ä½¿ç¨ AutoFixture ç¢çæ¸¬è©¦è³æ
- æ³è¦èªåå»ºç« Mock ç©ä»¶ï¼æ¸å°æåè¨å®
æ å¢ 4ï¼æ¸¬è©¦ä¸æç¹æ®å ´æ¯
æéç¸é測試
â dotnet-testing-datetime-testing-timeprovider
èçï¼DateTime.Nowãæåè½æãæéè¨ç®
æªæ¡ç³»çµ±æ¸¬è©¦
â dotnet-testing-filesystem-testing-abstractions
èçï¼æªæ¡è®å¯«ãç®éæä½ãè·¯å¾èç
ç§æ/å
§é¨æå¡æ¸¬è©¦
â dotnet-testing-private-internal-testing
èçï¼éè¦æ¸¬è©¦ privateãinternal æå¡ï¼ä½æè¬¹æ
使ç¨ï¼
æ å¢ 5ï¼éè¦æ´å¥½çæ·è¨æ¹å¼
åºç¤éæ± – æµæ¢æ·è¨
â dotnet-testing-awesome-assertions-guide
ææå°æ¡é½æè©²ä½¿ç¨ï¼æå測試å¯è®æ§
é²ééæ± – è¤éç©ä»¶æ¯è¼
â dotnet-testing-complex-object-comparison
èçï¼æ·±å±¤ç©ä»¶æ¯è¼ãDTO é©èãEntity æ¯å°
é©èè¦å測試
â dotnet-testing-fluentvalidation-testing
èçï¼æ¸¬è©¦ FluentValidation é©èå¨
æ å¢ 6ï¼æ³äºè§£æ¸¬è©¦è¦èç
â dotnet-testing-code-coverage-analysis
å¸ç¿ï¼ä½¿ç¨ Coverlet åæç¨å¼ç¢¼è¦èçãç¢çå ±å
æè½åé¡å°å
1. 測試åºç¤ï¼3 åæè½ï¼- å¿ å¸åºç¤
| æè½å稱 | æ ¸å¿å¹å¼ | é©åæ°æ | ä½æä½¿ç¨ |
|---|---|---|---|
dotnet-testing-unit-test-fundamentals |
çè§£ FIRST ååã3A Patternãæ¸¬è©¦éåå¡çåºç¤æ¦å¿µ | âââ | æææ¸¬è©¦çèµ·é»ï¼å»ºç«æ£ç¢ºç測試è§å¿µ |
dotnet-testing-test-naming-conventions |
å¸ç¿ä¸æ®µå¼å½åæ³ã䏿å½åå»ºè° | âââ | æå測試å¯è®æ§èå¯ç¶è·æ§ |
dotnet-testing-xunit-project-setup |
å»ºç«æ¨æºç xUnit æ¸¬è©¦å°æ¡çµæ§ | âââ | å»ºç«æ°æ¸¬è©¦å°æ¡æ |
å¸ç¿é åºå»ºè°ï¼fundamentals â naming-conventions â xunit-project-setup
æ ¸å¿æ¶ç©«ï¼
- FIRST ååï¼FastãIndependentãRepeatableãSelf-ValidatingãTimely
- 3A Patternï¼Arrange-Act-Assert çµæ§å測試
- å½åè¦ç¯ï¼
[è¢«æ¸¬æ¹æ³]_[測試æ å¢]_[é æè¡çº] - å°æ¡çµæ§ï¼tests/ ç®éã.csproj è¨å®ãNuGet å¥ä»¶ç®¡ç
2. æ¸¬è©¦è³æçæï¼5 åæè½ï¼- æåæç
| æè½å稱 | ç¹é» | åªå¢ | ä½æä½¿ç¨ |
|---|---|---|---|
dotnet-testing-autofixture-basics |
èªåç¢çå¿åæ¸¬è©¦è³æ | æ¸å°æ¨£æ¿ç¨å¼ç¢¼ãå¿«éå»ºç«æ¸¬è©¦ç©ä»¶ | éè¦å¤§éæ¸¬è©¦è³æãæ¸¬è©¦è³æå §å®¹ä¸éè¦æ |
dotnet-testing-autofixture-customization |
客製å AutoFixture è¡çº | æ§å¶è³æçæè¦åãç¬¦åæ¥åé輯 | éè¦ç¹å®è¦åçæ¸¬è©¦è³æ |
dotnet-testing-bogus-fake-data |
ç¢çæ¬çåè³æï¼å§åãå°åãEmail çï¼ | è³æçèµ·ä¾çå¯¦ãææ¼é¤é¯ | éè¦ç實æçæ¸¬è©¦è³æãå±ç¤ºç¨é |
dotnet-testing-test-data-builder-pattern |
ä½¿ç¨ Builder Pattern å»ºç«æ¸¬è©¦è³æ | èªææ¸ æ°ãè¡¨éæ¸¬è©¦æå | éè¦é«å¯è®æ§ãè¤éç©ä»¶å»ºæ§ |
dotnet-testing-autofixture-bogus-integration |
çµå AutoFixture è Bogus | å ©è åªå¢äºè£ | åæéè¦èªåå忬çè³æ |
鏿æåï¼
éè¦å¤§éè³æ + ä¸å¨ä¹ç實æï¼
â autofixture-basics
éè¦çèµ·ä¾ç實çè³æï¼
â bogus-fake-data
éè¦é«åº¦å¯è®æ§åèªææ¸
æ°ï¼
â test-data-builder-pattern
éè¦éæ´»æ§å¶çæè¦åï¼
â autofixture-basics + autofixture-customization
éè¦èªåå + æ¬çï¼
â autofixture-basics + autofixture-bogus-integration
å¸ç¿è·¯å¾ï¼
- å ¥éï¼autofixture-basics æ bogus-fake-data
- é²éï¼autofixture-customization + test-data-builder-pattern
- æ´åï¼autofixture-bogus-integration
3. 測試æ¿èº«ï¼2 åæè½ï¼- èçä¾è³´
| æè½å稱 | ç¨é | æ¶µèç¯å | ä½æä½¿ç¨ |
|---|---|---|---|
dotnet-testing-nsubstitute-mocking |
NSubstitute Mock æ¡æ¶ | MockãStubãSpyãé©èå¼å« | æå¤é¨ä¾è³´éè¦æ¨¡æ¬ |
dotnet-testing-autofixture-nsubstitute-integration |
AutoFixture + NSubstitute æ´å | èªåå»ºç« Mock ç©ä»¶ | ä½¿ç¨ AutoFixture 䏿大éä¾è³´ |
æ ¸å¿æ¦å¿µï¼
- Mockï¼æ¨¡æ¬ç©ä»¶ä¸¦é©èäºå
- Stubï¼æä¾é è¨åæ
- Spyï¼è¨éå¼å«ä¸¦é©è
å¸ç¿é åºå»ºè°ï¼
- å å¸ nsubstitute-mockingï¼çè§£ Mock åºç¤ï¼
- å¦æå·²ä½¿ç¨ AutoFixtureï¼åå¸ integrationï¼æåæçï¼
常è¦ç¨éï¼
- 模æ¬è³æåº«åå層ï¼Repositoryï¼
- 模æ¬å¤é¨ API å¼å«
- 模æ¬ç¬¬ä¸æ¹æå
- é©èæ¹æ³æ¯å¦è¢«æ£ç¢ºå¼å«
4. æ·è¨é©èï¼3 åæè½ï¼- å¯«åºæ¸ æ°æ¸¬è©¦
| æè½å稱 | ç¹è² | æåå¹ åº¦ | ä½æä½¿ç¨ |
|---|---|---|---|
dotnet-testing-awesome-assertions-guide |
FluentAssertions æµæ¢æ·è¨ | âââ é« | æææ¸¬è©¦ï¼å¼·çæ¨è¦ï¼ |
dotnet-testing-complex-object-comparison |
深層ç©ä»¶æ¯å°æå·§ | âââ é« | DTOãEntityãè¤éç©ä»¶é©è |
dotnet-testing-fluentvalidation-testing |
測試 FluentValidation é©èå¨ | ââ ä¸ | ä½¿ç¨ FluentValidation çå°æ¡ |
FluentAssertions ç¯ä¾å°æ¯ï¼
// å³çµ±æ·è¨
Assert.Equal(expected.Name, actual.Name);
Assert.Equal(expected.Age, actual.Age);
Assert.True(actual.IsActive);
// FluentAssertionsï¼æ´æè®ï¼
actual.Should().BeEquivalentTo(expected, options => options
.Including(x => x.Name)
.Including(x => x.Age));
actual.IsActive.Should().BeTrue();
å¸ç¿è·¯å¾ï¼
- awesome-assertions-guideï¼ææå°æ¡å¿ å¸ï¼
- complex-object-comparisonï¼èçè¤éæ¯å°ï¼
- fluentvalidation-testingï¼ç¹å®éæ±ï¼
5. ç¹æ®å ´æ¯ï¼3 åæè½ï¼- è§£æ±ºæ£æåé¡
| æè½å稱 | 解決åé¡ | 實åå¹å¼ | å¸ç¿é£åº¦ |
|---|---|---|---|
dotnet-testing-datetime-testing-timeprovider |
æéç¸é測試ï¼ä½¿ç¨ .NET 8+ TimeProviderï¼ | âââ é« | ä¸ç |
dotnet-testing-filesystem-testing-abstractions |
æªæ¡ç³»çµ±æ½è±¡å測試 | âââ é« | ä¸ç |
dotnet-testing-private-internal-testing |
æ¸¬è©¦ç§æ/å §é¨æå¡ | ââ ä¸ | ç°¡å® |
æé測試常è¦åé¡ï¼
// åé¡ï¼é£ä»¥æ¸¬è©¦
public bool IsExpired()
{
return DateTime.Now > ExpiryDate; // DateTime.Now ç¡æ³æ§å¶
}
// 解決ï¼ä½¿ç¨ TimeProvider
public bool IsExpired(TimeProvider timeProvider)
{
return timeProvider.GetUtcNow() > ExpiryDate; // å¯å¨æ¸¬è©¦ä¸æ³¨å
¥åæé
}
æªæ¡ç³»çµ±æ¸¬è©¦å¸¸è¦åé¡ï¼
// åé¡ï¼é£ä»¥æ¸¬è©¦
public void SaveToFile(string content)
{
File.WriteAllText("data.txt", content); // çå¯¦æªæ¡æä½
}
// 解決ï¼ä½¿ç¨ IFileSystem æ½è±¡
public void SaveToFile(string content, IFileSystem fileSystem)
{
fileSystem.File.WriteAllText("data.txt", content); // å¯å¨æ¸¬è©¦ä¸ä½¿ç¨è¨æ¶é«æªæ¡ç³»çµ±
}
使éè¦éäºæè½ï¼
- TimeProviderï¼æç¨ç³»çµ±ãææææª¢æ¥ãæéè¨ç®
- FileSystemï¼æªæ¡ä¸å³ãå ±è¡¨ç¢çãè¨å®æªè®å¯«
- Private Testingï¼éæ§éºçç¨å¼ç¢¼ï¼ä½æåªå èæ ®éæ§è¨è¨ï¼
6. 測試度éï¼1 åæè½ï¼- åè³ªç£æ§
| æè½å稱 | ç¨é | å·¥å · | ä½æä½¿ç¨ |
|---|---|---|---|
dotnet-testing-code-coverage-analysis |
ç¨å¼ç¢¼è¦èçåæèå ±å | CoverletãReportGenerator | è©ä¼°æ¸¬è©¦å®æ´æ§ãCI/CD æ´å |
æ¶µèå §å®¹ï¼
- ä½¿ç¨ Coverlet æ¶éè¦èçè³æ
- ç¢ç HTML å ±å
- è¨å®è¦èçéæª»
- CI/CD æ´å
éè¦æéï¼
- é«è¦èç â é«å質測試
- ç®æ¨æ¯ææç¾©ç測試ï¼èéè¿½æ± 100% è¦èç
- è¦èçæ¯åèææ¨ï¼ä¸æ¯çµå°æ¨æº
7. æ¡æ¶æ´åï¼2 åæè½ï¼- é²éæ´å
| æè½å稱 | æ´åå°è±¡ | å¹å¼ | ä½æä½¿ç¨ |
|---|---|---|---|
dotnet-testing-autodata-xunit-integration |
AutoFixture + xUnit Theory | ç°¡å忏忏¬è©¦ | ä½¿ç¨ xUnit Theory ä¸éè¦æ¸¬è©¦è³æ |
dotnet-testing-test-output-logging |
ITestOutputHelper + ILogger | 測試輸åºèé¤é¯ | éè¦æ¥ç測試å·è¡éç¨ãé¤é¯è¤é測試 |
AutoData ç¯ä¾ï¼
// å³çµ±å¯«æ³
[Theory]
[InlineData("user1", "pass1")]
[InlineData("user2", "pass2")]
public void Login_ValidCredentials_Success(string username, string password)
{
// ...
}
// ä½¿ç¨ AutoData
[Theory, AutoData]
public void Login_ValidCredentials_Success(string username, string password)
{
// username å password èªåç¢ç
}
Test Output ç¯ä¾ï¼
public class MyTests
{
private readonly ITestOutputHelper _output;
public MyTests(ITestOutputHelper output)
{
_output = output;
}
[Fact]
public void Test()
{
_output.WriteLine("Debug information"); // 卿¸¬è©¦è¼¸åºä¸é¡¯ç¤º
}
}
常è¦ä»»åæ å°è¡¨
ä»»å 1ï¼å¾é¶å»ºç«æ¸¬è©¦å°æ¡
æ å¢ï¼å ¨æ°å°æ¡ï¼éè¦å»ºç«å®æ´ç測試åºç¤è¨æ½
æ¨è¦æè½çµåï¼
dotnet-testing-xunit-project-setup– 建ç«å°æ¡çµæ§dotnet-testing-test-naming-conventions– è¨å®å½åè¦ç¯dotnet-testing-unit-test-fundamentals– æ°å¯«ç¬¬ä¸å測試
å¯¦æ½æ¥é©ï¼
- ä½¿ç¨ xunit-project-setup å»ºç«æ¸¬è©¦å°æ¡
- é ç½® .csproj æªæ¡è NuGet å¥ä»¶
- å¸ç¿å½åè¦ç¯ï¼å¶å®å鿍æº
- æç § 3A Pattern æ°å¯«ç¬¬ä¸å測試
æç¤ºè©ç¯ä¾ï¼
è«ä½¿ç¨ dotnet-testing-xunit-project-setup skill çºæçå°æ¡å»ºç«æ¸¬è©¦çµæ§ï¼
å°æ¡åç¨±æ¯ MyProjectï¼ç¶å¾ä½¿ç¨ dotnet-testing-unit-test-fundamentals skill
çº Calculator é¡å¥å»ºç«ç¬¬ä¸å測試ã
ä»»å 2ï¼çºæä¾è³´çæåé¡å¥å¯«æ¸¬è©¦
æ å¢ï¼UserService ä¾è³´ IUserRepository å IEmailService
æ¨è¦æè½çµåï¼
dotnet-testing-unit-test-fundamentals– æ¸¬è©¦çµæ§dotnet-testing-nsubstitute-mocking– 模æ¬ä¾è³´dotnet-testing-autofixture-basics– ç¢çæ¸¬è©¦è³ædotnet-testing-awesome-assertions-guide– æ¸ æ°æ·è¨
å¯¦æ½æ¥é©ï¼
- ä½¿ç¨ NSubstitute å»ºç« Repository å EmailService ç Mock
- ç¨ AutoFixture ç¢ç User æ¸¬è©¦è³æ
- æç § 3A Pattern æ°å¯«æ¸¬è©¦
- ä½¿ç¨ FluentAssertions é©èçµæ
æç¤ºè©ç¯ä¾ï¼
è«ä½¿ç¨ dotnet-testing-nsubstitute-mocking å dotnet-testing-autofixture-basics skills
çº UserService å»ºç«æ¸¬è©¦ãUserService ç建æ§å½å¼éè¦ IUserRepository å IEmailServiceã
è«æ¸¬è©¦ CreateUser æ¹æ³ã
é æç¨å¼ç¢¼çµæ§ï¼
[Fact]
public void CreateUser_ValidUser_ShouldSaveAndSendEmail()
{
// Arrange - ä½¿ç¨ NSubstitute å»ºç« Mock
var repository = Substitute.For<IUserRepository>();
var emailService = Substitute.For<IEmailService>();
// ä½¿ç¨ AutoFixture ç¢çæ¸¬è©¦è³æ
var fixture = new Fixture();
var user = fixture.Create<User>();
var sut = new UserService(repository, emailService);
// Act
sut.CreateUser(user);
// Assert - ä½¿ç¨ FluentAssertions
repository.Received(1).Save(Arg.Is<User>(u => u.Email == user.Email));
emailService.Received(1).SendWelcomeEmail(user.Email);
}
ä»»å 3ï¼æ¸¬è©¦ææéé輯çç¨å¼ç¢¼
æ å¢ï¼OrderService 夿·è¨å®æ¯å¦éæ
æ¨è¦æè½çµåï¼
dotnet-testing-datetime-testing-timeprovider– TimeProvider æ½è±¡ådotnet-testing-unit-test-fundamentals– 測試åºç¤dotnet-testing-nsubstitute-mocking– Mock TimeProvider
å¯¦æ½æ¥é©ï¼
- éæ§ç¨å¼ç¢¼ï¼æ³¨å ¥ TimeProvider
- 卿¸¬è©¦ä¸ä½¿ç¨ FakeTimeProvider
- æ§å¶æéé²è¡æ¸¬è©¦
æç¤ºè©ç¯ä¾ï¼
è«ä½¿ç¨ dotnet-testing-datetime-testing-timeprovider skill åå©éæ§ OrderServiceï¼
使å
¶å¯æ¸¬è©¦æéç¸éé輯ãè¨å®å¨å»ºç« 30 天å¾è¦çºéæã
é æç¨å¼ç¢¼çµæ§ï¼
// éæ§å
public class OrderService
{
public bool IsExpired(Order order)
{
return DateTime.Now > order.CreatedDate.AddDays(30); // ç¡æ³æ¸¬è©¦
}
}
// éæ§å¾
public class OrderService
{
private readonly TimeProvider _timeProvider;
public OrderService(TimeProvider timeProvider)
{
_timeProvider = timeProvider;
}
public bool IsExpired(Order order)
{
return _timeProvider.GetUtcNow() > order.CreatedDate.AddDays(30);
}
}
// 測試
[Fact]
public void IsExpired_Order31DaysOld_ShouldReturnTrue()
{
// Arrange
var fakeTime = new FakeTimeProvider();
fakeTime.SetUtcNow(new DateTimeOffset(2024, 1, 31, 0, 0, 0, TimeSpan.Zero));
var order = new Order
{
CreatedDate = new DateTimeOffset(2024, 1, 1, 0, 0, 0, TimeSpan.Zero)
};
var sut = new OrderService(fakeTime);
// Act
var result = sut.IsExpired(order);
// Assert
result.Should().BeTrue();
}
ä»»å 4ï¼æ¹å測試å¯è®æ§
æ å¢ï¼ç¾ææ¸¬è©¦é£ä»¥çè§£ï¼ç¶è·å°é£
æ¨è¦æè½çµåï¼
dotnet-testing-test-naming-conventions– å½åè¦ç¯dotnet-testing-awesome-assertions-guide– æµæ¢æ·è¨dotnet-testing-test-data-builder-pattern– æ¸ æ°çæ¸¬è©¦è³æ
å¯¦æ½æ¥é©ï¼
- éæ°å½åæ¸¬è©¦æ¹æ³ï¼éµå¾ªä¸æ®µå¼å½å
- ä½¿ç¨ FluentAssertions æ¹å¯«æ·è¨
- ä½¿ç¨ Builder Pattern å»ºç«æ¸¬è©¦è³æ
æç¤ºè©ç¯ä¾ï¼
è«ä½¿ç¨ dotnet-testing-awesome-assertions-guide å dotnet-testing-test-naming-conventions skills
檢è¦ä¸¦æ¹åéäºæ¸¬è©¦çå¯è®æ§ï¼
[è²¼ä¸æ¸¬è©¦ç¨å¼ç¢¼]
ä»»å 5ï¼ç¢ç大鿏¬è©¦è³æ
æ å¢ï¼æè½æ¸¬è©¦éè¦ 1000 ç Customer è³æ
æ¨è¦æè½çµåï¼
dotnet-testing-autofixture-basics– èªåç¢çdotnet-testing-bogus-fake-data– æ¬çè³æï¼å¯é¸ï¼dotnet-testing-autofixture-bogus-integration– çµåå ©è åªå¢ï¼å¯é¸ï¼
å¯¦æ½æ¥é©ï¼
- ä½¿ç¨ AutoFixture.CreateMany() ç¢ç大éè³æ
- ï¼å¯é¸ï¼ä½¿ç¨ Bogus è®è³ææ´ç實
- ï¼å¯é¸ï¼æ´åå ©è ï¼èªåå + æ¬ç
æç¤ºè©ç¯ä¾ï¼
è«ä½¿ç¨ dotnet-testing-autofixture-basics skill çºæè½æ¸¬è©¦ç¢ç 1000 ç Customer è³æï¼
æ¯çè³æéè¦æ NameãEmailãPhoneNumber çæ¬ä½ã
ä»»å 6ï¼æ¸¬è©¦ FluentValidation é©èå¨
æ å¢ï¼CreateUserValidator æå¤æ¢é©èè¦å
æ¨è¦æè½ï¼
dotnet-testing-fluentvalidation-testing
å¯¦æ½æ¥é©ï¼
- ä½¿ç¨ FluentValidation.TestHelper
- æ¸¬è©¦æ¯æ¢é©èè¦å
- 測試çµåæ å¢
æç¤ºè©ç¯ä¾ï¼
è«ä½¿ç¨ dotnet-testing-fluentvalidation-testing skill çº CreateUserValidator å»ºç«æ¸¬è©¦ã
é©èå¨çè¦åå
æ¬ï¼Name å¿
å¡«ãEmail æ ¼å¼é©èãAge å¿
é å¤§æ¼ 18ã
ä»»å 7ï¼æ¸¬è©¦æªæ¡ä¸å³åè½
æ å¢ï¼FileUploadService éè¦å²åä¸å³çæªæ¡
æ¨è¦æè½ï¼
dotnet-testing-filesystem-testing-abstractions
å¯¦æ½æ¥é©ï¼
- éæ§ç¨å¼ç¢¼ï¼ä½¿ç¨ IFileSystem
- 卿¸¬è©¦ä¸ä½¿ç¨ MockFileSystem
- é©èæªæ¡æä½
æç¤ºè©ç¯ä¾ï¼
è«ä½¿ç¨ dotnet-testing-filesystem-testing-abstractions skill å婿¸¬è©¦ FileUploadServiceã
該æåæå°ä¸å³çæªæ¡å²åå° uploads/ ç®éã
å¸ç¿è·¯å¾å»ºè°
æ°æè·¯å¾ï¼1-2 é±ï¼
ç®æ¨ï¼å»ºç«æ¸¬è©¦åºç¤ï¼è½å¤ æ°å¯«åºæ¬çå®å 測試
éæ®µ 1ï¼å»ºç«åºç¤ï¼Day 1-5ï¼
Day 1-2ï¼æ¸¬è©¦åºç¤æ¦å¿µ
- æè½ï¼
dotnet-testing-unit-test-fundamentals - å¸ç¿éé»ï¼
- FIRST åå
- 3A Pattern
- [Fact] è [Theory] ç使ç¨
- åºæ¬æ·è¨æ¹æ³
- 實ä½ç·´ç¿ï¼çºç°¡å®ç Calculator é¡å¥å¯«æ¸¬è©¦
Day 3ï¼å½åè¦ç¯
- æè½ï¼
dotnet-testing-test-naming-conventions - å¸ç¿éé»ï¼
- 䏿®µå¼å½åæ³
- 䏿å½å建è°
- 測試é¡å¥å½å
- 實ä½ç·´ç¿ï¼éæ°å½å Day 1-2 çæ¸¬è©¦
Day 4-5ï¼å»ºç«æ¸¬è©¦å°æ¡
- æè½ï¼
dotnet-testing-xunit-project-setup - å¸ç¿éé»ï¼
- å°æ¡çµæ§è¦å
- .csproj è¨å®
- NuGet å¥ä»¶ç®¡ç
- xunit.runner.json è¨å®
- 實ä½ç·´ç¿ï¼çºç¾æå°æ¡å»ºç«æ¸¬è©¦å°æ¡
éæ®µ 2ï¼æåå質ï¼Day 6-10ï¼
Day 6-7ï¼æµæ¢æ·è¨
- æè½ï¼
dotnet-testing-awesome-assertions-guide - å¸ç¿éé»ï¼
- FluentAssertions åºç¤
- éåæ·è¨
- ä¾å¤æ·è¨
- ç©ä»¶æ¯å°
- 實ä½ç·´ç¿ï¼æ¹å¯«ä¹åçæ¸¬è©¦ï¼ä½¿ç¨ FluentAssertions
Day 8ï¼æ¸¬è©¦è¼¸åº
- æè½ï¼
dotnet-testing-test-output-logging - å¸ç¿éé»ï¼
- ITestOutputHelper 使ç¨
- æ´å ILogger
- é¤é¯æå·§
- 實ä½ç·´ç¿ï¼çºè¤é測試å å ¥è¼¸åº
Day 9-10ï¼èçä¾è³´
- æè½ï¼
dotnet-testing-nsubstitute-mocking - å¸ç¿éé»ï¼
- Mock vs Stub vs Spy
- åºæ¬æ¨¡æ¬è¨å®
- é©èå¼å«
- Returns å Throws
- 實ä½ç·´ç¿ï¼æ¸¬è©¦æ Repository ä¾è³´ç Service
éæ®µ 3ï¼èªå忏¬è©¦è³æï¼Day 11-14ï¼
Day 11-12ï¼AutoFixture åºç¤
- æè½ï¼
dotnet-testing-autofixture-basics - å¸ç¿éé»ï¼
- å¿åæ¸¬è©¦è³æ
- Create å CreateMany
- æ¸å°æ¸¬è©¦æ¨£æ¿ç¨å¼ç¢¼
- 實ä½ç·´ç¿ï¼ä½¿ç¨ AutoFixture ç°¡åæ¸¬è©¦
Day 13-14ï¼æ´åæç¨
- æè½ï¼
dotnet-testing-autodata-xunit-integrationdotnet-testing-autofixture-nsubstitute-integration
- å¸ç¿éé»ï¼
- AutoData 屬æ§
- èªåå»ºç« Mock
- çµå使ç¨
- 實ä½ç·´ç¿ï¼ç¶åæç¨ AutoFixture + NSubstitute
éæ®µ 4ï¼ç¸½çµè實æ°ï¼Day 15ï¼
- çºä¸åå°åå°æ¡å»ºç«å®æ´æ¸¬è©¦
- æç¨æå¸çæææè½
- è¨å® Code Coverage
é²éè·¯å¾ï¼2-3 é±ï¼
åç½®æ¢ä»¶ï¼å®ææ°æè·¯å¾
第ä¸é±ï¼æ¸¬è©¦è³æå°ç²¾
Day 1-2ï¼AutoFixture é²é
- æè½ï¼
dotnet-testing-autofixture-customization - å¸ç¿éé»ï¼
- Customizations
- Specimens
- Behaviors
- èªè¨çæè¦å
Day 3-4ï¼æ¬çè³æ
- æè½ï¼
dotnet-testing-bogus-fake-data - å¸ç¿éé»ï¼
- Faker 使ç¨
- ç實æè³æçæ
- æ¬å°åè³æ
Day 5ï¼Builder Pattern
- æè½ï¼
dotnet-testing-test-data-builder-pattern - å¸ç¿éé»ï¼
- å»ºç« Test Data Builder
- Fluent Interface
- é è¨å¼è¨å®
Day 6-7ï¼æ´åæç¨
- æè½ï¼
dotnet-testing-autofixture-bogus-integration - å¸ç¿éé»ï¼
- æ´å AutoFixture è Bogus
- 鏿åé©çå·¥å ·
第äºé±ï¼ç¹æ®å ´æ¯èç
Day 1-2ï¼æéæ¸¬è©¦
- æè½ï¼
dotnet-testing-datetime-testing-timeprovider - å¸ç¿éé»ï¼
- TimeProvider æ½è±¡å
- FakeTimeProvider 使ç¨
- æåèç
Day 3-4ï¼æªæ¡ç³»çµ±æ¸¬è©¦
- æè½ï¼
dotnet-testing-filesystem-testing-abstractions - å¸ç¿éé»ï¼
- IFileSystem ä»é¢
- MockFileSystem 使ç¨
- æªæ¡æä½æ¸¬è©¦
Day 5-6ï¼è¤éç©ä»¶æ¯å°
- æè½ï¼
dotnet-testing-complex-object-comparison - å¸ç¿éé»ï¼
- 深層ç©ä»¶æ¯å°
- æé¤ç¹å®å±¬æ§
- èªè¨æ¯å°è¦å
Day 7ï¼ç§ææå¡æ¸¬è©¦
- æè½ï¼
dotnet-testing-private-internal-testing - å¸ç¿éé»ï¼
- InternalsVisibleTo
- 測試çç¥
- 使æé¿å
第ä¸é±ï¼åè³ªèæ´å
Day 1-2ï¼é©è測試
- æè½ï¼
dotnet-testing-fluentvalidation-testing - å¸ç¿éé»ï¼
- TestHelper 使ç¨
- é©èè¦å測試
- é¯èª¤è¨æ¯é©è
Day 3-4ï¼ç¨å¼ç¢¼è¦èç
- æè½ï¼
dotnet-testing-code-coverage-analysis - å¸ç¿éé»ï¼
- Coverlet 使ç¨
- å ±åç¢ç
- CI/CD æ´å
Day 5-7ï¼ç¶å實æ°
- çºä¸åå°æ¡å»ºç«å®æ´æ¸¬è©¦
- æç¨ææå¸å°çæè½
- å»ºç«æ¸¬è©¦æä½³å¯¦è¸æä»¶
å¿«éåèï¼æè©²å å¸ä»éº¼ï¼
ææ¯æ°æï¼å®å ¨æ²å¯«é測試 â æ°æè·¯å¾é段 1ï¼unit-test-fundamentals â test-naming-conventions â xunit-project-setup
ææå¯«åºç¤æ¸¬è©¦ï¼æ³æåå質 â æ°æè·¯å¾é段 2ï¼awesome-assertions-guide â nsubstitute-mocking
ææ³æå測試æç â é²éè·¯å¾ç¬¬ä¸é±ï¼æ¸¬è©¦è³æçæç³»å
æéå°ç¹æ®å ´æ¯ï¼æéãæªæ¡ç³»çµ±ï¼ â é²éè·¯å¾ç¬¬äºé±ï¼ç¹æ®å ´æ¯èçç³»å
ææ³è©ä¼°æ¸¬è©¦å質 â code-coverage-analysis
å¼å°å°è©±ç¯ä¾
以ä¸ç¯ä¾å±ç¤º AI å¦ä½èæ¨äºåï¼å¹«å©æ¨é¸ææ£ç¢ºçæè½ã
ç¯ä¾ 1ï¼æ°æå ¥é
æ¨ï¼ææ³å¸ç¿ .NET 測試
AIï¼æå¾æ¨æå婿¨å¸ç¿ .NET 測試ï¼çºäºæä¾æé©åçæå¼ï¼è«å訴æï¼
-
æ¨ç測試ç¶é©ï¼
- å®å ¨æ²å¯«é測試
- 寫éä¸äºåºç¤æ¸¬è©¦
- æä¸å®ç¶é©ï¼æ³æ·±å ¥å¸ç¿
-
æ¨çå°æ¡æ æ³ï¼
- æ°å°æ¡ï¼å¾é¶éå§
- ç¾æå°æ¡ï¼æ³å å ¥æ¸¬è©¦
- æ¹åç¾ææ¸¬è©¦å質
è«åè¨´ææ¨çæ æ³ï¼æææ¨è¦é©åçå¸ç¿è·¯å¾ã
æ¨ï¼å®å ¨æ²å¯«éæ¸¬è©¦ï¼æ¯æ°å°æ¡
AIï¼å¤ªå¥½äºï¼ææçºæ¨è¦åä¸åå¾ªåºæ¼¸é²çå¸ç¿è·¯å¾ãå»ºè°æ¨å¾ä»¥ä¸ä¸åæè½éå§ï¼
ç¬¬ä¸æ¥ï¼ç解測試åºç¤ï¼1-2 天ï¼
ä½¿ç¨ dotnet-testing-unit-test-fundamentals skill
å¸ç¿éé»ï¼FIRST ååã3A Patternãåºæ¬æ¸¬è©¦çµæ§
ç¬¬äºæ¥ï¼å¸ç¿å½åè¦ç¯ï¼å天ï¼
ä½¿ç¨ dotnet-testing-test-naming-conventions skill
å¸ç¿éé»ï¼ä¸æ®µå¼å½åæ³ãæåå¯è®æ§
ç¬¬ä¸æ¥ï¼å»ºç«æ¸¬è©¦å°æ¡ï¼1 天ï¼
ä½¿ç¨ dotnet-testing-xunit-project-setup skill
å¸ç¿éé»ï¼å°æ¡çµæ§ãå¥ä»¶è¨å®
éè¦æä½¿ç¨éäº skills å婿¨éå§åï¼
ç¯ä¾ 2ï¼èçä¾è³´
æ¨ï¼æéè¦çº UserService 寫測試ï¼ä½å®ä¾è³´è³æåº«åå¤é¨ API
AIï¼äºè§£ï¼æ¨çæ æ³éè¦æ¨¡æ¬ï¼Mockï¼å¤é¨ä¾è³´ãææ¨è¦ä»¥ä¸æè½çµåï¼
å¿ è¦æè½ï¼
dotnet-testing-nsubstitute-mocking– 模æ¬è³æåº«è API ä¾è³´ ç¨éï¼å»ºç« IUserRepository å IApiClient ç Mock ç©ä»¶
å»ºè°æé
ï¼
2. dotnet-testing-autofixture-basics – èªåç¢çæ¸¬è©¦è³æ
ç¨éï¼å¿«éç¢ç User 測試ç©ä»¶
dotnet-testing-awesome-assertions-guide– æ¸ æ°çæ·è¨ ç¨éï¼è®æ¸¬è©¦æ´æè®
實æ½å»ºè°ï¼
- å ä½¿ç¨ NSubstitute çºä¾è³´å»ºç« Mock
- ç¨ AutoFixture ç¢ç User æ¸¬è©¦è³æ
- æç § 3A Pattern æ°å¯«æ¸¬è©¦
- ä½¿ç¨ FluentAssertions é©èçµæ
éè¦æä½¿ç¨éäº skills å婿¨å»ºç«æ¸¬è©¦åï¼
ç¯ä¾ 3ï¼ç¹å®åé¡
æ¨ï¼æçç¨å¼ç¢¼ç¨ DateTime.Nowï¼è¦æéº¼æ¸¬è©¦ï¼
AIï¼éæ¯æéç¸é測試çç¶å
¸åé¡ï¼ææ¨è¦ä½¿ç¨ dotnet-testing-datetime-testing-timeprovider skillã
åé¡åæï¼
DateTime.Now æ¯æ¬¡å·è¡é½ä¸åï¼ç¡æ³å¯«åºå¯éè¤ç測試ï¼éå FIRST ååä¸ç Repeatableï¼ã
è§£æ±ºæ¹æ¡ï¼
- éæ§ç¨å¼ç¢¼ï¼æ³¨å
¥
TimeProvider - 卿¸¬è©¦ä¸ä½¿ç¨
FakeTimeProvideræ§å¶æé - 鿍£å°±è½æ¸¬è©¦ç¹å®æéé»çè¡çº
ç¯ä¾ï¼
// éæ§åï¼é£ä»¥æ¸¬è©¦ï¼
public bool IsExpired()
{
return DateTime.Now > ExpiryDate;
}
// éæ§å¾ï¼å¯æ¸¬è©¦ï¼
public bool IsExpired(TimeProvider timeProvider)
{
return timeProvider.GetUtcNow() > ExpiryDate;
}
éè¦æä½¿ç¨ dotnet-testing-datetime-testing-timeprovider skill å婿¨éæ§ä¸¦å»ºç«æ¸¬è©¦åï¼
ç¯ä¾ 4ï¼æ¹åç¾ææ¸¬è©¦
æ¨ï¼æç測試å¾é£è®ï¼ç¶è·å°é£
AIï¼æ¸¬è©¦å¯è®æ§åé¡å¾å¸¸è¦ï¼æå»ºè°å¾ä»¥ä¸ä¸åæ¹åæ¹åï¼
1. å½åè¦ç¯
ä½¿ç¨ dotnet-testing-test-naming-conventions skill
- æ¡ç¨ä¸æ®µå¼å½åï¼
[æ¹æ³]_[æ å¢]_[é æ] - è®æ¸¬è©¦åç¨±èªæèªªæ
2. æµæ¢æ·è¨
ä½¿ç¨ dotnet-testing-awesome-assertions-guide skill
- ä½¿ç¨ FluentAssertions å代å³çµ±æ·è¨
- å¤§å¹ æåå¯è®æ§
3. æ¸
æ°çæ¸¬è©¦è³æ
ä½¿ç¨ dotnet-testing-test-data-builder-pattern skill
- ä½¿ç¨ Builder Pattern å»ºç«æ¸¬è©¦è³æ
- è®æ¸¬è©¦æåæ´æç¢º
å¿«éç¯ä¾ï¼
// æ¹åå
[Fact]
public void Test1()
{
var u = new User { Name = "test", Age = 20 };
var r = svc.Validate(u);
Assert.True(r);
}
// æ¹åå¾
[Fact]
public void Validate_AdultUser_ShouldReturnTrue()
{
// Arrange
var user = new UserBuilder()
.WithName("test")
.WithAge(20)
.Build();
// Act
var result = _service.Validate(user);
// Assert
result.Should().BeTrue();
}
è¦ä¸è¦æå婿¨æ¹åç¹å®ç測試ï¼è«è²¼ä¸æ¨ç測試ç¨å¼ç¢¼ã
èé²éæè½çéä¿
宿åºç¤æè½å¾ï¼å¦ææ¨éè¦é²è¡æ´å測試ãAPI 測試ã容å¨å測試æå¾®æå測試ï¼è«åèï¼
é²éæ´å測試 â dotnet-testing-advanced
- ASP.NET Core æ´å測試
- 容å¨å測試ï¼Testcontainersï¼
- å¾®æå測試ï¼.NET Aspireï¼
- æ¸¬è©¦æ¡æ¶åç´èé·ç§»
ç¸éè³æº
åå§è³æä¾æº
-
iThome éµäººè³½ç³»åæç« ï¼èæ´¾è»é«å·¥ç¨å¸«ç測試修練 – 30 å¤©ææ° ð 2025 iThome éµäººè³½ Software Development çµå è»
-
宿´ç¯ä¾ç¨å¼ç¢¼ï¼30Days_in_Testing_Samples å 嫿æç¯ä¾å°æ¡çå¯å·è¡ç¨å¼ç¢¼
å¸ç¿ææª
æ¬æè½éåºæ¼ä»¥ä¸å®æ´æææç èæï¼
-
Agent Skillsï¼å¾æ¶æ§è¨è¨å°å¯¦æ°æç¨ (docs/Agent_Skills_Mastery.pdf) 宿´æ¶µè Agent Skills å¾çè«å°å¯¦è¸
-
Claude Code Skills: è® AI è®èº«å°æ¥å·¥å (docs/Agent_Skills_Architecture.pdf) æ·±å ¥è§£æ Agent Skills çæ¶æ§è¨è¨
-
.NET Testingï¼å¯«å¾æ´å¥½ãè·å¾æ´å¿« (docs/NET_Testing_Write_Better_Run_Faster.pdf) 測試å·è¡åªåèé¤é¯æå·§
ä¸ä¸æ¥
é¸æç¬¦åæ¨éæ±çæè½éå§å¸ç¿ï¼æåè¨´ææ¨çå ·é«æ æ³ï¼æææ¨è¦æé©åçå¸ç¿è·¯å¾ï¼
å¿«ééå§ï¼
- æ°æ â å¾
dotnet-testing-unit-test-fundamentalséå§ - æç¶é© â åè¨´ææ¨éå°çå ·é«åé¡
- ä¸ç¢ºå® â åè¨´ææ¨çå°æ¡æ æ³ï¼ææå¹«æ¨åæ