Skip to content

Commit f3edd7f

Browse files
committed
Add test output from a different directory to ensure the output is kept even if all tests of a run have passed
1 parent 40ab73b commit f3edd7f

2 files changed

Lines changed: 47 additions & 28 deletions

File tree

src/Dibix.Testing/TestBase.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ internal TestOutputWriter TestOutputHelper
5555
}
5656
protected virtual bool AttachOutputObserver => false;
5757
protected virtual TextWriter Out => this.TestOutputHelper;
58+
59+
/// <summary>
60+
/// By default, the test results directory is cleaned up by MSTest, after all tests of a run have passed.
61+
/// It might be desired to keep the test output even if all tests have passed, i.E. for investigation purposes.
62+
/// Setting this property to true, will store the output in the temp directory, so they are still available after each run.
63+
/// </summary>
64+
protected virtual bool UseDedicatedTestResultsDirectory => true;
5865
private TestResultComposer TestResultComposer
5966
{
6067
get => SafeGetProperty(ref this._testResultComposer);
@@ -73,7 +80,7 @@ protected TestBase()
7380
[TestInitialize]
7481
public async Task OnTestInitialize()
7582
{
76-
this.TestResultComposer = new TestResultComposer(this.TestContext);
83+
this.TestResultComposer = new TestResultComposer(this.TestContext, this.UseDedicatedTestResultsDirectory);
7784
this.TestOutputHelper = new TestOutputWriter(this.TestContext, this.TestResultComposer, outputToFile: true, tailOutput: this.AttachOutputObserver);
7885
AppDomain.CurrentDomain.FirstChanceException += this.OnFirstChanceException;
7986

src/Dibix.Testing/Utilities/TestResultComposer.cs

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,36 @@
44
using System.IO;
55
using System.IO.Compression;
66
using System.Linq;
7+
using System.Reflection;
78
using Microsoft.VisualStudio.TestTools.UnitTesting;
89

910
namespace Dibix.Testing
1011
{
1112
internal sealed class TestResultComposer
1213
{
14+
private const string ExpectedDirectoryName = "expected";
15+
private const string ActualDirectoryName = "actual";
1316
private readonly TestContext _testContext;
17+
private readonly bool _useDedicatedTestResultsDirectory;
18+
private readonly string _defaultRunDirectory;
19+
private readonly string _dedicatedRunDirectory;
1420
private readonly string _runDirectory;
1521
private readonly string _testDirectory;
22+
private readonly string _expectedDirectory;
23+
private readonly string _actualDirectory;
1624
private readonly ICollection<string> _testRunFiles;
1725
private readonly ICollection<string> _testFiles;
1826

19-
public TestResultComposer(TestContext testContext)
27+
public TestResultComposer(TestContext testContext, bool useDedicatedTestResultsDirectory)
2028
{
2129
this._testContext = testContext;
22-
this._runDirectory = testContext.TestRunResultsDirectory;
23-
this._testDirectory = this.EnsureDirectory("TestResults", testContext.TestName);
30+
this._useDedicatedTestResultsDirectory = useDedicatedTestResultsDirectory;
31+
this._defaultRunDirectory = testContext.TestRunResultsDirectory;
32+
this._dedicatedRunDirectory = BuildDedicatedRunDirectory(testContext);
33+
this._runDirectory = this._useDedicatedTestResultsDirectory ? this._dedicatedRunDirectory : this._defaultRunDirectory;
34+
this._testDirectory = Path.Combine(this._runDirectory, "TestResults", testContext.TestName);
35+
this._expectedDirectory = Path.Combine(this._runDirectory, ExpectedDirectoryName);
36+
this._actualDirectory = Path.Combine(this._runDirectory, ActualDirectoryName);
2437
this._testRunFiles = new HashSet<string>();
2538
this._testFiles = new HashSet<string>();
2639
}
@@ -40,8 +53,8 @@ public string AddFile(string fileName, string content)
4053

4154
public void AddFileComparison(string expectedContent, string actualContent, string extension)
4255
{
43-
this.EnsureFileComparisonContent(this.GetExpectedDirectory(), extension, expectedContent);
44-
this.EnsureFileComparisonContent(this.GetActualDirectory(), extension, actualContent);
56+
this.EnsureFileComparisonContent(this._expectedDirectory, extension, expectedContent);
57+
this.EnsureFileComparisonContent(this._actualDirectory, extension, actualContent);
4558
this.EnsureWinMergeStarter();
4659
}
4760

@@ -67,17 +80,6 @@ private void EnsureFileComparisonContent(string path, string content)
6780
this.RegisterFile(path, scopeIsTestRun: false);
6881
}
6982

70-
private string GetExpectedDirectory() => this.EnsureDirectory("expected");
71-
72-
private string GetActualDirectory() => this.EnsureDirectory("actual");
73-
74-
private string EnsureDirectory(params string[] directoryNames)
75-
{
76-
string path = Path.Combine(EnumerableExtensions.Create(this._runDirectory).Concat(directoryNames).ToArray());
77-
Directory.CreateDirectory(path);
78-
return path;
79-
}
80-
8183
private bool ShouldRegisterTestRunFile(string path)
8284
{
8385
if (File.Exists(path))
@@ -99,6 +101,7 @@ private void RegisterFile(string path, bool scopeIsTestRun)
99101
if (files.Contains(path))
100102
throw new InvalidOperationException($"Test result file already registered: {path}");
101103

104+
EnsureDirectory(path);
102105
this._testContext.AddResultFile(path);
103106
files.Add(path);
104107
}
@@ -111,11 +114,8 @@ private void EnsureWinMergeStarter()
111114
if (!this.ShouldRegisterTestRunFile(path))
112115
return;
113116

114-
string expectedDirectory = new DirectoryInfo(this.GetExpectedDirectory()).Name;
115-
string actualDirectory = new DirectoryInfo(this.GetActualDirectory()).Name;
116-
117117
WriteContentToFile(path, $@"@echo off
118-
start winmergeU ""{expectedDirectory}"" ""{actualDirectory}""");
118+
start winmergeU ""{ExpectedDirectoryName}"" ""{ActualDirectoryName}""");
119119
this.RegisterFile(path, scopeIsTestRun: true);
120120
}
121121
@@ -164,15 +164,13 @@ private void ZipTestOutput()
164164
this.RegisterFile(path, scopeIsTestRun: false);
165165
}
166166

167-
// Copy the test output to a dedicated directory, if specified.
168167
private void CopyTestOutput()
169168
{
170-
string privateTestResultsDirectory = (string)this._testContext.Properties["PrivateTestResultsDirectory"];
171-
if (privateTestResultsDirectory == null)
169+
if (!this._useDedicatedTestResultsDirectory)
172170
return;
173171

174-
this.CopyFiles(this._testRunFiles, privateTestResultsDirectory, ignoreIfExists: true);
175-
this.CopyFiles(this._testFiles, privateTestResultsDirectory);
172+
this.CopyFiles(this._testRunFiles, this._defaultRunDirectory, ignoreIfExists: true);
173+
this.CopyFiles(this._testFiles, this._defaultRunDirectory);
176174
}
177175

178176
private void CopyFiles(IEnumerable<string> files, string targetDirectory, bool ignoreIfExists = false)
@@ -181,12 +179,26 @@ private void CopyFiles(IEnumerable<string> files, string targetDirectory, bool i
181179
{
182180
string relativeFilePath = file.Substring(this._runDirectory.Length + 1);
183181
string targetFilePath = Path.Combine(targetDirectory, relativeFilePath);
184-
string fullTargetDirectory = Path.GetDirectoryName(targetFilePath);
185-
Directory.CreateDirectory(fullTargetDirectory);
182+
EnsureDirectory(targetFilePath);
186183

187184
if (!ignoreIfExists || !File.Exists(targetFilePath))
188185
File.Copy(file, targetFilePath);
189186
}
190187
}
188+
189+
private static void EnsureDirectory(string path)
190+
{
191+
string directory = Path.GetDirectoryName(path);
192+
Directory.CreateDirectory(directory);
193+
}
194+
195+
private static string BuildDedicatedRunDirectory(TestContext testContext)
196+
{
197+
Assembly assembly = TestImplementationResolver.ResolveTestAssembly(testContext);
198+
string assemblyName = assembly.GetName().Name;
199+
string directoryName = new DirectoryInfo(testContext.TestRunDirectory).Name;
200+
string path = Path.Combine(Path.GetTempPath(), assemblyName, "TestResults", directoryName);
201+
return path;
202+
}
191203
}
192204
}

0 commit comments

Comments
 (0)