Skip to content

Commit 12352b6

Browse files
Copilotpascalberger
andcommitted
Implement JUnit issue provider with tests and validation
Co-authored-by: pascalberger <2190718+pascalberger@users.noreply.github.com>
1 parent ddaa125 commit 12352b6

14 files changed

Lines changed: 907 additions & 0 deletions
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<Description>Tests for the Cake.Issues.JUnit addin</Description>
4+
</PropertyGroup>
5+
6+
<ItemGroup>
7+
<None Remove="Testfiles\**\*" />
8+
</ItemGroup>
9+
10+
<ItemGroup>
11+
<EmbeddedResource Include="Testfiles\*.xml" />
12+
</ItemGroup>
13+
14+
<ItemGroup>
15+
<ProjectReference Include="..\Cake.Issues.JUnit\Cake.Issues.JUnit.csproj" />
16+
</ItemGroup>
17+
</Project>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
namespace Cake.Issues.JUnit.Tests;
2+
3+
using System.Text;
4+
5+
internal class JUnitIssuesProviderFixture
6+
: BaseConfigurableIssueProviderFixture<JUnitIssuesProvider, JUnitIssuesSettings>
7+
{
8+
public JUnitIssuesProviderFixture(string fileResourceName)
9+
: this(fileResourceName, @"c:\Source\Cake.Issues")
10+
{
11+
}
12+
13+
public JUnitIssuesProviderFixture(string fileResourceName, string repositoryRoot)
14+
: base(fileResourceName)
15+
{
16+
this.ReadIssuesSettings =
17+
new ReadIssuesSettings(repositoryRoot);
18+
}
19+
20+
protected override string FileResourceNamespace => "Cake.Issues.JUnit.Tests.Testfiles.";
21+
22+
/// <summary>
23+
/// Sets the content of the log file.
24+
/// </summary>
25+
/// <param name="content">Content to set.</param>
26+
public void SetFileContent(string content)
27+
{
28+
content.NotNullOrWhiteSpace();
29+
this.LogFileContent = Encoding.UTF8.GetBytes(content);
30+
}
31+
}
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
namespace Cake.Issues.JUnit.Tests;
2+
3+
public sealed class JUnitIssuesProviderTests
4+
{
5+
public sealed class TheCtor
6+
{
7+
[Fact]
8+
public void Should_Throw_If_Log_Is_Null()
9+
{
10+
// Given / When
11+
var result = Record.Exception(() =>
12+
new JUnitIssuesProvider(
13+
null,
14+
new JUnitIssuesSettings("Foo".ToByteArray())));
15+
16+
// Then
17+
result.IsArgumentNullException("log");
18+
}
19+
20+
[Fact]
21+
public void Should_Throw_If_IssueProviderSettings_Are_Null()
22+
{
23+
// Given / When
24+
var result = Record.Exception(() => new JUnitIssuesProvider(new FakeLog(), null));
25+
26+
// Then
27+
result.IsArgumentNullException("issueProviderSettings");
28+
}
29+
}
30+
31+
public sealed class TheReadIssuesMethod
32+
{
33+
[Fact]
34+
public void Should_Read_Issues_Correct_For_CppLint()
35+
{
36+
// Given
37+
var fixture = new JUnitIssuesProviderFixture("cpplint.xml");
38+
39+
// When
40+
var issues = fixture.ReadIssues().ToList();
41+
42+
// Then
43+
issues.Count.ShouldBe(2);
44+
45+
var issue1 = issues[0];
46+
issue1.ProviderType.ShouldBe("Cake.Issues.JUnit.JUnitIssuesProvider");
47+
issue1.ProviderName.ShouldBe("JUnit");
48+
issue1.MessageText.ShouldBe("Lines should be <= 80 characters long\nsrc/example.cpp:15: Lines should be <= 80 characters long [whitespace/line_length] [2]");
49+
issue1.Priority.ShouldBe(IssuePriority.Error);
50+
issue1.Rule.ShouldBe("warning");
51+
issue1.AffectedFileRelativePath.ShouldBe("src/example.cpp");
52+
issue1.Line.ShouldBe(15);
53+
54+
var issue2 = issues[1];
55+
issue2.ProviderType.ShouldBe("Cake.Issues.JUnit.JUnitIssuesProvider");
56+
issue2.ProviderName.ShouldBe("JUnit");
57+
issue2.MessageText.ShouldBe("Include order issue\nsrc/example.cpp:5: #includes are not properly sorted [build/include_order] [4]");
58+
issue2.Priority.ShouldBe(IssuePriority.Error);
59+
issue2.Rule.ShouldBe("warning");
60+
issue2.AffectedFileRelativePath.ShouldBe("src/example.cpp");
61+
issue2.Line.ShouldBe(5);
62+
}
63+
64+
[Fact]
65+
public void Should_Read_Issues_Correct_For_Kubeconform()
66+
{
67+
// Given
68+
var fixture = new JUnitIssuesProviderFixture("kubeconform.xml");
69+
70+
// When
71+
var issues = fixture.ReadIssues().ToList();
72+
73+
// Then
74+
issues.Count.ShouldBe(2);
75+
76+
var issue1 = issues[0];
77+
issue1.ProviderType.ShouldBe("Cake.Issues.JUnit.JUnitIssuesProvider");
78+
issue1.ProviderName.ShouldBe("JUnit");
79+
issue1.MessageText.ShouldBe("Invalid resource definition\ndeployment.yaml:10:15: error validating data: ValidationError(Deployment.spec.template.spec.containers[0].image): invalid value: \"\", expected non-empty string");
80+
issue1.Priority.ShouldBe(IssuePriority.Error);
81+
issue1.Rule.ShouldBe("ValidationError");
82+
issue1.AffectedFileRelativePath.ShouldBe("deployment.yaml");
83+
issue1.Line.ShouldBe(10);
84+
issue1.Column.ShouldBe(15);
85+
86+
var issue2 = issues[1];
87+
issue2.ProviderType.ShouldBe("Cake.Issues.JUnit.JUnitIssuesProvider");
88+
issue2.ProviderName.ShouldBe("JUnit");
89+
issue2.MessageText.ShouldBe("Port configuration invalid\nservice.yaml:8:5: Port 8080 is already in use by another service");
90+
issue2.Priority.ShouldBe(IssuePriority.Error);
91+
issue2.Rule.ShouldBe("ConfigError");
92+
issue2.AffectedFileRelativePath.ShouldBe("service.yaml");
93+
issue2.Line.ShouldBe(8);
94+
issue2.Column.ShouldBe(5);
95+
}
96+
97+
[Fact]
98+
public void Should_Read_Issues_Correct_For_HtmlHint()
99+
{
100+
// Given
101+
var fixture = new JUnitIssuesProviderFixture("htmlhint.xml");
102+
103+
// When
104+
var issues = fixture.ReadIssues().ToList();
105+
106+
// Then
107+
issues.Count.ShouldBe(2);
108+
109+
var issue1 = issues[0];
110+
issue1.ProviderType.ShouldBe("Cake.Issues.JUnit.JUnitIssuesProvider");
111+
issue1.ProviderName.ShouldBe("JUnit");
112+
issue1.MessageText.ShouldBe("Tagname must be lowercase\nindex.html(12,5): Tagname 'DIV' must be lowercase");
113+
issue1.Priority.ShouldBe(IssuePriority.Error);
114+
issue1.Rule.ShouldBe("error");
115+
issue1.AffectedFileRelativePath.ShouldBe("index.html");
116+
issue1.Line.ShouldBe(12);
117+
issue1.Column.ShouldBe(5);
118+
119+
var issue2 = issues[1];
120+
issue2.ProviderType.ShouldBe("Cake.Issues.JUnit.JUnitIssuesProvider");
121+
issue2.ProviderName.ShouldBe("JUnit");
122+
issue2.MessageText.ShouldBe("Attribute value must be in double quotes\nabout.html line 8: The value of attribute 'class' must be in double quotes.");
123+
issue2.Priority.ShouldBe(IssuePriority.Error);
124+
issue2.Rule.ShouldBe("warning");
125+
issue2.AffectedFileRelativePath.ShouldBe("about.html");
126+
issue2.Line.ShouldBe(8);
127+
}
128+
129+
[Fact]
130+
public void Should_Read_Issues_Correct_For_CommitLint()
131+
{
132+
// Given
133+
var fixture = new JUnitIssuesProviderFixture("commitlint.xml");
134+
135+
// When
136+
var issues = fixture.ReadIssues().ToList();
137+
138+
// Then
139+
issues.Count.ShouldBe(1);
140+
141+
var issue = issues[0];
142+
issue.ProviderType.ShouldBe("Cake.Issues.JUnit.JUnitIssuesProvider");
143+
issue.ProviderName.ShouldBe("JUnit");
144+
issue.MessageText.ShouldBe("Type must be one of the allowed values\ncommit-2: type must be one of [build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test]");
145+
issue.Priority.ShouldBe(IssuePriority.Error);
146+
issue.Rule.ShouldBe("error");
147+
}
148+
149+
[Fact]
150+
public void Should_Handle_Empty_TestSuite()
151+
{
152+
// Given
153+
var junitContent = @"<?xml version=""1.0"" encoding=""UTF-8""?>
154+
<testsuite name=""empty"" tests=""0"" failures=""0"" errors=""0"" time=""0.000"">
155+
</testsuite>";
156+
var fixture = new JUnitIssuesProviderFixture("empty.xml");
157+
fixture.SetFileContent(junitContent);
158+
159+
// When
160+
var issues = fixture.ReadIssues().ToList();
161+
162+
// Then
163+
issues.Count.ShouldBe(0);
164+
}
165+
166+
[Fact]
167+
public void Should_Handle_Invalid_XML()
168+
{
169+
// Given
170+
var junitContent = @"<?xml version=""1.0"" encoding=""UTF-8""?>
171+
<testsuite name=""invalid"" tests=""1"" failures=""1"" errors=""0"">
172+
<testcase classname=""test"" name=""test"">
173+
<failure message=""test failure"">
174+
</testcase>";
175+
var fixture = new JUnitIssuesProviderFixture("invalid.xml");
176+
fixture.SetFileContent(junitContent);
177+
178+
// When / Then
179+
Should.Throw<IssuesException>(() => fixture.ReadIssues().ToList())
180+
.Message.ShouldContain("Failed to parse JUnit XML");
181+
}
182+
}
183+
}
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
namespace Cake.Issues.JUnit.Tests;
2+
3+
public sealed class JUnitIssuesSettingsTests
4+
{
5+
public sealed class TheCtor
6+
{
7+
[Fact]
8+
public void Should_Throw_If_LogFilePath_Is_Null()
9+
{
10+
// Given / When
11+
var result = Record.Exception(() =>
12+
new JUnitIssuesSettings((FilePath)null));
13+
14+
// Then
15+
result.IsArgumentNullException("logFilePath");
16+
}
17+
18+
[Fact]
19+
public void Should_Throw_If_LogFileContent_Is_Null()
20+
{
21+
// Given / When
22+
var result = Record.Exception(() =>
23+
new JUnitIssuesSettings((byte[])null));
24+
25+
// Then
26+
result.IsArgumentNullException("logFileContent");
27+
}
28+
29+
[Fact]
30+
public void Should_Set_LogFileContent()
31+
{
32+
// Given
33+
var logFileContent = "foo".ToByteArray();
34+
35+
// When
36+
var settings = new JUnitIssuesSettings(logFileContent);
37+
38+
// Then
39+
settings.LogFileContent.ShouldBe(logFileContent);
40+
}
41+
}
42+
43+
public sealed class TheFromFilePathMethod
44+
{
45+
[Fact]
46+
public void Should_Throw_If_LogFilePath_Is_Null()
47+
{
48+
// Given / When
49+
var result = Record.Exception(() =>
50+
JUnitIssuesSettings.FromFilePath(null));
51+
52+
// Then
53+
result.IsArgumentNullException("logFilePath");
54+
}
55+
}
56+
57+
public sealed class TheFromContentMethod
58+
{
59+
[Fact]
60+
public void Should_Throw_If_LogFileContent_Is_Null()
61+
{
62+
// Given / When
63+
var result = Record.Exception(() =>
64+
JUnitIssuesSettings.FromContent((string)null));
65+
66+
// Then
67+
result.IsArgumentNullException("logFileContent");
68+
}
69+
70+
[Fact]
71+
public void Should_Throw_If_LogFileContent_Is_Empty()
72+
{
73+
// Given / When
74+
var result = Record.Exception(() =>
75+
JUnitIssuesSettings.FromContent(string.Empty));
76+
77+
// Then
78+
result.IsArgumentNullOrWhiteSpaceException("logFileContent");
79+
}
80+
81+
[Fact]
82+
public void Should_Throw_If_LogFileContent_Is_WhiteSpace()
83+
{
84+
// Given / When
85+
var result = Record.Exception(() =>
86+
JUnitIssuesSettings.FromContent(" "));
87+
88+
// Then
89+
result.IsArgumentNullOrWhiteSpaceException("logFileContent");
90+
}
91+
92+
[Fact]
93+
public void Should_Set_LogFileContent()
94+
{
95+
// Given
96+
var logFileContent = "foo";
97+
98+
// When
99+
var settings = JUnitIssuesSettings.FromContent(logFileContent);
100+
101+
// Then
102+
settings.LogFileContent.ShouldBe(logFileContent.ToByteArray());
103+
}
104+
105+
[Fact]
106+
public void Should_Throw_If_LogFileContent_Byte_Array_Is_Null()
107+
{
108+
// Given / When
109+
var result = Record.Exception(() =>
110+
JUnitIssuesSettings.FromContent((byte[])null));
111+
112+
// Then
113+
result.IsArgumentNullException("logFileContent");
114+
}
115+
116+
[Fact]
117+
public void Should_Set_LogFileContent_From_Byte_Array()
118+
{
119+
// Given
120+
var logFileContent = "foo".ToByteArray();
121+
122+
// When
123+
var settings = JUnitIssuesSettings.FromContent(logFileContent);
124+
125+
// Then
126+
settings.LogFileContent.ShouldBe(logFileContent);
127+
}
128+
}
129+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
using System.Runtime.CompilerServices;
2+
3+
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<testsuite name="commitlint" tests="3" failures="1" errors="0" time="0.012">
3+
<testcase classname="commit-1" name="header-max-length" time="0.004"/>
4+
<testcase classname="commit-2" name="type-enum" time="0.004">
5+
<failure message="Type must be one of the allowed values" type="error">
6+
commit-2: type must be one of [build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test]
7+
</failure>
8+
</testcase>
9+
<testcase classname="commit-3" name="subject-case" time="0.004"/>
10+
</testsuite>

0 commit comments

Comments
 (0)