Skip to content

Commit d8482fd

Browse files
Port improvements from TemplateDotNetLibrary template (#32)
* Initial plan * Port improvements from TemplateDotNetLibrary: editorconfig, gitignore, buildmark version, test csproj structure Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com> * Port test improvements from TemplateDotNetLibrary - Remove redundant InternalsVisibleTo from test AssemblyInfo.cs - Add consistent AAA (Arrange/Act/Assert) comments to all test methods - Matches patterns from TemplateDotNetLibrary and existing PathHelpersTests.cs * Add consistent AAA comments to tests and remove redundant InternalsVisibleTo from test AssemblyInfo Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com> * Add MSTest V4 Best Practices section to test-developer agent from Library template Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Malcolmnixon <1863707+Malcolmnixon@users.noreply.github.com>
1 parent 33d0259 commit d8482fd

File tree

9 files changed

+114
-37
lines changed

9 files changed

+114
-37
lines changed

.config/dotnet-tools.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
]
4040
},
4141
"demaconsulting.buildmark": {
42-
"version": "0.2.0",
42+
"version": "0.3.0",
4343
"commands": [
4444
"buildmark"
4545
]

.editorconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ root = true
66
# All files
77
[*]
88
charset = utf-8
9+
end_of_line = lf
910
indent_style = space
1011
indent_size = 4
1112
insert_final_newline = true

.github/agents/test-developer.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,41 @@ public void ClassName_MethodUnderTest_Scenario_ExpectedBehavior()
7171
- Use MSTest V4 testing framework
7272
- Follow existing naming conventions in the test suite
7373

74+
### MSTest V4 Best Practices
75+
76+
Common anti-patterns to avoid (not exhaustive):
77+
78+
1. **Avoid Assertions in Catch Blocks (MSTEST0058)** - Instead of wrapping code in try/catch and asserting in the
79+
catch block, use `Assert.ThrowsExactly<T>()`:
80+
81+
```csharp
82+
var ex = Assert.ThrowsExactly<ArgumentNullException>(() => SomeWork());
83+
Assert.Contains("Some message", ex.Message);
84+
```
85+
86+
2. **Avoid using Assert.IsTrue / Assert.IsFalse for equality checks** - Use `Assert.AreEqual` /
87+
`Assert.AreNotEqual` instead, as it provides better failure messages:
88+
89+
```csharp
90+
// ❌ Bad: Assert.IsTrue(result == expected);
91+
// ✅ Good: Assert.AreEqual(expected, result);
92+
```
93+
94+
3. **Avoid non-public test classes and methods** - Test classes and `[TestMethod]` methods must be `public` or
95+
they will be silently ignored:
96+
97+
```csharp
98+
// ❌ Bad: internal class MyTests
99+
// ✅ Good: public class MyTests
100+
```
101+
102+
4. **Avoid Assert.IsTrue(collection.Count == N)** - Use `Assert.HasCount` for count assertions:
103+
104+
```csharp
105+
// ❌ Bad: Assert.IsTrue(collection.Count == 3);
106+
// ✅ Good: Assert.HasCount(3, collection);
107+
```
108+
74109
## Defer To
75110

76111
- **Requirements Agent**: For test strategy and coverage requirements

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ artifacts/
7878

7979
# Node.js
8080
node_modules/
81+
package-lock.json
8182
npm-debug.log
8283

8384
# Python

test/DemaConsulting.TemplateDotNetTool.Tests/AssemblyInfo.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,4 @@
1818
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1919
// SOFTWARE.
2020

21-
using System.Runtime.CompilerServices;
22-
23-
[assembly: InternalsVisibleTo("DemaConsulting.TemplateDotNetTool.Tests")]
2421
[assembly: DoNotParallelize]

test/DemaConsulting.TemplateDotNetTool.Tests/ContextTests.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,10 @@ public class ContextTests
3232
[TestMethod]
3333
public void Context_Create_NoArguments_ReturnsDefaultContext()
3434
{
35+
// Act
3536
using var context = Context.Create([]);
3637

38+
// Assert
3739
Assert.IsFalse(context.Version);
3840
Assert.IsFalse(context.Help);
3941
Assert.IsFalse(context.Silent);
@@ -47,8 +49,10 @@ public void Context_Create_NoArguments_ReturnsDefaultContext()
4749
[TestMethod]
4850
public void Context_Create_VersionFlag_SetsVersionTrue()
4951
{
52+
// Act
5053
using var context = Context.Create(["--version"]);
5154

55+
// Assert
5256
Assert.IsTrue(context.Version);
5357
Assert.IsFalse(context.Help);
5458
Assert.AreEqual(0, context.ExitCode);
@@ -60,8 +64,10 @@ public void Context_Create_VersionFlag_SetsVersionTrue()
6064
[TestMethod]
6165
public void Context_Create_ShortVersionFlag_SetsVersionTrue()
6266
{
67+
// Act
6368
using var context = Context.Create(["-v"]);
6469

70+
// Assert
6571
Assert.IsTrue(context.Version);
6672
Assert.IsFalse(context.Help);
6773
Assert.AreEqual(0, context.ExitCode);
@@ -73,8 +79,10 @@ public void Context_Create_ShortVersionFlag_SetsVersionTrue()
7379
[TestMethod]
7480
public void Context_Create_HelpFlag_SetsHelpTrue()
7581
{
82+
// Act
7683
using var context = Context.Create(["--help"]);
7784

85+
// Assert
7886
Assert.IsFalse(context.Version);
7987
Assert.IsTrue(context.Help);
8088
Assert.AreEqual(0, context.ExitCode);
@@ -86,8 +94,10 @@ public void Context_Create_HelpFlag_SetsHelpTrue()
8694
[TestMethod]
8795
public void Context_Create_ShortHelpFlag_H_SetsHelpTrue()
8896
{
97+
// Act
8998
using var context = Context.Create(["-h"]);
9099

100+
// Assert
91101
Assert.IsFalse(context.Version);
92102
Assert.IsTrue(context.Help);
93103
Assert.AreEqual(0, context.ExitCode);
@@ -99,8 +109,10 @@ public void Context_Create_ShortHelpFlag_H_SetsHelpTrue()
99109
[TestMethod]
100110
public void Context_Create_ShortHelpFlag_Question_SetsHelpTrue()
101111
{
112+
// Act
102113
using var context = Context.Create(["-?"]);
103114

115+
// Assert
104116
Assert.IsFalse(context.Version);
105117
Assert.IsTrue(context.Help);
106118
Assert.AreEqual(0, context.ExitCode);
@@ -112,8 +124,10 @@ public void Context_Create_ShortHelpFlag_Question_SetsHelpTrue()
112124
[TestMethod]
113125
public void Context_Create_SilentFlag_SetsSilentTrue()
114126
{
127+
// Act
115128
using var context = Context.Create(["--silent"]);
116129

130+
// Assert
117131
Assert.IsTrue(context.Silent);
118132
Assert.AreEqual(0, context.ExitCode);
119133
}
@@ -124,8 +138,10 @@ public void Context_Create_SilentFlag_SetsSilentTrue()
124138
[TestMethod]
125139
public void Context_Create_ValidateFlag_SetsValidateTrue()
126140
{
141+
// Act
127142
using var context = Context.Create(["--validate"]);
128143

144+
// Assert
129145
Assert.IsTrue(context.Validate);
130146
Assert.AreEqual(0, context.ExitCode);
131147
}
@@ -136,8 +152,10 @@ public void Context_Create_ValidateFlag_SetsValidateTrue()
136152
[TestMethod]
137153
public void Context_Create_ResultsFlag_SetsResultsFile()
138154
{
155+
// Act
139156
using var context = Context.Create(["--results", "test.trx"]);
140157

158+
// Assert
141159
Assert.AreEqual("test.trx", context.ResultsFile);
142160
Assert.AreEqual(0, context.ExitCode);
143161
}
@@ -148,15 +166,18 @@ public void Context_Create_ResultsFlag_SetsResultsFile()
148166
[TestMethod]
149167
public void Context_Create_LogFlag_OpensLogFile()
150168
{
169+
// Arrange
151170
var logFile = Path.GetTempFileName();
152171
try
153172
{
173+
// Act
154174
using (var context = Context.Create(["--log", logFile]))
155175
{
156176
context.WriteLine("Test message");
157177
Assert.AreEqual(0, context.ExitCode);
158178
}
159179

180+
// Assert
160181
// Verify log file was written
161182
Assert.IsTrue(File.Exists(logFile));
162183
var logContent = File.ReadAllText(logFile);
@@ -177,6 +198,7 @@ public void Context_Create_LogFlag_OpensLogFile()
177198
[TestMethod]
178199
public void Context_Create_UnknownArgument_ThrowsArgumentException()
179200
{
201+
// Act & Assert
180202
var exception = Assert.Throws<ArgumentException>(() => Context.Create(["--unknown"]));
181203
Assert.Contains("Unsupported argument", exception.Message);
182204
}
@@ -187,15 +209,18 @@ public void Context_Create_UnknownArgument_ThrowsArgumentException()
187209
[TestMethod]
188210
public void Context_WriteLine_NotSilent_WritesToConsole()
189211
{
212+
// Arrange
190213
var originalOut = Console.Out;
191214
try
192215
{
193216
using var outWriter = new StringWriter();
194217
Console.SetOut(outWriter);
195218
using var context = Context.Create([]);
196219

220+
// Act
197221
context.WriteLine("Test message");
198222

223+
// Assert
199224
var output = outWriter.ToString();
200225
Assert.Contains("Test message", output);
201226
}
@@ -211,15 +236,18 @@ public void Context_WriteLine_NotSilent_WritesToConsole()
211236
[TestMethod]
212237
public void Context_WriteLine_Silent_DoesNotWriteToConsole()
213238
{
239+
// Arrange
214240
var originalOut = Console.Out;
215241
try
216242
{
217243
using var outWriter = new StringWriter();
218244
Console.SetOut(outWriter);
219245
using var context = Context.Create(["--silent"]);
220246

247+
// Act
221248
context.WriteLine("Test message");
222249

250+
// Assert
223251
var output = outWriter.ToString();
224252
Assert.DoesNotContain("Test message", output);
225253
}

test/DemaConsulting.TemplateDotNetTool.Tests/DemaConsulting.TemplateDotNetTool.Tests.csproj

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,47 @@
11
<Project Sdk="Microsoft.NET.Sdk">
2+
23
<PropertyGroup>
4+
<!-- Build Configuration -->
35
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
46
<LangVersion>12</LangVersion>
57
<ImplicitUsings>enable</ImplicitUsings>
68
<Nullable>enable</Nullable>
7-
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
8-
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
9-
<EnableNETAnalyzers>true</EnableNETAnalyzers>
10-
<AnalysisLevel>latest</AnalysisLevel>
119

1210
<IsPackable>false</IsPackable>
1311
<IsTestProject>true</IsTestProject>
1412
<GenerateDocumentationFile>True</GenerateDocumentationFile>
13+
14+
<!-- Code Quality Configuration -->
15+
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
16+
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
17+
<EnableNETAnalyzers>true</EnableNETAnalyzers>
18+
<AnalysisLevel>latest</AnalysisLevel>
1519
</PropertyGroup>
1620

21+
<!-- Test Framework Dependencies -->
1722
<ItemGroup>
1823
<PackageReference Include="coverlet.collector" Version="8.0.0">
1924
<PrivateAssets>all</PrivateAssets>
2025
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
2126
</PackageReference>
27+
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
28+
<PackageReference Include="MSTest.TestAdapter" Version="4.1.0" />
29+
<PackageReference Include="MSTest.TestFramework" Version="4.1.0" />
30+
</ItemGroup>
31+
32+
<!-- Code Analysis Dependencies -->
33+
<ItemGroup>
2234
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="10.0.103">
2335
<PrivateAssets>all</PrivateAssets>
2436
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
2537
</PackageReference>
26-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
27-
<PackageReference Include="MSTest.TestAdapter" Version="4.1.0" />
28-
<PackageReference Include="MSTest.TestFramework" Version="4.1.0" />
2938
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.19.0.132793">
3039
<PrivateAssets>all</PrivateAssets>
3140
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
3241
</PackageReference>
3342
</ItemGroup>
3443

44+
<!-- Project References -->
3545
<ItemGroup>
3646
<ProjectReference Include="..\..\src\DemaConsulting.TemplateDotNetTool\DemaConsulting.TemplateDotNetTool.csproj" />
3747
</ItemGroup>

0 commit comments

Comments
 (0)