Skip to content
Merged
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
8 changes: 4 additions & 4 deletions Allure.NUnit/Core/AllureNUnitHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,7 @@ internal static TestResult CreateTestResult(ITest test)
{
name = ResolveDisplayName(test),
titlePath = EnumerateNamesFromTestFixtureToRoot(test).Reverse().ToList(),
labels = new List<Label>
{
labels = [
Label.Thread(),
Label.Host(),
Label.Language(),
Expand All @@ -107,8 +106,9 @@ internal static TestResult CreateTestResult(ITest test)
Label.TestMethod(test.MethodName),
Label.TestClass(
GetClassName(test.ClassName)
)
}
),
..ModelFunctions.EnumerateEnvironmentLabels(),
]
};
UpdateTestDataFromAllureAttributes(test, testResult);
AddTestParametersFromNUnit(test, testResult);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using NUnit.Framework;
using Allure.Net.Commons.Functions;
using System.Collections.Generic;

namespace Allure.Net.Commons.Tests.FunctionTests.ModelFunctionTests;

class LabelsFromEnvVarsTests
{
Dictionary<string, string> env;

[SetUp]
public void SetUpEnvSource()
{
this.env = [];
ModelFunctions.SetGetEnvironmentVariables(() => this.env);
}

[TearDown]
public void RemoveEnvSource()
{
ModelFunctions.SetGetEnvironmentVariables(null);
}

[Test]
public void ShouldBeEmtyIfNoVarMatches()
{
this.env["foo"] = "bar";
this.env["bazbazbazbazbazbaz"] = "qux";

Assert.That(ModelFunctions.EnumerateEnvironmentLabels(), Is.Empty);
}

[Test]
public void ShouldIncludeLabelFromMatchingVar()
{
this.env["ALLURE_LABEL_foo"] = "bar";

Assert.That(
ModelFunctions.EnumerateEnvironmentLabels(),
Is.EquivalentTo(new Label[]
{
new() { name = "foo", value = "bar" },
}).UsingPropertiesComparer()
);
}

[Test]
public void ShouldIncludeMultipleMatchingLabels()
{
this.env["ALLURE_LABEL_foo"] = "bar";
this.env["ALLURE_LABEL_baz"] = "qux";
this.env["ALLURE_LABEL_qut"] = "qtu";

Assert.That(
ModelFunctions.EnumerateEnvironmentLabels(),
Is.EquivalentTo(new Label[]
{
new() { name = "foo", value = "bar" },
new() { name = "baz", value = "qux" },
new() { name = "qut", value = "qtu" },
}).UsingPropertiesComparer()
);
}

[Test]
public void ShouldPreserveCase()
{
this.env["ALLURE_LABEL_Foo"] = "bar";

Assert.That(
ModelFunctions.EnumerateEnvironmentLabels(),
Is.EquivalentTo(new Label[]
{
new() { name = "Foo", value = "bar" },
}).UsingPropertiesComparer()
);
}

[Test]
public void ShouldIgnoreNullValues()
{
this.env["ALLURE_LABEL_foo"] = null;

Assert.That(ModelFunctions.EnumerateEnvironmentLabels(), Is.Empty);
}

[Test]
public void ShouldIgnoreEmptyValues()
{
this.env["ALLURE_LABEL_foo"] = "";

Assert.That(ModelFunctions.EnumerateEnvironmentLabels(), Is.Empty);
}

[Test]
public void ShouldIgnoreEmptyNames()
{
this.env["ALLURE_LABEL_"] = "bar";

Assert.That(ModelFunctions.EnumerateEnvironmentLabels(), Is.Empty);
}
}
46 changes: 46 additions & 0 deletions Allure.Net.Commons/Functions/ModelFunctions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading;

#nullable enable

Expand Down Expand Up @@ -106,6 +109,35 @@ public static void EnsureSuites(
}
}

/// <summary>
/// Returns a sequence of labels defined by the environment variables in form
/// of <c>ALLURE_LABEL_&lt;name>=&lt;value></c>
/// </summary>
public static IEnumerable<Label> EnumerateEnvironmentLabels()
{
foreach (DictionaryEntry entry in GetEnvironmentVariables())
{
var key = entry.Key as string;
var value = entry.Value as string;
if (ShouldAddEnvVarAsLabel(key, value))
{
var name = key.Substring(ENV_LABEL_PATTERN.Length);
yield return new() { name = name, value = value };
}
}
}

static bool ShouldAddEnvVarAsLabel(
[NotNullWhen(true)] string? name,
[NotNullWhen(true)] string? value
) =>
name is not null
&& name.Length > ENV_LABEL_PATTERN.Length
&& name.StartsWith(ENV_LABEL_PATTERN)
&& !string.IsNullOrEmpty(value);

const string ENV_LABEL_PATTERN = "ALLURE_LABEL_";

static bool IsSuiteLabel(Label label) => label.name switch
{
LabelName.PARENT_SUITE or LabelName.SUITE or LabelName.SUB_SUITE => true,
Expand All @@ -123,4 +155,18 @@ static IEnumerable<string> GetExceptionClassChain(Exception e)
yield return intetrface.FullName;
}
}

#region For testing

static IDictionary GetEnvironmentVariables() =>
(GetEnvironmentVariablesBox.Value
?? Environment.GetEnvironmentVariables).Invoke();

internal static void SetGetEnvironmentVariables(Func<IDictionary>? getEnvVars) =>
GetEnvironmentVariablesBox.Value = getEnvVars;

// To decouple from Environment.GetEnvironmentVariable
static AsyncLocal<Func<IDictionary>?> GetEnvironmentVariablesBox { get; set; } = new();

#endregion
}
14 changes: 14 additions & 0 deletions Allure.Net.Commons/Internal/NotNullWhen.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace System.Diagnostics.CodeAnalysis;

/// <summary>
/// This attribute hints the compiler that the parameter it's applied to
/// is not null if the method returns a specified value.
/// It's not included in netstandard2.0 but can be define it the project's code.
/// </summary>
/// <param name="returnValue">
/// A return value that indicated the argument is not null
/// </param>
[AttributeUsage(AttributeTargets.Parameter)]
internal sealed class NotNullWhenAttribute(bool returnValue) : Attribute {
public bool ReturnValue { get; } = returnValue;
}
11 changes: 6 additions & 5 deletions Allure.Reqnroll/Functions/MappingFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ StepInfo stepInfo
".txt"
));
}

var dataTable = stepInfo.Table;
if (dataTable is not null)
{
Expand Down Expand Up @@ -436,10 +436,11 @@ static List<Parameter> GetParameters(ScenarioInfo scenarioInfo)
static List<Label> InitializeTestLabels(
FeatureInfo featureInfo,
IEnumerable<Label>? scenarioLabels
) =>
CreateDefaultLabels(featureInfo)
.Concat(scenarioLabels ?? Enumerable.Empty<Label>())
.ToList();
) => [
.. CreateDefaultLabels(featureInfo),
.. ModelFunctions.EnumerateEnvironmentLabels(),
.. scenarioLabels ?? [],
];

static IEnumerable<Label> CreateDefaultLabels(FeatureInfo featureInfo)
{
Expand Down
10 changes: 5 additions & 5 deletions Allure.SpecFlow/PluginHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,7 @@ internal static void StartTestCase(
name = title,
description = scenarioInfo.Description,
titlePath = CreateTitlePath(testRunnerManager, featureInfo),
labels = new List<Label>
{
labels = [
Label.Thread(),
string.IsNullOrWhiteSpace(
AllureLifecycle.Instance.AllureConfiguration.Title
Expand All @@ -105,9 +104,10 @@ internal static void StartTestCase(
),
Label.Language(),
Label.Framework("SpecFlow"),
Label.Feature(featureInfo.Title)
}
.Union(labels).ToList(),
Label.Feature(featureInfo.Title),
..ModelFunctions.EnumerateEnvironmentLabels(),
..labels,
],
links = links,
parameters = parameters
};
Expand Down
6 changes: 3 additions & 3 deletions Allure.Xunit/AllureXunitHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@
var className =
string.IsNullOrEmpty(@namespace)
? testClass.Name
: testClass.Name?.Substring(@namespace.Length + 1);

Check warning on line 111 in Allure.Xunit/AllureXunitHelper.cs

View workflow job for this annotation

GitHub Actions / test

Dereference of a possibly null reference.

Check warning on line 111 in Allure.Xunit/AllureXunitHelper.cs

View workflow job for this annotation

GitHub Actions / test

Dereference of a possibly null reference.

AllureLifecycle.Instance.UpdateTestCase(
testResult => ModelFunctions.EnsureSuites(
Expand Down Expand Up @@ -154,16 +154,16 @@
{
name = BuildName(testCase),
titlePath = IdFunctions.CreateTitlePath(testClass),
labels = new()
{
labels = [
Label.Thread(),
Label.Host(),
Label.Language(),
Label.Framework("xUnit.net"),
Label.TestClass(testMethod.TestClass.Class.Name),
Label.TestMethod(testCase.TestMethod.Method.Name),
Label.Package(testMethod.TestClass.Class.Name),
}
..ModelFunctions.EnumerateEnvironmentLabels(),
]
};
SetTestResultIdentifiers(testCase, displayName, testResult);
UpdateTestDataFromAttributes(testResult, testMethod);
Expand Down
Loading