diff --git a/Tests/CodexTests/CodexDistTest.cs b/Tests/CodexTests/CodexDistTest.cs index 2bb4fba..ca97ca7 100644 --- a/Tests/CodexTests/CodexDistTest.cs +++ b/Tests/CodexTests/CodexDistTest.cs @@ -18,7 +18,6 @@ namespace CodexTests { public class CodexDistTest : DistTest { - private const bool enableOverwatchTranscript = true; private static readonly Dictionary writers = new Dictionary(); public CodexDistTest() @@ -128,9 +127,16 @@ namespace CodexTests { } + private CreateTranscriptAttribute? GetTranscriptAttributeOfCurrentTest() + { + var attrs = GetCurrentTestMethodAttribute(); + if (attrs.Any()) return attrs.Single(); + return null; + } + private void SetupTranscript(TestLifecycle lifecycle) { - if (!enableOverwatchTranscript) return; + if (GetTranscriptAttributeOfCurrentTest() == null) return; var writer = new CodexTranscriptWriter(Transcript.NewWriter()); Ci.SetCodexHooksProvider(writer); @@ -139,7 +145,10 @@ namespace CodexTests private void TeardownTranscript(TestLifecycle lifecycle, DistTestResult result) { - if (!enableOverwatchTranscript) return; + var attr = GetTranscriptAttributeOfCurrentTest(); + if (attr == null) return; + + var outputFilepath = GetOutputFullPath(lifecycle, attr); var writer = writers[lifecycle]; writers.Remove(lifecycle); @@ -153,11 +162,10 @@ namespace CodexTests writer.ProcessLogs(lifecycle.DownloadAllLogs()); }); - var file = lifecycle.Log.CreateSubfile("owts"); - Stopwatch.Measure(lifecycle.Log, $"Transcript.Finalize: {file.FullFilename}", () => + Stopwatch.Measure(lifecycle.Log, $"Transcript.Finalize: {outputFilepath}", () => { writer.IncludeFile(lifecycle.Log.LogFile.FullFilename); - writer.Finalize(file.FullFilename); + writer.Finalize(outputFilepath); }); } catch (Exception ex) @@ -165,5 +173,25 @@ namespace CodexTests lifecycle.Log.Error("Failure during transcript teardown: " + ex); } } + + private string GetOutputFullPath(TestLifecycle lifecycle, CreateTranscriptAttribute attr) + { + var outputPath = Path.GetDirectoryName(lifecycle.Log.LogFile.FullFilename); + if (outputPath == null) throw new Exception("Logfile path is null"); + var outputFile = Path.Combine(outputPath, attr.OutputFilename); + if (!outputFile.EndsWith(".owts")) outputFile += ".owts"; + return outputFile; + } + } + + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false)] + public class CreateTranscriptAttribute : PropertyAttribute + { + public CreateTranscriptAttribute(string outputFilename) + { + OutputFilename = outputFilename; + } + + public string OutputFilename { get; } } } diff --git a/Tests/DistTestCore/DistTest.cs b/Tests/DistTestCore/DistTest.cs index 09e1a85..57983fb 100644 --- a/Tests/DistTestCore/DistTest.cs +++ b/Tests/DistTestCore/DistTest.cs @@ -262,11 +262,16 @@ namespace DistTestCore return CurrentTestMethodHasAttribute(); } - private bool CurrentTestMethodHasAttribute() where T : PropertyAttribute + protected bool CurrentTestMethodHasAttribute() where T : PropertyAttribute + { + return GetCurrentTestMethodAttribute().Any(); + } + + protected T[] GetCurrentTestMethodAttribute() where T : PropertyAttribute { // Don't be fooled! TestContext.CurrentTest.Test allows you easy access to the attributes of the current test. - // But this doesn't work for tests making use of [TestCase] or [Combinatorial]. So instead, we use reflection here to figure out - // if the attribute is present. + // But this doesn't work for tests making use of [TestCase] or [Combinatorial]. So instead, we use reflection here to + // fetch the attributes of type T. var currentTest = TestContext.CurrentContext.Test; var className = currentTest.ClassName; var methodName = currentTest.MethodName; @@ -274,7 +279,10 @@ namespace DistTestCore var testClasses = testAssemblies.SelectMany(a => a.GetTypes()).Where(c => c.FullName == className).ToArray(); var testMethods = testClasses.SelectMany(c => c.GetMethods()).Where(m => m.Name == methodName).ToArray(); - return testMethods.Any(m => m.GetCustomAttribute() != null); + return testMethods.Select(m => m.GetCustomAttribute()) + .Where(a => a != null) + .Cast() + .ToArray(); } private void IncludeLogsOnTestFailure(TestLifecycle lifecycle)