From 9474d1a72c8ba58207e57468d7f4ce2b21bca210 Mon Sep 17 00:00:00 2001 From: Maksim Stepanov <17935127+delatrie@users.noreply.github.com> Date: Thu, 28 Sep 2023 02:56:29 +0700 Subject: [PATCH] Implement selective run for allure-xunit --- Allure.XUnit/AllureMessageSink.cs | 92 +++++++++++++++++++++-------- Allure.XUnit/AllureXunitHelper.cs | 36 ++++------- Allure.XUnit/AllureXunitPatcher.cs | 45 ++++++++------ Allure.XUnit/AllureXunitTestData.cs | 8 ++- 4 files changed, 110 insertions(+), 71 deletions(-) diff --git a/Allure.XUnit/AllureMessageSink.cs b/Allure.XUnit/AllureMessageSink.cs index 90d3b5c2..a1e146bd 100644 --- a/Allure.XUnit/AllureMessageSink.cs +++ b/Allure.XUnit/AllureMessageSink.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using Allure.Net.Commons; +using Allure.Net.Commons.TestPlan; using Allure.Xunit; using Xunit; using Xunit.Abstractions; @@ -14,6 +15,16 @@ namespace Allure.XUnit public class AllureMessageSink : DefaultRunnerReporterWithTypesMessageHandler { + static readonly Lazy lazyTestPlan + = new(AllureTestPlan.FromEnvironment); + + static AllureTestPlan TestPlan { get => lazyTestPlan.Value; } + + static AllureContext AllureContext + { + get => AllureLifecycle.Instance.Context; + } + readonly ConcurrentDictionary allureTestData = new(); @@ -40,6 +51,16 @@ MessageHandlerArgs args args.Message.ExecutionOptions.SetSynchronousMessageReporting(true); } + internal bool SelectByTestPlan(ITest test) + { + var associatedData = this.GetOrCreateTestData(test); + var testResult = AllureXunitHelper.CreateTestResultByTest(test); + var isSelected = TestPlan.IsMatch(testResult); + associatedData.TestResult = testResult; + associatedData.IsSelected = isSelected; + return isSelected; + } + internal void OnTestArgumentsCreated(ITest test, object[] arguments) => this.GetOrCreateTestData(test).Arguments = arguments; @@ -47,17 +68,24 @@ void OnTestStarting(MessageHandlerArgs args) { var message = args.Message; var test = message.Test; + var testData = this.GetOrCreateTestData(test); - if (IsStaticTestMethod(message)) - { - AllureXunitHelper.StartStaticAllureTestCase(test); - this.CaptureTestContext(test); - } - else + if (testData.IsSelected) { - AllureXunitHelper.StartNewAllureContainer( - message.TestClass.Class.Name - ); + if (IsStaticTestMethod(message)) + { + AllureXunitHelper.StartAllureTestCase( + test, + testData.TestResult + ); + this.CaptureTestContext(test); + } + else + { + AllureXunitHelper.StartNewAllureContainer( + message.TestClass.Class.Name + ); + } } } @@ -67,9 +95,11 @@ MessageHandlerArgs args { var message = args.Message; var test = message.Test; + if (!IsStaticTestMethod(message)) { - AllureXunitHelper.StartAllureTestCase(test); + var testResult = this.GetOrCreateTestData(test).TestResult; + AllureXunitHelper.StartAllureTestCase(test, testResult); this.CaptureTestContext(test); } } @@ -90,31 +120,41 @@ void OnTestSkipped(MessageHandlerArgs args) { var message = args.Message; var test = message.Test; - this.UpdateTestContext(test, () => + var testData = this.GetOrCreateTestData(test); + if (testData.IsSelected) { - if (!AllureLifecycle.Instance.Context.HasTest) + this.UpdateTestContext(test, () => { - AllureXunitHelper.StartAllureTestCase(test); - } - AllureXunitHelper.ApplyTestSkip(message); - }); + if (!AllureContext.HasTest) + { + AllureXunitHelper.StartAllureTestCase( + test, + testData.TestResult + ); + } + AllureXunitHelper.ApplyTestSkip(message); + }); + } } void OnTestFinished(MessageHandlerArgs args) { var message = args.Message; var test = args.Message.Test; - var arguments = this.allureTestData[test].Arguments; + var testData = this.GetOrCreateTestData(test); - this.RunInTestContext(test, () => + if (testData.IsSelected) { - this.AddAllureParameters(test, arguments); - AllureXunitHelper.ReportCurrentTestCase(); - if (!IsStaticTestMethod(message)) + this.RunInTestContext(test, () => { - AllureXunitHelper.ReportCurrentTestContainer(); - } - }); + this.AddAllureParameters(test, testData.Arguments); + AllureXunitHelper.ReportCurrentTestCase(); + if (!IsStaticTestMethod(message)) + { + AllureXunitHelper.ReportCurrentTestContainer(); + } + }); + } this.allureTestData.Remove(test, out _); } @@ -129,7 +169,7 @@ AllureXunitTestData GetOrCreateTestData(ITest test) return data; } - void AddAllureParameters(ITest test, object[] arguments) + void AddAllureParameters(ITest test, object[]? arguments) { var testCase = test.TestCase; var parameters = testCase.TestMethod.Method.GetParameters(); @@ -148,7 +188,7 @@ void AddAllureParameters(ITest test, object[] arguments) void CaptureTestContext(ITest test) => this.GetOrCreateTestData(test).Context = - AllureLifecycle.Instance.Context; + AllureContext; AllureContext RunInTestContext(ITest test, Action action) => AllureLifecycle.Instance.RunInContext( diff --git a/Allure.XUnit/AllureXunitHelper.cs b/Allure.XUnit/AllureXunitHelper.cs index 98d3a3fa..3b22b13c 100644 --- a/Allure.XUnit/AllureXunitHelper.cs +++ b/Allure.XUnit/AllureXunitHelper.cs @@ -60,19 +60,13 @@ string className return container; } - internal static TestResult StartStaticAllureTestCase(ITest test) - { - var testResult = CreateTestResultByTest(test); - AllureLifecycle.Instance.StartTestCase(testResult); - return testResult; - } - - internal static TestResult StartAllureTestCase(ITest test) - { - var testResult = CreateTestResultByTest(test); - AllureLifecycle.Instance.StartTestCase(testResult); - return testResult; - } + internal static void StartAllureTestCase( + ITest test, + TestResult? testResult + ) => + AllureLifecycle.Instance.StartTestCase( + testResult ?? CreateTestResultByTest(test) + ); internal static void ApplyTestFailure(IFailureInformation failure) { @@ -149,20 +143,9 @@ internal static void ReportCurrentTestContainer() AllureLifecycle.Instance.WriteTestContainer(); } - internal static void ReportSkippedTestCase(ITestCase testCase) - { - var testResult = CreateTestResultByTestCase(testCase); - ApplyTestSkip(testResult, testCase.SkipReason); - AllureLifecycle.Instance.StartTestCase(testResult); - ReportCurrentTestCase(); - } - - static TestResult CreateTestResultByTest(ITest test) => + internal static TestResult CreateTestResultByTest(ITest test) => CreateTestResult(test.TestCase, test.DisplayName); - static TestResult CreateTestResultByTestCase(ITestCase testCase) => - CreateTestResult(testCase, testCase.DisplayName); - static TestResult CreateTestResult( ITestCase testCase, string displayName @@ -421,6 +404,9 @@ public static void StartTestCase(ITestCaseMessage testCaseMessage) ); } + static TestResult CreateTestResultByTestCase(ITestCase testCase) => + CreateTestResult(testCase, testCase.DisplayName); + [Obsolete(OBS_MSG_UNINTENDED_PUBLIC)] [EditorBrowsable(EditorBrowsableState.Never)] public static void MarkTestCaseAsFailedOrBroken(ITestFailed testFailed) diff --git a/Allure.XUnit/AllureXunitPatcher.cs b/Allure.XUnit/AllureXunitPatcher.cs index cd370fb2..7bc25e89 100644 --- a/Allure.XUnit/AllureXunitPatcher.cs +++ b/Allure.XUnit/AllureXunitPatcher.cs @@ -13,6 +13,19 @@ static class AllureXunitPatcher static bool isPatched = false; static IRunnerLogger logger; + static AllureMessageSink CurrentSink + { + get + { + var sink = AllureMessageSink.CurrentSink; + if (sink is null) + { + logger.LogWarning("Unable to get current message sink."); + } + return sink; + } + } + public static void PatchXunit(IRunnerLogger runnerLogger) { if (isPatched) @@ -39,9 +52,13 @@ static void PatchXunitTestRunnerCtors(Harmony patcher) { patcher.Patch( ctor, + prefix: new HarmonyMethod( + typeof(AllureXunitPatcher), + nameof(OnTestRunnerCreating) + ), postfix: new HarmonyMethod( typeof(AllureXunitPatcher), - nameof(AllureXunitPatcher.OnTestRunnerCreated) + nameof(OnTestRunnerCreated) ) ); wasPatched = true; @@ -72,26 +89,18 @@ static void PatchXunitTestRunnerCtors(Harmony patcher) } } - static void OnTestRunnerCreated( - ITest test, - object[] testMethodArguments - ) + static void OnTestRunnerCreating(ITest test, ref string skipReason) { - if (AllureMessageSink.CurrentSink is null) - { - logger.LogWarning( - "Unable to get current message sink from the test " + - "runner's hook of the {0} test", - test.DisplayName - ); - } - else + if (!CurrentSink.SelectByTestPlan(test)) { - AllureMessageSink.CurrentSink.OnTestArgumentsCreated( - test, - testMethodArguments - ); + skipReason = "Deselected by the testplan."; } } + + static void OnTestRunnerCreated( + ITest test, + object[] testMethodArguments + ) => + CurrentSink.OnTestArgumentsCreated(test, testMethodArguments); } } \ No newline at end of file diff --git a/Allure.XUnit/AllureXunitTestData.cs b/Allure.XUnit/AllureXunitTestData.cs index f8512b5f..2a0d3b18 100644 --- a/Allure.XUnit/AllureXunitTestData.cs +++ b/Allure.XUnit/AllureXunitTestData.cs @@ -1,10 +1,14 @@ using Allure.Net.Commons; +#nullable enable + namespace Allure.XUnit { class AllureXunitTestData { - public AllureContext Context { get; set; } - public object[] Arguments { get; set; } + public AllureContext? Context { get; set; } + public object[]? Arguments { get; set; } + public TestResult? TestResult { get; set; } + public bool IsSelected { get; set; } = true; } } \ No newline at end of file