Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Selective run #389

Closed
wants to merge 13 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Allure.Features/Allure.Features.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@
<PackageReference Include="NUnit3TestAdapter" Version="4.0.0" />
<PackageReference Include="SpecFlow" Version="3.9.74" />
<PackageReference Include="SpecFlow.SharedSteps" Version="3.0.7" />
<PackageReference Include="SpecFlow.Tools.MsBuild.Generation" Version="3.9.8" />
<PackageReference Include="SpecFlow.NUnit" Version="3.9.8" />

<!-- SpecFlow.SharedSteps doesn't work with SpecFlow.Tools.MsBuild.Generation v3.9.58+ -->
<PackageReference Include="SpecFlow.Tools.MsBuild.Generation" Version="3.9.52" />

<PackageReference Include="SpecFlow.NUnit" Version="3.9.52" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Allure.Net.Commons\Allure.Net.Commons.csproj" />
Expand Down
1 change: 1 addition & 0 deletions Allure.Features/allureConfig.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"$schema": "https://raw.githubusercontent.com/allure-framework/allure-csharp/selective-run/Allure.SpecFlowPlugin/Schemas/allureConfig.schema.json",
"allure": {
"title": "5994A3F7-AF84-46AD-9393-000BB45553CC",
"directory": "allure-results",
Expand Down
1 change: 1 addition & 0 deletions Allure.NUnit.Examples/allureConfig.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"$schema": "https://raw.githubusercontent.com/allure-framework/allure-csharp/selective-run/Allure.NUnit/Schemas/allureConfig.schema.json",
"allure": {
"directory": "allure-results",
"links": [
Expand Down
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
22 changes: 22 additions & 0 deletions Allure.NUnit/Schemas/allureConfig.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"allOf": [
{
"$ref": "https://raw.githubusercontent.com/allure-framework/allure-csharp/selective-run/Allure.Net.Commons/Schemas/allureConfig.schema.json"
}
],
"properties": {
"allure": {
"properties": {
"brokenTestData": {
"type": "array",
"description": "A list of exceptions type names. If any of them is thrown, the test is marked as broken. Otherwise, the test state is determined by the inner logic of allure-nunit.",
"items": {
"type": "string",
"description": "The full class name of an exception type.",
"examples": [ "System.Exception" ]
}
}
}
}
}
}
Loading
Loading