Skip to content

Commit

Permalink
Selective run support: commons, nunit, xunit (#390)
Browse files Browse the repository at this point in the history
* Implement selective run commons

* Change GetAllureId to take an enumeration

* Implement selective run for allure-nunit

* Add a shorthand for testplan's IsMatch

* Implement selective run for allure-xunit

* Move TestPlan property to commons. Rename selection check method
  • Loading branch information
delatrie authored Oct 10, 2023
1 parent a924992 commit 9abc94d
Show file tree
Hide file tree
Showing 13 changed files with 809 additions and 158 deletions.
10 changes: 10 additions & 0 deletions Allure.NUnit/Core/AllureExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Allure.Net.Commons;
using NUnit.Framework.Interfaces;
using NUnit.Framework.Internal;

namespace NUnit.Allure.Core
Expand Down Expand Up @@ -204,6 +205,15 @@ public static async Task<T> WrapInStepAsync<T>(
}
}

internal const string DESELECTED_BY_TESTPLAN_KEY
= "DESELECTED_BY_TESTPLAN";

static internal void Deselect(this ITest test) =>
test.Properties.Add(DESELECTED_BY_TESTPLAN_KEY, true);

static internal bool IsDeselected(this ITest test) =>
test.Properties.ContainsKey(DESELECTED_BY_TESTPLAN_KEY);

[Obsolete(
"Use AllureLifecycle.AddScreenDiff instance method instead to " +
"add a screen diff to the current test."
Expand Down
22 changes: 15 additions & 7 deletions Allure.NUnit/Core/AllureNUnitAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,17 @@ public void BeforeTest(ITest test) =>

if (!test.IsSuite)
{
helper.StartTestContainer(); // A container for SetUp/TearDown methods
helper.StartTestCase();
helper.PrepareTestContext();
}
});

public void AfterTest(ITest test) =>
public void AfterTest(ITest test)
{
if (test.IsDeselected())
{
return;
}

RunHookInRestoredAllureContext(test, () =>
{
if (_allureNUnitHelper.TryGetValue(test.Id, out var helper))
Expand All @@ -52,14 +57,17 @@ public void AfterTest(ITest test) =>
}
else if (IsSuiteWithNoAfterFixtures(test))
{
// If a test fixture contains a OneTimeTearDown method
// with the [AllureAfter] attribute, the corresponding
// container is closed in StopContainerAspect instead.
// If a test class has no class-scope after-feature
// (i.e., a method with both [OneTimeTearDown] and
// [AllureAfter]), the class-scope container is closed
// here. Otherwise, it's closed in StopContainerAspect
// instead.
helper.StopTestContainer();
}
}
});

}

public ActionTargets Targets =>
ActionTargets.Test | ActionTargets.Suite;

Expand Down
179 changes: 103 additions & 76 deletions Allure.NUnit/Core/AllureNUnitHelper.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using Allure.Net.Commons;
using Allure.Net.Commons.TestPlan;
using Newtonsoft.Json.Linq;
using NUnit.Allure.Attributes;
using NUnit.Framework;
Expand Down Expand Up @@ -40,73 +42,26 @@ internal void StartTestContainer()
});
}

internal void StartTestCase()
internal void PrepareTestContext()
{
var testResult = new TestResult
var testResult = this.CreateTestResult();
if (IsSelectedByTestPlan(testResult))
{
uuid = string.Concat(
Guid.NewGuid().ToString(),
"-tr-",
_test.Id
),
name = _test.Name,
historyId = _test.FullName,
fullName = _test.FullName,
labels = new List<Label>
{
Label.Thread(),
Label.Host(),
Label.Package(
GetNamespace(_test.ClassName)
),
Label.TestMethod(_test.MethodName),
Label.TestClass(
GetClassName(_test.ClassName)
)
}
};
AllureLifecycle.StartTestCase(testResult);
}

static string GetNamespace(string classFullName)
{
var lastDotIndex = classFullName?.LastIndexOf('.') ?? -1;
return lastDotIndex == -1 ? null : classFullName.Substring(
0,
lastDotIndex
);
}

static string GetClassName(string classFullName)
{
var lastDotIndex = classFullName?.LastIndexOf('.') ?? -1;
return lastDotIndex == -1 ? classFullName : classFullName.Substring(
lastDotIndex + 1
);
}

private TestFixture GetTestFixture(ITest test)
{
var currentTest = test;
var isTestSuite = currentTest.IsSuite;
while (isTestSuite != true)
this.StartTestContainer(); // A container for SetUp/TearDown methods
AllureLifecycle.StartTestCase(testResult);
}
else
{
currentTest = currentTest.Parent;
if (currentTest is ParameterizedMethodSuite)
{
currentTest = currentTest.Parent;
}
isTestSuite = currentTest.IsSuite;
this._test.Deselect();
Assert.Ignore("Deselected by the testplan.");
}

return (TestFixture) currentTest;
}

internal void StopTestCase()
{
UpdateTestDataFromAttributes();
UpdateTestDataFromNUnitProperties();
AddConsoleOutputAttachment();

for (var i = 0; i < _test.Arguments.Length; i++)
{
AllureLifecycle.UpdateTestCase(
Expand All @@ -129,7 +84,7 @@ internal void StopTestCase()
{
message = string.IsNullOrWhiteSpace(
TestContext.CurrentContext.Result.Message
) ? TestContext.CurrentContext.Test.Name
) ? TestContext.CurrentContext.Test.Name
: TestContext.CurrentContext.Result.Message,
trace = TestContext.CurrentContext.Result.StackTrace
}
Expand Down Expand Up @@ -195,7 +150,89 @@ public static Status GetNUnitStatus()
return Status.passed;
}

private void UpdateTestDataFromAttributes()
TestResult CreateTestResult()
{
var testResult = new TestResult
{
uuid = string.Concat(
Guid.NewGuid().ToString(),
"-tr-",
_test.Id
),
name = _test.Name,
historyId = _test.FullName,
fullName = _test.FullName,
labels = new List<Label>
{
Label.Thread(),
Label.Host(),
Label.Package(
GetNamespace(_test.ClassName)
),
Label.TestMethod(_test.MethodName),
Label.TestClass(
GetClassName(_test.ClassName)
)
}
};
this.UpdateTestDataFromAllureAttributes(testResult);
return testResult;
}

void UpdateTestDataFromAllureAttributes(TestResult testResult)
{
foreach (var attribute in this.IterateAllAllureAttribites())
{
attribute.UpdateTestResult(testResult);
}
}

static bool IsSelectedByTestPlan(TestResult testResult) =>
AllureLifecycle.TestPlan.IsSelected(testResult);

IEnumerable<AllureTestCaseAttribute> IterateAllAllureAttribites() =>
this._test.Method
.GetCustomAttributes<AllureTestCaseAttribute>(true)
.Concat(
this.GetTestFixture(this._test)
.GetCustomAttributes<AllureTestCaseAttribute>(true)
);

static string GetNamespace(string classFullName)
{
var lastDotIndex = classFullName?.LastIndexOf('.') ?? -1;
return lastDotIndex == -1 ? null : classFullName.Substring(
0,
lastDotIndex
);
}

static string GetClassName(string classFullName)
{
var lastDotIndex = classFullName?.LastIndexOf('.') ?? -1;
return lastDotIndex == -1 ? classFullName : classFullName.Substring(
lastDotIndex + 1
);
}

private TestFixture GetTestFixture(ITest test)
{
var currentTest = test;
var isTestSuite = currentTest.IsSuite;
while (isTestSuite != true)
{
currentTest = currentTest.Parent;
if (currentTest is ParameterizedMethodSuite)
{
currentTest = currentTest.Parent;
}
isTestSuite = currentTest.IsSuite;
}

return (TestFixture) currentTest;
}

private void UpdateTestDataFromNUnitProperties()
{
foreach (var p in GetTestProperties(PropertyNames.Description))
{
Expand All @@ -217,20 +254,6 @@ private void UpdateTestDataFromAttributes()
x => x.labels.Add(Label.Tag(p))
);
}

var attributes = _test.Method
.GetCustomAttributes<AllureTestCaseAttribute>(true)
.ToList();
attributes.AddRange(
GetTestFixture(_test)
.GetCustomAttributes<AllureTestCaseAttribute>(true)
.ToList()
);

attributes.ForEach(a =>
{
AllureLifecycle.UpdateTestCase(a.UpdateTestResult);
});
}

private void AddConsoleOutputAttachment()
Expand Down Expand Up @@ -280,7 +303,9 @@ public void WrapInStep(Action action, string stepName = "")
}

private string ContainerId => $"tc-{_test.Id}";


[Obsolete("Not intended as a part of the public API")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void SaveOneTimeResultToContext()
{
var currentResult = TestExecutionContext
Expand Down Expand Up @@ -314,7 +339,9 @@ public void SaveOneTimeResultToContext()
);
testFixture.Properties.Set("OneTimeSetUpResult", fixtureResult);
}


[Obsolete("Not intended as a part of the public API")]
[EditorBrowsable(EditorBrowsableState.Never)]
public void AddOneTimeSetupResult()
{
var testFixture = GetTestFixture(
Expand Down
Loading

0 comments on commit 9abc94d

Please sign in to comment.