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
{
private const bool enableOverwatchTranscript = true;
private static readonly Dictionary<TestLifecycle, CodexTranscriptWriter> writers = new Dictionary<TestLifecycle, CodexTranscriptWriter>();
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)
{
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; }
}
}

View File

@ -262,11 +262,16 @@ namespace DistTestCore
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.
// 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<T>() != null);
return testMethods.Select(m => m.GetCustomAttribute<T>())
.Where(a => a != null)
.Cast<T>()
.ToArray();
}
private void IncludeLogsOnTestFailure(TestLifecycle lifecycle)