Skip to content

Commit aa33cf5

Browse files
authored
Create a test context to take away a lot of the repeating plumbing code (Buildalyzer#260)
1 parent cfe8e01 commit aa33cf5

File tree

6 files changed

+137
-47
lines changed

6 files changed

+137
-47
lines changed

Buildalyzer.sln

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
21
Microsoft Visual Studio Solution File, Format Version 12.00
32
# Visual Studio Version 17
43
VisualStudioVersion = 17.9.34622.214

tests/Buildalyzer.Tests/Integration/SimpleProjectsFixture.cs

Lines changed: 15 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.IO;
33
using System.IO.Compression;
44
using Buildalyzer.Environment;
5+
using Buildalyzer.TestTools;
56
using FluentAssertions;
67
using Shouldly;
78

@@ -60,27 +61,23 @@ public class SimpleProjectsFixture
6061
};
6162

6263
[Test]
63-
public void DesignTimeBuildsProject(
64+
public void Builds_DesignTime(
6465
[ValueSource(nameof(Preferences))] EnvironmentPreference preference,
6566
[ValueSource(nameof(ProjectFiles))] string projectFile)
6667
{
67-
// Given
68-
StringWriter log = new StringWriter();
69-
IProjectAnalyzer analyzer = GetProjectAnalyzer(projectFile, log);
70-
EnvironmentOptions options = new EnvironmentOptions
68+
using var ctx = Context.ForProject(projectFile);
69+
70+
var options = new EnvironmentOptions
7171
{
72-
Preference = preference
72+
Preference = preference,
73+
DesignTime = true,
7374
};
7475

75-
// When
76-
DeleteProjectDirectory(projectFile, "obj");
77-
DeleteProjectDirectory(projectFile, "bin");
78-
IAnalyzerResults results = analyzer.Build(options);
76+
var results = ctx.Analyzer.Build(options);
7977

80-
// Then
81-
results.Count.ShouldBeGreaterThan(0, log.ToString());
82-
results.OverallSuccess.ShouldBeTrue(log.ToString());
83-
results.ShouldAllBe(x => x.Succeeded, log.ToString());
78+
results.Should().NotBeEmpty();
79+
results.OverallSuccess.Should().BeTrue();
80+
results.Should().AllSatisfy(r => r.Succeeded.Should().BeTrue());
8481
}
8582

8683
[Test]
@@ -139,7 +136,7 @@ public void GetsSourceFiles(
139136
[Test]
140137
public void GetsReferences(
141138
[ValueSource(nameof(Preferences))] EnvironmentPreference preference,
142-
[ValueSource(nameof(ProjectFiles))] [NotNull] string projectFile)
139+
[ValueSource(nameof(ProjectFiles))][NotNull] string projectFile)
143140
{
144141
// Given
145142
StringWriter log = new StringWriter();
@@ -685,7 +682,7 @@ public static void DuplicateProjectReferences()
685682
}
686683

687684
[Test]
688-
public void GetsAdditionalCscFiles()
685+
public void Resolves_additional_files_for_Razor_project()
689686
{
690687
// Given
691688
StringWriter log = new StringWriter();
@@ -699,7 +696,7 @@ public void GetsAdditionalCscFiles()
699696
}
700697

701698
[Test]
702-
public void GetsAdditionalFile()
699+
public void Resolves_additional_files()
703700
{
704701
// Given
705702
StringWriter log = new StringWriter();
@@ -710,24 +707,7 @@ public void GetsAdditionalFile()
710707
.Should().BeEquivalentTo("message.txt");
711708
}
712709

713-
[Test]
714-
public void HandlesProcessFailure()
715-
{
716-
// Given
717-
StringWriter log = new StringWriter();
718-
IProjectAnalyzer analyzer = GetProjectAnalyzer(@"SdkNet6Exe\SdkNet6Exe.csproj", log);
719-
720-
// When
721-
IAnalyzerResults results = analyzer.Build(new EnvironmentOptions
722-
{
723-
Arguments = { "/unknown" } // This argument will cause msbuild to immediately fail
724-
});
725-
726-
// Then
727-
results.OverallSuccess.ShouldBeFalse();
728-
}
729-
730-
private static IProjectAnalyzer GetProjectAnalyzer(string projectFile, StringWriter log)
710+
private static IProjectAnalyzer GetProjectAnalyzer(string projectFile, System.IO.StringWriter log)
731711
{
732712
IProjectAnalyzer analyzer = new AnalyzerManager(
733713
new AnalyzerManagerOptions
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
using System.Diagnostics;
2+
using System.IO;
3+
4+
namespace Buildalyzer.TestTools;
5+
6+
/// <summary>Creates a test context for testing <see cref="IProjectAnalyzer"/>s.</summary>
7+
/// <remarks>
8+
/// The context ensures an fresh build (deletes previous artifacts in advance).
9+
/// The context logs to the console in DEBUG mode.
10+
/// </remarks>
11+
public sealed class BuildalyzerTestContext : IDisposable
12+
{
13+
public TextWriter Log => IsDisposed ? throw new ObjectDisposedException(GetType().FullName) : log;
14+
15+
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
16+
private readonly TextWriter log = new StringWriter();
17+
18+
public BuildalyzerTestContext(FileInfo projectFile)
19+
{
20+
ProjectFile = projectFile;
21+
Manager = new AnalyzerManager(
22+
new AnalyzerManagerOptions
23+
{
24+
LogWriter = Log,
25+
});
26+
27+
Analyzer = Manager.GetProject(projectFile.FullName);
28+
29+
DebugMode(ref InDebugMode);
30+
AddBinaryLogger();
31+
DeleteSubDirectory("bin");
32+
DeleteSubDirectory("obj");
33+
}
34+
35+
public FileInfo ProjectFile { get; }
36+
37+
public AnalyzerManager Manager { get; }
38+
39+
public IProjectAnalyzer Analyzer { get; }
40+
41+
/// <inheritdoc />
42+
public void Dispose()
43+
{
44+
if (!IsDisposed)
45+
{
46+
if (InDebugMode)
47+
{
48+
Console.WriteLine(Log.ToString());
49+
}
50+
Log.Dispose();
51+
52+
IsDisposed = true;
53+
}
54+
}
55+
56+
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
57+
private bool IsDisposed;
58+
59+
/// <summary>Ensures that the analysis is done ignoring previous results.</summary>
60+
private void DeleteSubDirectory(string path)
61+
{
62+
var directory = new DirectoryInfo(Path.Combine(ProjectFile.Directory!.FullName, path));
63+
64+
if (directory.Exists)
65+
{
66+
try
67+
{
68+
directory.Delete(true);
69+
Log.WriteLine($"Deleted all files at {directory}");
70+
}
71+
catch (Exception x)
72+
{
73+
Log.WriteLine(x);
74+
}
75+
}
76+
}
77+
78+
[Conditional("BinaryLog")]
79+
private void AddBinaryLogger()
80+
{
81+
Analyzer.AddBinaryLogger(Path.Combine(@"C:\Temp\", Path.ChangeExtension(ProjectFile.Name, ".core.binlog")));
82+
}
83+
84+
/// <summary>Sets <paramref name="inDebugMode"/> to true when run in DEBUG mode.</summary>
85+
[Conditional("DEBUG")]
86+
private void DebugMode(ref bool inDebugMode) => inDebugMode = true;
87+
88+
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
89+
private readonly bool InDebugMode;
90+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using System.Diagnostics.Contracts;
2+
using System.IO;
3+
4+
namespace Buildalyzer.TestTools;
5+
6+
public static class Context
7+
{
8+
[Pure]
9+
public static BuildalyzerTestContext ForProject(string path) => new(GetProjectPath(path));
10+
11+
private static FileInfo GetProjectPath(string file)
12+
{
13+
var location = new FileInfo(typeof(Context).Assembly.Location).Directory!;
14+
return new FileInfo(Path.Combine(
15+
location.FullName,
16+
"..",
17+
"..",
18+
"..",
19+
"..",
20+
"projects",
21+
file));
22+
}
23+
}

tests/Buildalyzer.Workspaces.Tests/Buildalyzer.Workspaces.Tests.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
44
<TargetFramework>net8.0</TargetFramework>
@@ -22,6 +22,7 @@
2222

2323
<ItemGroup>
2424
<ProjectReference Include="..\..\src\Buildalyzer.Workspaces\Buildalyzer.Workspaces.csproj" />
25+
<ProjectReference Include="..\Buildalyzer.Tests\Buildalyzer.Tests.csproj" />
2526
</ItemGroup>
2627

2728
<ItemGroup Label="Additional files">

tests/Buildalyzer.Workspaces.Tests/ProjectAnalyzerExtensionsFixture.cs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using System.IO;
22
using System.Linq;
33
using System.Threading.Tasks;
4+
using Buildalyzer.TestTools;
5+
using FluentAssertions;
46
using Microsoft.CodeAnalysis;
57
using NUnit.Framework;
68
using Shouldly;
@@ -12,19 +14,14 @@ namespace Buildalyzer.Workspaces.Tests;
1214
public class ProjectAnalyzerExtensionsFixture
1315
{
1416
[Test]
15-
public void LoadsWorkspace()
17+
public void Loads_Workspace()
1618
{
17-
// Given
18-
SafeStringWriter log = new SafeStringWriter();
19-
IProjectAnalyzer analyzer = GetProjectAnalyzer(@"projects\SdkNetStandardProject\SdkNetStandardProject.csproj", log);
19+
using var ctx = Context.ForProject(@"SdkNetStandardProject\SdkNetStandardProject.csproj");
2020

21-
// When
22-
Workspace workspace = analyzer.GetWorkspace();
21+
var workspace = ctx.Analyzer.GetWorkspace();
2322

24-
// Then
25-
string logged = log.ToString();
26-
logged.ShouldNotContain("Workspace failed");
27-
workspace.CurrentSolution.Projects.First().Documents.ShouldContain(x => x.Name == "Class1.cs", log.ToString());
23+
ctx.Log.ToString().Should().NotContain("Workspace failed");
24+
workspace.CurrentSolution.Projects.First().Documents.First().Should().BeEquivalentTo(new { Name = "Class1.cs" });
2825
}
2926

3027
[Test]

0 commit comments

Comments
 (0)