Test attribute for creating transcripts

This commit is contained in:
benbierens 2024-07-31 09:50:02 +02:00
parent 7d737a5534
commit cfd635146b
No known key found for this signature in database
GPG Key ID: 877D2C2E09A22F3A
2 changed files with 46 additions and 10 deletions

View File

@ -18,7 +18,6 @@ namespace CodexTests
{ {
public class CodexDistTest : DistTest public class CodexDistTest : DistTest
{ {
private const bool enableOverwatchTranscript = true;
private static readonly Dictionary<TestLifecycle, CodexTranscriptWriter> writers = new Dictionary<TestLifecycle, CodexTranscriptWriter>(); private static readonly Dictionary<TestLifecycle, CodexTranscriptWriter> writers = new Dictionary<TestLifecycle, CodexTranscriptWriter>();
public CodexDistTest() public CodexDistTest()
@ -128,9 +127,16 @@ namespace CodexTests
{ {
} }
private CreateTranscriptAttribute? GetTranscriptAttributeOfCurrentTest()
{
var attrs = GetCurrentTestMethodAttribute<CreateTranscriptAttribute>();
if (attrs.Any()) return attrs.Single();
return null;
}
private void SetupTranscript(TestLifecycle lifecycle) private void SetupTranscript(TestLifecycle lifecycle)
{ {
if (!enableOverwatchTranscript) return; if (GetTranscriptAttributeOfCurrentTest() == null) return;
var writer = new CodexTranscriptWriter(Transcript.NewWriter()); var writer = new CodexTranscriptWriter(Transcript.NewWriter());
Ci.SetCodexHooksProvider(writer); Ci.SetCodexHooksProvider(writer);
@ -139,7 +145,10 @@ namespace CodexTests
private void TeardownTranscript(TestLifecycle lifecycle, DistTestResult result) 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]; var writer = writers[lifecycle];
writers.Remove(lifecycle); writers.Remove(lifecycle);
@ -153,11 +162,10 @@ namespace CodexTests
writer.ProcessLogs(lifecycle.DownloadAllLogs()); writer.ProcessLogs(lifecycle.DownloadAllLogs());
}); });
var file = lifecycle.Log.CreateSubfile("owts"); Stopwatch.Measure(lifecycle.Log, $"Transcript.Finalize: {outputFilepath}", () =>
Stopwatch.Measure(lifecycle.Log, $"Transcript.Finalize: {file.FullFilename}", () =>
{ {
writer.IncludeFile(lifecycle.Log.LogFile.FullFilename); writer.IncludeFile(lifecycle.Log.LogFile.FullFilename);
writer.Finalize(file.FullFilename); writer.Finalize(outputFilepath);
}); });
} }
catch (Exception ex) catch (Exception ex)
@ -165,5 +173,25 @@ namespace CodexTests
lifecycle.Log.Error("Failure during transcript teardown: " + ex); 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; }
} }
} }

View File

@ -262,11 +262,16 @@ namespace DistTestCore
return CurrentTestMethodHasAttribute<DontDownloadLogsAttribute>(); return CurrentTestMethodHasAttribute<DontDownloadLogsAttribute>();
} }
private bool CurrentTestMethodHasAttribute<T>() where T : PropertyAttribute protected bool CurrentTestMethodHasAttribute<T>() where T : PropertyAttribute
{
return GetCurrentTestMethodAttribute<T>().Any();
}
protected T[] GetCurrentTestMethodAttribute<T>() where T : PropertyAttribute
{ {
// Don't be fooled! TestContext.CurrentTest.Test allows you easy access to the attributes of the current test. // 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 // But this doesn't work for tests making use of [TestCase] or [Combinatorial]. So instead, we use reflection here to
// if the attribute is present. // fetch the attributes of type T.
var currentTest = TestContext.CurrentContext.Test; var currentTest = TestContext.CurrentContext.Test;
var className = currentTest.ClassName; var className = currentTest.ClassName;
var methodName = currentTest.MethodName; var methodName = currentTest.MethodName;
@ -274,7 +279,10 @@ namespace DistTestCore
var testClasses = testAssemblies.SelectMany(a => a.GetTypes()).Where(c => c.FullName == className).ToArray(); 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(); var testMethods = testClasses.SelectMany(c => c.GetMethods()).Where(m => m.Name == methodName).ToArray();
return testMethods.Any(m => m.GetCustomAttribute<T>() != null); return testMethods.Select(m => m.GetCustomAttribute<T>())
.Where(a => a != null)
.Cast<T>()
.ToArray();
} }
private void IncludeLogsOnTestFailure(TestLifecycle lifecycle) private void IncludeLogsOnTestFailure(TestLifecycle lifecycle)