Skip to content

Commit 56c9431

Browse files
(GH-275) Add option to filter test results in GetTestRuns to specific test outcomes (#311)
Co-authored-by: Pascal Berger <[email protected]>
1 parent 176f6fb commit 56c9431

File tree

8 files changed

+356
-7
lines changed

8 files changed

+356
-7
lines changed
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
namespace Cake.AzureDevOps.Tests.Fakes
2+
{
3+
using System;
4+
using System.Threading;
5+
using Cake.AzureDevOps.Authentication;
6+
using Microsoft.TeamFoundation.Build.WebApi;
7+
using Microsoft.TeamFoundation.Core.WebApi;
8+
using Moq;
9+
10+
public class FakeAllSetBuildClientFactory : FakeBuildClientFactory
11+
{
12+
public override BuildHttpClient CreateBuildClient(Uri collectionUrl, IAzureDevOpsCredentials credentials)
13+
{
14+
var mock = new Mock<BuildHttpClient>(MockBehavior.Loose, collectionUrl, credentials.ToVssCredentials());
15+
16+
mock.Setup(arg => arg.GetBuildAsync(It.IsAny<Guid>(), It.IsAny<int>(), null, null, default(CancellationToken)))
17+
.ReturnsAsync((Guid projectId, int buildId, string propertyFilters, object userState, CancellationToken token) => new Build
18+
{
19+
Id = buildId,
20+
BuildNumber = buildId.ToString(),
21+
Project = new TeamProjectReference { Id = projectId },
22+
});
23+
24+
mock.Setup(arg => arg.GetBuildAsync(It.IsAny<string>(), It.IsAny<int>(), null, null, default(CancellationToken)))
25+
.ReturnsAsync((string projectName, int buildId, string propertyFilters, object userState, CancellationToken token) => new Build
26+
{
27+
Id = buildId,
28+
BuildNumber = buildId.ToString(),
29+
Project = new TeamProjectReference { Name = projectName },
30+
});
31+
32+
mock = this.Setup(mock);
33+
34+
return mock.Object;
35+
}
36+
}
37+
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
namespace Cake.AzureDevOps.Tests.Fakes
2+
{
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using System.Threading;
7+
using Cake.AzureDevOps.Authentication;
8+
using Microsoft.TeamFoundation.TestManagement.WebApi;
9+
using Moq;
10+
11+
public class FakeAllSetTestManagementClientFactory : FakeTestManagementClientFactory
12+
{
13+
public override TestManagementHttpClient CreateTestManagementClient(Uri collectionUrl, IAzureDevOpsCredentials credentials)
14+
{
15+
var mock = new Mock<TestManagementHttpClient>(MockBehavior.Strict, collectionUrl, credentials.ToVssCredentials());
16+
17+
mock.Setup(arg => arg.GetTestResultDetailsForBuildAsync(It.IsAny<Guid>(), It.Is<int>(id => id == 1), null, null, null, null, null, null, null, default(CancellationToken)))
18+
.ReturnsAsync(() => new TestResultsDetails { ResultsForGroup = new List<TestResultsDetailsForGroup>() });
19+
20+
mock.Setup(arg => arg.GetTestResultDetailsForBuildAsync(It.IsAny<Guid>(), It.Is<int>(id => id > 1), null, null, null, null, null, null, null, default(CancellationToken)))
21+
.ReturnsAsync(() => new TestResultsDetails
22+
{
23+
ResultsForGroup = new List<TestResultsDetailsForGroup>()
24+
{
25+
new TestResultsDetailsForGroup
26+
{
27+
Results = new List<TestCaseResult>()
28+
{
29+
new TestCaseResult { Id = 11, TestRun = new ShallowReference { Id = "1" } },
30+
new TestCaseResult { Id = 12, TestRun = new ShallowReference { Id = "1" } },
31+
new TestCaseResult { Id = 13, TestRun = new ShallowReference { Id = "1" } },
32+
},
33+
},
34+
},
35+
});
36+
37+
mock.Setup(arg => arg.GetTestResultsAsync(It.IsAny<Guid>(), It.IsAny<int>(), null, It.IsAny<int?>(), It.IsAny<int?>(), It.IsAny<IEnumerable<TestOutcome>>(), null, default(CancellationToken)))
38+
.ReturnsAsync((Guid projectId, int testRunId, ResultDetails? details, int? skip, int? top, IEnumerable<TestOutcome> outcomes, object userState, CancellationToken token) => new List<TestCaseResult>()
39+
{
40+
new TestCaseResult { AutomatedTestName = "t1", Outcome = "Passed", ErrorMessage = string.Empty },
41+
new TestCaseResult { AutomatedTestName = "t2", Outcome = "Failed", ErrorMessage = "Error" },
42+
new TestCaseResult { AutomatedTestName = "t3", Outcome = "Passed", ErrorMessage = string.Empty },
43+
}.Take(top.Value).ToList());
44+
45+
mock = this.Setup(mock);
46+
47+
return mock.Object;
48+
}
49+
}
50+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
namespace Cake.AzureDevOps.Tests.Fakes
2+
{
3+
using System;
4+
using Cake.AzureDevOps.Authentication;
5+
using Microsoft.TeamFoundation.Build.WebApi;
6+
using Microsoft.VisualStudio.Services.Identity;
7+
using Moq;
8+
9+
public abstract class FakeBuildClientFactory : IBuildClientFactory
10+
{
11+
public abstract BuildHttpClient CreateBuildClient(Uri collectionUrl, IAzureDevOpsCredentials credentials);
12+
13+
public BuildHttpClient CreateBuildClient(Uri collectionUrl, IAzureDevOpsCredentials credentials, out Identity authorizedIdentity)
14+
{
15+
authorizedIdentity = new Identity { ProviderDisplayName = "FakeUser", Id = Guid.NewGuid(), IsActive = true };
16+
return this.CreateBuildClient(collectionUrl, credentials);
17+
}
18+
19+
protected virtual Mock<BuildHttpClient> Setup(Mock<BuildHttpClient> m)
20+
{
21+
return m;
22+
}
23+
}
24+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
namespace Cake.AzureDevOps.Tests.Fakes
2+
{
3+
using System;
4+
using System.Threading;
5+
using Cake.AzureDevOps.Authentication;
6+
using Microsoft.TeamFoundation.Build.WebApi;
7+
using Moq;
8+
9+
public class FakeNullBuildClientFactory : FakeBuildClientFactory
10+
{
11+
public override BuildHttpClient CreateBuildClient(Uri collectionUrl, IAzureDevOpsCredentials credentials)
12+
{
13+
var mock = new Mock<BuildHttpClient>(MockBehavior.Loose, collectionUrl, credentials.ToVssCredentials());
14+
15+
mock.Setup(arg => arg.GetBuildAsync(It.IsAny<Guid>(), It.IsAny<int>(), null, null, default(CancellationToken)))
16+
.ReturnsAsync(() => null);
17+
18+
mock.Setup(arg => arg.GetBuildAsync(It.IsAny<string>(), It.IsAny<int>(), null, null, default(CancellationToken)))
19+
.ReturnsAsync(() => null);
20+
21+
mock = this.Setup(mock);
22+
23+
return mock.Object;
24+
}
25+
}
26+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
namespace Cake.AzureDevOps.Tests.Fakes
2+
{
3+
using System;
4+
using Cake.AzureDevOps.Authentication;
5+
using Microsoft.TeamFoundation.TestManagement.WebApi;
6+
using Microsoft.VisualStudio.Services.Identity;
7+
using Moq;
8+
9+
public abstract class FakeTestManagementClientFactory : ITestManagementClientFactory
10+
{
11+
public abstract TestManagementHttpClient CreateTestManagementClient(Uri collectionUrl, IAzureDevOpsCredentials credentials);
12+
13+
public TestManagementHttpClient CreateTestManagementClient(Uri collectionUrl, IAzureDevOpsCredentials credentials, out Identity authorizedIdentity)
14+
{
15+
authorizedIdentity = new Identity { ProviderDisplayName = "FakeUser", Id = Guid.NewGuid(), IsActive = true };
16+
return this.CreateTestManagementClient(collectionUrl, credentials);
17+
}
18+
19+
protected virtual Mock<TestManagementHttpClient> Setup(Mock<TestManagementHttpClient> m)
20+
{
21+
return m;
22+
}
23+
}
24+
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
namespace Cake.AzureDevOps.Tests.Pipelines
2+
{
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using Cake.AzureDevOps.Pipelines;
6+
using Cake.AzureDevOps.Tests.Fakes;
7+
using Shouldly;
8+
using Xunit;
9+
10+
public sealed class AzureDevOpsBuildTests
11+
{
12+
public sealed class TheGetTestRunsMethod
13+
{
14+
[Fact]
15+
public void Should_Return_Empty_List_If_Build_Is_Invalid()
16+
{
17+
// Given
18+
var fixture = new BuildFixture(BuildFixture.ValidAzureDevOpsCollectionUrl, "Foo", 42);
19+
fixture.Settings.ThrowExceptionIfBuildCouldNotBeFound = false;
20+
fixture.BuildClientFactory = new FakeNullBuildClientFactory();
21+
22+
var build = new AzureDevOpsBuild(
23+
fixture.Log,
24+
fixture.Settings,
25+
fixture.BuildClientFactory,
26+
fixture.TestManagementClientFactory);
27+
28+
// When
29+
var result = build.GetTestRuns();
30+
31+
// Then
32+
result.ShouldNotBeNull();
33+
result.ShouldBeEmpty();
34+
result.ShouldBeOfType<List<AzureDevOpsTestRun>>();
35+
}
36+
37+
[Fact]
38+
public void Should_Return_Empty_List_If_Build_Does_Not_Contain_Test_Runs()
39+
{
40+
var fixture = new BuildFixture(BuildFixture.ValidAzureDevOpsCollectionUrl, "Foo", 1);
41+
var build = new AzureDevOpsBuild(
42+
fixture.Log,
43+
fixture.Settings,
44+
fixture.BuildClientFactory,
45+
fixture.TestManagementClientFactory);
46+
47+
// When
48+
var result = build.GetTestRuns();
49+
50+
// Then
51+
result.ShouldNotBeNull();
52+
result.ShouldBeEmpty();
53+
result.ShouldBeOfType<List<AzureDevOpsTestRun>>();
54+
}
55+
56+
[Theory]
57+
[InlineData(0)]
58+
[InlineData(1)]
59+
public void Should_Return_List_Of_Test_Runs_With_X_Test_Results_If_X_Is_Less_Then_Total(int testRunsCount)
60+
{
61+
// Given
62+
var fixture = new BuildFixture(BuildFixture.ValidAzureDevOpsCollectionUrl, "Foo", 42);
63+
var build = new AzureDevOpsBuild(
64+
fixture.Log,
65+
fixture.Settings,
66+
fixture.BuildClientFactory,
67+
fixture.TestManagementClientFactory);
68+
69+
// When
70+
var result = build.GetTestRuns(testRunsCount);
71+
72+
// Then
73+
result.ShouldNotBeNull();
74+
result.ShouldHaveSingleItem();
75+
result.First().RunId.ShouldBe(1);
76+
77+
var testResults = result.First().TestResults;
78+
testResults.Count().ShouldBe(testRunsCount);
79+
}
80+
81+
[Fact]
82+
public void Should_Throw_If_Input_Test_Outcomes_Are_Invalid()
83+
{
84+
// Given
85+
var fixture = new BuildFixture(BuildFixture.ValidAzureDevOpsCollectionUrl, "Foo", 42);
86+
var build = new AzureDevOpsBuild(
87+
fixture.Log,
88+
fixture.Settings,
89+
fixture.BuildClientFactory,
90+
fixture.TestManagementClientFactory);
91+
92+
// When
93+
var result = Record.Exception(() => build.GetTestRuns(null, new string[] { "FakeOutcome" }));
94+
95+
// Then
96+
result.IsArgumentException(null);
97+
}
98+
99+
[Fact]
100+
public void Should_Return_List_Of_Test_Runs_With_Test_Results()
101+
{
102+
// Given
103+
var fixture = new BuildFixture(BuildFixture.ValidAzureDevOpsCollectionUrl, "Foo", 42);
104+
var build = new AzureDevOpsBuild(
105+
fixture.Log,
106+
fixture.Settings,
107+
fixture.BuildClientFactory,
108+
fixture.TestManagementClientFactory);
109+
110+
// When
111+
var result = build.GetTestRuns();
112+
113+
// Then
114+
result.ShouldNotBeNull();
115+
result.ShouldHaveSingleItem();
116+
result.First().RunId.ShouldBe(1);
117+
118+
var testResults = result.First().TestResults;
119+
testResults.ShouldNotBeNull();
120+
testResults.Count().ShouldBe(3);
121+
testResults.ElementAt(0).ShouldBeEquivalentTo(
122+
new AzureDevOpsTestResult { AutomatedTestName = "t1", Outcome = "Passed", ErrorMessage = string.Empty });
123+
testResults.ElementAt(1).ShouldBeEquivalentTo(
124+
new AzureDevOpsTestResult { AutomatedTestName = "t2", Outcome = "Failed", ErrorMessage = "Error" });
125+
testResults.ElementAt(2).ShouldBeEquivalentTo(
126+
new AzureDevOpsTestResult { AutomatedTestName = "t3", Outcome = "Passed", ErrorMessage = string.Empty });
127+
}
128+
}
129+
}
130+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
namespace Cake.AzureDevOps.Tests.Pipelines
2+
{
3+
using System;
4+
using Cake.AzureDevOps.Authentication;
5+
using Cake.AzureDevOps.Pipelines;
6+
using Cake.AzureDevOps.Tests.Fakes;
7+
using Cake.Core.Diagnostics;
8+
using Cake.Testing;
9+
10+
internal class BuildFixture
11+
{
12+
public const string ValidAzureDevOpsCollectionUrl = "https://my-account.visualstudio.com/DefaultCollection";
13+
14+
public BuildFixture(string collectionUrl, string projectName, int buildId)
15+
{
16+
this.Settings = new AzureDevOpsBuildSettings(new Uri(collectionUrl), projectName, buildId, new AzureDevOpsNtlmCredentials());
17+
this.InitialzeFakes();
18+
}
19+
20+
public ICakeLog Log { get; set; }
21+
22+
public IBuildClientFactory BuildClientFactory { get; set; }
23+
24+
public ITestManagementClientFactory TestManagementClientFactory { get; set; }
25+
26+
public AzureDevOpsBuildSettings Settings { get; set; }
27+
28+
private void InitialzeFakes()
29+
{
30+
this.Log = new FakeLog();
31+
this.BuildClientFactory = new FakeAllSetBuildClientFactory();
32+
this.TestManagementClientFactory = new FakeAllSetTestManagementClientFactory();
33+
}
34+
}
35+
}

0 commit comments

Comments
 (0)