diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index cc09f513..5acd609e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -28,10 +28,10 @@ jobs: run: dotnet restore ${{ env.SOLUTION_PATH }} --packages ${{ env.RESTORE_OUTPUT_PATH }} - name: 'Build project using dotnet' - run: dotnet build ${{ env.SOLUTION_PATH }} --no-restore --configuration ${{ env.BUILD_CONFIGURATION }} + run: dotnet build ${{ env.SOLUTION_PATH }} --no-restore --configuration ${{ env.BUILD_CONFIGURATION }} -p:ContinuousIntegrationBuild=true - name: 'Pack project' - run: dotnet pack ${{ env.SOLUTION_PATH }} --no-restore --no-build --configuration ${{ env.BUILD_CONFIGURATION }} --include-symbols --include-source -p:PackageOutputPath=${{ env.PACKAGE_OUTPUT_PATH }} + run: dotnet pack ${{ env.SOLUTION_PATH }} --no-restore --no-build --configuration ${{ env.BUILD_CONFIGURATION }} -p:PackageOutputPath=${{ env.PACKAGE_OUTPUT_PATH }} - name: 'NuGet publish' run: | diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index adab4ba5..8aa650eb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -45,14 +45,8 @@ jobs: git config --global user.email qameta-ci@qameta.io - name: "Set release version" run: | - sed -i -e '//,/<\/PropertyGroup>/ s|[0-9a-zA-Z.|-]*|${{ env.release_version }}|g' ./Allure.Net.Commons/Allure.Net.Commons.csproj - cat ./Allure.Net.Commons/Allure.Net.Commons.csproj - sed -i -e '//,/<\/PropertyGroup>/ s|[0-9a-zA-Z.|-]*|${{ env.release_version }}|g' ./Allure.SpecFlowPlugin/Allure.SpecFlowPlugin.csproj - cat ./Allure.SpecFlowPlugin/Allure.SpecFlowPlugin.csproj - sed -i -e '//,/<\/PropertyGroup>/ s|[0-9a-zA-Z.|-]*|${{ env.release_version }}|g' ./Allure.XUnit/Allure.XUnit.csproj - cat ./Allure.XUnit/Allure.XUnit.csproj - sed -i -e '//,/<\/PropertyGroup>/ s|[0-9a-zA-Z.|-]*|${{ env.release_version }}|g' ./Allure.NUnit/Allure.NUnit.csproj - cat ./Allure.NUnit/Allure.NUnit.csproj + sed -i -e '//,/<\/PropertyGroup>/ s|[0-9a-zA-Z.|-]*|${{ env.release_version }}|g' ./Directory.Build.props + cat ./Directory.Build.props - name: "Commit release version and create tag" run: | git commit -am "release ${{ env.release_version }}" @@ -60,14 +54,8 @@ jobs: git push origin ${{ env.release_version }} - name: "Set next development version" run: | - sed -i -e '//,/<\/PropertyGroup>/ s|[0-9a-zA-Z.|-]*|${{ inputs.nextVersion }}-SNAPSHOT|g' ./Allure.Net.Commons/Allure.Net.Commons.csproj - cat ./Allure.Net.Commons/Allure.Net.Commons.csproj - sed -i -e '//,/<\/PropertyGroup>/ s|[0-9a-zA-Z.|-]*|${{ inputs.nextVersion }}-SNAPSHOT|g' ./Allure.SpecFlowPlugin/Allure.SpecFlowPlugin.csproj - cat ./Allure.SpecFlowPlugin/Allure.SpecFlowPlugin.csproj - sed -i -e '//,/<\/PropertyGroup>/ s|[0-9a-zA-Z.|-]*|${{ inputs.nextVersion }}-SNAPSHOT|g' ./Allure.XUnit/Allure.XUnit.csproj - cat ./Allure.XUnit/Allure.XUnit.csproj - sed -i -e '//,/<\/PropertyGroup>/ s|[0-9a-zA-Z.|-]*|${{ inputs.nextVersion }}-SNAPSHOT|g' ./Allure.NUnit/Allure.NUnit.csproj - cat ./Allure.NUnit/Allure.NUnit.csproj + sed -i -e '//,/<\/PropertyGroup>/ s|[0-9a-zA-Z.|-]*|${{ inputs.nextVersion }}-SNAPSHOT|g' ./Directory.Build.props + cat ./Directory.Build.props - name: "Commit next development version and push it" run: | git commit -am "set next development version ${{ inputs.nextVersion }}" diff --git a/Allure.Features/Allure.Features.csproj b/Allure.Features/Allure.Features.csproj index 67af0001..dfea952d 100644 --- a/Allure.Features/Allure.Features.csproj +++ b/Allure.Features/Allure.Features.csproj @@ -1,33 +1,31 @@  - - netcoreapp3.1 - 11 - false - bin - + + netcoreapp3.1 + bin + - - - - - - - - - - - - - - - - - Always - - - - - PreserveNewest - - + + + + + + + + + + + + + + + + + Always + + + + + PreserveNewest + + diff --git a/Allure.NUnit.Examples/Allure.NUnit.Examples.csproj b/Allure.NUnit.Examples/Allure.NUnit.Examples.csproj index 370c9fb1..4b40b417 100644 --- a/Allure.NUnit.Examples/Allure.NUnit.Examples.csproj +++ b/Allure.NUnit.Examples/Allure.NUnit.Examples.csproj @@ -1,30 +1,28 @@  - - net6.0 - 11 - false - Library - + + net6.0 + Library + - - - - - + + + + + - - - + + + - - - Always - - - - Always - - + + + Always + + + + Always + + diff --git a/Allure.NUnit/Allure.NUnit.csproj b/Allure.NUnit/Allure.NUnit.csproj index 2fce0102..f91b90aa 100644 --- a/Allure.NUnit/Allure.NUnit.csproj +++ b/Allure.NUnit/Allure.NUnit.csproj @@ -2,33 +2,20 @@ netstandard2.0 - 11 - 2.10-SNAPSHOT - false - Qameta Software + true Nick Chursin NUnit attributes extenstions for Allure Allure.NUnit Allure.NUnit NUnit.Allure https://www.nuget.org/packages/Allure.NUnit - https://github.com/allure-framework/allure-csharp allure nunit LICENSE.md README.md Allure-N-Color.png - true - true - true - snupkg - - - - - diff --git a/Allure.Net.Commons.Tests/Allure.Net.Commons.Tests.csproj b/Allure.Net.Commons.Tests/Allure.Net.Commons.Tests.csproj index 88452e2a..0a31f921 100644 --- a/Allure.Net.Commons.Tests/Allure.Net.Commons.Tests.csproj +++ b/Allure.Net.Commons.Tests/Allure.Net.Commons.Tests.csproj @@ -1,33 +1,31 @@  - - net6.0 - false - 11 - + + net6.0 + - - - - - - - + + + + + + + - - - + + + - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + diff --git a/Allure.Net.Commons/Allure.Net.Commons.csproj b/Allure.Net.Commons/Allure.Net.Commons.csproj index f988dae6..8dcc65ca 100644 --- a/Allure.Net.Commons/Allure.Net.Commons.csproj +++ b/Allure.Net.Commons/Allure.Net.Commons.csproj @@ -2,40 +2,21 @@ netstandard2.0 - 11 - 2.10-SNAPSHOT - false + true Alexander Bakanov, Nikolay Laptev - Qameta Software - .NET implementation of Allure java-commons + Provides common facilities to build allure integrations for .NET test frameworks https://www.nuget.org/packages/Allure.Net.Commons README.md - https://github.com/allure-framework/allure-csharp - git allure Allure-Color.png - False - False - key.snk - default - true - true - snupkg - - - - - - - - + diff --git a/Allure.Net.Commons/AllureLifecycle.cs b/Allure.Net.Commons/AllureLifecycle.cs index 0f29f05c..f2f41514 100644 --- a/Allure.Net.Commons/AllureLifecycle.cs +++ b/Allure.Net.Commons/AllureLifecycle.cs @@ -4,7 +4,6 @@ using System.ComponentModel; using System.IO; using System.Linq; -using System.Runtime.CompilerServices; using System.Threading; using Allure.Net.Commons.Configuration; using Allure.Net.Commons.Storage; @@ -14,8 +13,6 @@ #nullable enable -[assembly: InternalsVisibleTo("Allure.Net.Commons.Tests")] - namespace Allure.Net.Commons; /// diff --git a/Allure.Net.Commons/Internal/AssemblyAttributes.cs b/Allure.Net.Commons/Internal/AssemblyAttributes.cs new file mode 100644 index 00000000..90a34646 --- /dev/null +++ b/Allure.Net.Commons/Internal/AssemblyAttributes.cs @@ -0,0 +1,4 @@ +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Allure.Net.Commons.Tests")] +[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] diff --git a/Allure.Net.Commons/Writer/FileSystemResultsWriter.cs b/Allure.Net.Commons/Writer/FileSystemResultsWriter.cs index 05e8f876..9c671282 100644 --- a/Allure.Net.Commons/Writer/FileSystemResultsWriter.cs +++ b/Allure.Net.Commons/Writer/FileSystemResultsWriter.cs @@ -1,15 +1,11 @@ using System; using System.IO; -using System.Runtime.CompilerServices; using System.Threading; using Allure.Net.Commons.Configuration; using Allure.Net.Commons.Helpers; using Newtonsoft.Json; using Newtonsoft.Json.Converters; -[assembly: InternalsVisibleTo("Allure.Net.Commons.Tests")] -[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")] - namespace Allure.Net.Commons.Writer { internal class FileSystemResultsWriter : IAllureResultsWriter diff --git a/Allure.SpecFlowPlugin.Tests/Allure.SpecFlowPlugin.Tests.csproj b/Allure.SpecFlowPlugin.Tests/Allure.SpecFlowPlugin.Tests.csproj index 7e56a367..4bf8a2d1 100644 --- a/Allure.SpecFlowPlugin.Tests/Allure.SpecFlowPlugin.Tests.csproj +++ b/Allure.SpecFlowPlugin.Tests/Allure.SpecFlowPlugin.Tests.csproj @@ -1,31 +1,29 @@  - - netcoreapp3.1 - 11 - false - + + netcoreapp3.1 + - - - - - + + + + + - - - + + + - - - PreserveNewest - - - PreserveNewest - - - PreserveNewest - - + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + diff --git a/Allure.SpecFlowPlugin/Allure.SpecFlowPlugin.csproj b/Allure.SpecFlowPlugin/Allure.SpecFlowPlugin.csproj index 8a2f0ab4..e664a2b6 100644 --- a/Allure.SpecFlowPlugin/Allure.SpecFlowPlugin.csproj +++ b/Allure.SpecFlowPlugin/Allure.SpecFlowPlugin.csproj @@ -2,36 +2,25 @@ net462;netstandard2.0 - 11 + true enable Allure.SpecFlow - 2.10-SNAPSHOT Alexander Bakanov - Qameta Software Generates Allure report result files for SpecFlow test run https://www.nuget.org/packages/Allure.SpecFlow README.md Allure-SF-Color.png - https://github.com/allure-framework/allure-csharp specflow allure - false - true - true - snupkg - - - - - true - / + true + / diff --git a/Allure.XUnit.Examples/Allure.XUnit.Examples.csproj b/Allure.XUnit.Examples/Allure.XUnit.Examples.csproj index 13cf3e3a..9dd2e320 100644 --- a/Allure.XUnit.Examples/Allure.XUnit.Examples.csproj +++ b/Allure.XUnit.Examples/Allure.XUnit.Examples.csproj @@ -1,32 +1,31 @@ - + - false net6.0 - 11 - all - runtime; build; native; contentfiles; analyzers; buildtransitive + all + runtime; build; native; contentfiles; analyzers; buildtransitive - - all - runtime; build; native; contentfiles; analyzers; buildtransitive + + all + runtime; build; native; contentfiles; analyzers; buildtransitive - - Always - + + Always + - + + diff --git a/Allure.XUnit.Examples/allureConfig.json b/Allure.XUnit.Examples/allureConfig.json index 9f30479d..c2ef3daf 100644 --- a/Allure.XUnit.Examples/allureConfig.json +++ b/Allure.XUnit.Examples/allureConfig.json @@ -4,6 +4,7 @@ "links": [ "https://example.org/{issue}", "https://example.org/{tms}" - ] + ], + "xunitRunnerReporter": "auto" } } diff --git a/Allure.XUnit.Reporters/Allure.XUnit.Reporters.csproj b/Allure.XUnit.Reporters/Allure.XUnit.Reporters.csproj new file mode 100644 index 00000000..65851e41 --- /dev/null +++ b/Allure.XUnit.Reporters/Allure.XUnit.Reporters.csproj @@ -0,0 +1,14 @@ + + + + Allure.XUnit.reporters + netcoreapp2.0;netstandard2.1;net5.0;net6.0 + enable + + + + + + + + diff --git a/Allure.XUnit.Reporters/AllureRunnerReporter.cs b/Allure.XUnit.Reporters/AllureRunnerReporter.cs new file mode 100644 index 00000000..4c2a12d8 --- /dev/null +++ b/Allure.XUnit.Reporters/AllureRunnerReporter.cs @@ -0,0 +1,20 @@ +using Xunit; +using Xunit.Abstractions; + +#nullable enable + +namespace Allure.XUnit.Reporters +{ + public class AllureRunnerReporter : IRunnerReporter + { + public string Description { get; } + = "Creates allure input files for xunit tests"; + + public bool IsEnvironmentallyEnabled { get; } = true; + + public string RunnerSwitch { get; } = "allure"; + + public IMessageSink CreateMessageHandler(IRunnerLogger logger) => + AllureXunitFacade.CreateAllureXunitMessageHandler(logger); + } +} \ No newline at end of file diff --git a/Allure.XUnit/Allure.XUnit.csproj b/Allure.XUnit/Allure.XUnit.csproj index 298c724e..51e26bed 100644 --- a/Allure.XUnit/Allure.XUnit.csproj +++ b/Allure.XUnit/Allure.XUnit.csproj @@ -2,29 +2,24 @@ netcoreapp2.0;netstandard2.1;net5.0;net6.0 - 11 true - Qameta Software - 2.10-SNAPSHOT Allure.XUnit Shumakov Ivan Allure.XUnit Allure-X-Color.png https://www.nuget.org/packages/Allure.XUnit README.md - https://github.com/allure-framework/allure-csharp allure xunit - false - true - true - true - snupkg + + + + $(TargetsForTfmSpecificBuildOutput);PackAllureXunitReportersFiles + - - + @@ -37,10 +32,9 @@ - - + @@ -50,4 +44,11 @@ + + + + + + + diff --git a/Allure.XUnit/AllureMessageSink.cs b/Allure.XUnit/AllureMessageSink.cs index 2344cb32..90d3b5c2 100644 --- a/Allure.XUnit/AllureMessageSink.cs +++ b/Allure.XUnit/AllureMessageSink.cs @@ -11,16 +11,14 @@ namespace Allure.XUnit { - public class AllureMessageSink : TestMessageSink + public class AllureMessageSink : + DefaultRunnerReporterWithTypesMessageHandler { - readonly IRunnerLogger logger; - readonly ConcurrentDictionary allureTestData - = new(); + readonly ConcurrentDictionary + allureTestData = new(); - public AllureMessageSink(IRunnerLogger logger) + public AllureMessageSink(IRunnerLogger logger) : base(logger) { - this.logger = logger; - this.Runner.TestAssemblyExecutionStartingEvent += this.OnTestAssemblyExecutionStarting; @@ -31,34 +29,8 @@ public AllureMessageSink(IRunnerLogger logger) this.Execution.TestPassedEvent += this.OnTestPassed; this.Execution.TestSkippedEvent += this.OnTestSkipped; this.Execution.TestFinishedEvent += this.OnTestFinished; - } - public override bool OnMessageWithTypes( - IMessageSinkMessage message, - HashSet messageTypes - ) - { - try - { - this.logger.LogMessage(message.GetType().Name); - return base.OnMessageWithTypes(message, messageTypes); - } - catch (Exception e) - { - if (message is ITestCaseMessage testCaseMessage) - { - this.logger.LogError( - "Error during execution of {0}: {1}", - testCaseMessage.TestCase.DisplayName, - e - ); - } - else - { - this.logger.LogError(e.ToString()); - } - return false; - } + CurrentSink ??= this; } void OnTestAssemblyExecutionStarting( @@ -198,10 +170,12 @@ void LogUnreportedTheoryArgs(string testName) message += ". You may try to compile the project in debug mode " + "as a workaround"; #endif - this.logger.LogWarning(message); + this.Logger.LogWarning(message); } static bool IsStaticTestMethod(ITestMethodMessage message) => message.TestMethod.Method.IsStatic; + + public static AllureMessageSink? CurrentSink { get; private set; } } } \ No newline at end of file diff --git a/Allure.XUnit/AllureRunnerReporter.cs b/Allure.XUnit/AllureRunnerReporter.cs deleted file mode 100644 index 3d336582..00000000 --- a/Allure.XUnit/AllureRunnerReporter.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Xunit; -using Xunit.Abstractions; - -namespace Allure.XUnit -{ - public class AllureRunnerReporter : IRunnerReporter - { - public string Description { get; } = "allure-xunit"; - - public bool IsEnvironmentallyEnabled { get; } = true; - - public string RunnerSwitch { get; } = "allure"; - - public IMessageSink CreateMessageHandler(IRunnerLogger logger) - { - AllureXunitPatcher.PatchXunit(logger); - var sink = new AllureMessageSink(logger); - CurrentSink ??= sink; - return sink; - } - - internal static AllureMessageSink CurrentSink { get; private set; } - } -} \ No newline at end of file diff --git a/Allure.XUnit/AllureXunitConfiguration.cs b/Allure.XUnit/AllureXunitConfiguration.cs new file mode 100644 index 00000000..b3409e17 --- /dev/null +++ b/Allure.XUnit/AllureXunitConfiguration.cs @@ -0,0 +1,41 @@ +using Allure.Net.Commons; +using Allure.Net.Commons.Configuration; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.IO; + +#nullable enable + +namespace Allure.XUnit +{ + internal class AllureXunitConfiguration : AllureConfiguration + { + public string XunitRunnerReporter { get; set; } = "auto"; + + [JsonConstructor] + protected AllureXunitConfiguration( + string title, + string directory, + HashSet links + ) : base(title, directory, links) + { + } + + public static AllureXunitConfiguration CurrentConfig + { + get => currentConfig.Value; + } + + static readonly Lazy currentConfig + = new(ParseCurrentConfig); + + static AllureXunitConfiguration ParseCurrentConfig() => JObject.Parse( + AllureLifecycle.Instance.JsonConfiguration + )["allure"]?.ToObject() + ?? throw new FileNotFoundException( + "allureConfig.json not found" + ); + } +} diff --git a/Allure.XUnit/AllureXunitFacade.cs b/Allure.XUnit/AllureXunitFacade.cs new file mode 100644 index 00000000..2e1793cb --- /dev/null +++ b/Allure.XUnit/AllureXunitFacade.cs @@ -0,0 +1,128 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Xunit; +using Xunit.Abstractions; + +#nullable enable + +namespace Allure.XUnit +{ + public static class AllureXunitFacade + { + public static IMessageSink CreateAllureXunitMessageHandler( + IRunnerLogger logger + ) + { + AllureXunitPatcher.PatchXunit(logger); + var secondReporter = ResolveSecondReporter(); + var (startupMessage, sink) = ResolveMessageAndSink( + new AllureMessageSink(logger), + secondReporter, + logger + ); + logger.LogImportantMessage(startupMessage); + return sink; + } + + static IRunnerReporter? ResolveSecondReporter() => + AllureXunitConfiguration.CurrentConfig.XunitRunnerReporter switch + { + "none" => null, + "auto" => ResolveAutoReporter(), + string reporterName => ResolveExplicitReporter(reporterName) + }; + + static (string, IMessageSink) ResolveMessageAndSink( + AllureMessageSink allureSink, + IRunnerReporter? secondReporter, + IRunnerLogger logger + ) => + secondReporter is null ? ( + ALLURE_REPORTER_ON_MSG, + allureSink + ) : ( + $"{ALLURE_REPORTER_ON_MSG}. " + + $"Secondary reporter: {secondReporter.RunnerSwitch}", + new ComposedMessageSink( + allureSink, + secondReporter.CreateMessageHandler(logger) + ) + ); + + static IRunnerReporter? ResolveAutoReporter() => + ( + from reporter in GetReporters() + where reporter.IsEnvironmentallyEnabled + select reporter + ).FirstOrDefault(); + + static IRunnerReporter ResolveExplicitReporter(string reporterName) + { + var reporterType = Type.GetType(reporterName); + var resolvedReporter = TryCreateReporterByType(reporterType); + resolvedReporter ??= TryCreateReporterByName(reporterName); + if (resolvedReporter is null) + { + throw new InvalidOperationException( + $"Can't load the {reporterName} reporter" + ); + } + return resolvedReporter; + } + + static IRunnerReporter? TryCreateReporterByType(Type? reporterType) => + reporterType is null + ? null + : (Activator.CreateInstance(reporterType) as IRunnerReporter); + + static IRunnerReporter? TryCreateReporterByName(string reporterName) => + ( + from reporter in GetReporters() + where StringComparer.OrdinalIgnoreCase.Equals( + reporter.RunnerSwitch, + reporterName + ) + select reporter + ).FirstOrDefault(); + + static IEnumerable GetReporters() => + from assembly in AppDomain.CurrentDomain.GetAssemblies() + where IsPotentialReporterAssembly(assembly) + from type in assembly.GetTypes() + where IsReporterType(type) + select Activator.CreateInstance(type) as IRunnerReporter; + + /// + /// Save some time skipping core assemblies. Allure.* assemblies are + /// skipped as well, because there is only one reporter there and it + /// has already been picked at the time this code is run. + /// + static bool IsPotentialReporterAssembly(Assembly assembly) => + assembly?.FullName is not null + && + ASSEMBLY_PREFIXES_TO_SKIP.All( + a => !assembly.FullName.StartsWith( + a, + StringComparison.OrdinalIgnoreCase + ) + ); + + static bool IsReporterType(Type type) => + type.GetInterfaces().Contains(typeof(IRunnerReporter)) + && + !type.IsAbstract + && + !type.IsGenericTypeDefinition; + + static readonly string[] ASSEMBLY_PREFIXES_TO_SKIP = new[] + { + "System.", + "Microsoft.", + "Allure." + }; + + const string ALLURE_REPORTER_ON_MSG = "Allure reporter enabled"; + } +} diff --git a/Allure.XUnit/AllureXunitPatcher.cs b/Allure.XUnit/AllureXunitPatcher.cs index 889283fb..cd370fb2 100644 --- a/Allure.XUnit/AllureXunitPatcher.cs +++ b/Allure.XUnit/AllureXunitPatcher.cs @@ -77,7 +77,7 @@ static void OnTestRunnerCreated( object[] testMethodArguments ) { - if (AllureRunnerReporter.CurrentSink is null) + if (AllureMessageSink.CurrentSink is null) { logger.LogWarning( "Unable to get current message sink from the test " + @@ -87,7 +87,7 @@ object[] testMethodArguments } else { - AllureRunnerReporter.CurrentSink.OnTestArgumentsCreated( + AllureMessageSink.CurrentSink.OnTestArgumentsCreated( test, testMethodArguments ); diff --git a/Allure.XUnit/ComposedMessageSink.cs b/Allure.XUnit/ComposedMessageSink.cs new file mode 100644 index 00000000..66410aff --- /dev/null +++ b/Allure.XUnit/ComposedMessageSink.cs @@ -0,0 +1,51 @@ +using System.Collections.Generic; +using Xunit; +using Xunit.Abstractions; + +namespace Allure.XUnit +{ + internal class ComposedMessageSink : IMessageSink, IMessageSinkWithTypes + { + readonly IMessageSink[] sinks; + + public ComposedMessageSink(params IMessageSink[] sinks) + { + this.sinks = sinks; + } + + public void Dispose() { } + + public bool OnMessage(IMessageSinkMessage message) + { + foreach (var sink in sinks) + { + if (!sink.OnMessage(message)) + { + return false; + } + } + return true; + } + + public bool OnMessageWithTypes(IMessageSinkMessage message, HashSet messageTypes) + { + foreach(var sink in this.sinks) + { + if (!DispatchTypedSinkMessage(sink, message, messageTypes)) + { + return false; + } + } + return true; + } + + static bool DispatchTypedSinkMessage( + IMessageSink sink, + IMessageSinkMessage message, + HashSet messageTypes + ) => + sink is IMessageSinkWithTypes typedSink + ? typedSink.OnMessageWithTypes(message, messageTypes) + : sink.OnMessage(message); + } +} diff --git a/Allure.XUnit/README.md b/Allure.XUnit/README.md index ce5aee1e..58082e47 100644 --- a/Allure.XUnit/README.md +++ b/Allure.XUnit/README.md @@ -2,12 +2,110 @@ [![Nuget](https://img.shields.io/nuget/v/Allure.XUnit)](https://www.nuget.org/packages/Allure.XUnit/) -Allure.XUnit is library for display xunit tests in Allure report. +Allure.XUnit is a library for display xunit tests in Allure report. + +Allure.XUnit supports .NET Core 2.0 or later, and any .NET runtime compatible +with .NET Standard 2.1. + +## How to run + +Install the Allure.XUnit package and create `allureConfig.json`. Here is the +basic content of the config: + +```json +{ + "allure": {} +} +``` + +Make sure the config is copied to the output directory: + + - In Visual Studio select the file and set the following properties: + - Build Action: Content + - Copy to Output Directory: Always/Copy if newer + OR + - In the `.csproj` file make sure the following entry exists: + ```xml + + + Always + + + ``` + +Then, run the tests as usual. In many cases allure should start automatically. +The result files are created in the `allure-results` directory in the +target directory. +If that didn't happen, check out the `Running tests in a CI pipeline` section. + +### Running tests in a CI pipeline + +There might be a chance another xunit reporter kicks in disabling allure. This +typically happens in a CI pipeline when a pipeline-specific reporter detects +the CI environment and signals xunit that it's ready to be used. Xunit's +reporter pick is unreliable in such a case. + +If that happens, you should explicitly tell xunit to use the `allure` reporter. +How exactly - depends on what runner you use. For the most popular one - +`xunit.runner.visualstudio` - you either specify it via the CLI argument: + +``` +dotnet test -- RunConfiguration.ReporterSwitch=allure +``` + +Or use a `.runsettings` file: + +```xml + + + + allure + + +``` + +Now pass the file to `dotnet test`: + +``` +dotnet test -s +``` + +Or specify its path using your IDE. + +By default Allure.XUnit tries to use additional environmentally enabled +reporter (if any), so your tests are reported both to allure and, say, +TeamCity. Due to how xunit configuration works, that behavior occures +regardless of xunit's `NoAutoReporters` setting. If you want to disable this +behavior, check out the `Configuring a secondary reporter` section. + +### Configuring a secondary reporter + +Use the `xunitRunnerReporter` property of `allureConfig.json` to control +an additional reporter used by Allure.XUnit: + +```json +{ + "allure": { + "xunitRunnerReporter": "auto|none||" + } +} +``` + +We support the following values: + - `auto` - default value. Allure.XUnit uses the first environmentally + enabled reporter it finds. + - `none` - use this value to disable an additional reporter. + - `` - Allure.XUnit looks for the reporter with the specified + runner switch. If such reporter exists, it's used. Otherwise, the error is + thrown. + - `` - the assembly qualified class name is used to find the + reporter's class. If no such class can be found, the error is thrown. -Allure.XUnit supports .NET Core 2.0 and later. ## Attributes: +The following attributes are at your disposal: + * AllureDescription * AllureParentSuite * AllureFeature @@ -74,7 +172,9 @@ Use `AllureStepAttribute`, `AllureBeforeAttribute`, `AllureAfterAttribute` See [Examples](../Allure.XUnit.Examples/ExampleStepAttributes.cs). ### Allure.XUnit.StepExtensions deprecation -There is no more need to use separate Allure.XUnit.StepExtensions package - you can simply remove it from dependencies and use attributes from [Allure.XUnit.Attributes.Steps namespace](Attributes/Steps) directly. +There is no more need to use separate Allure.XUnit.StepExtensions package. You +should remove it from dependencies and use attributes from +[Allure.XUnit.Attributes.Steps namespace](Attributes/Steps) directly. ```c# using Allure.XUnit.Attributes.Steps; @@ -91,46 +191,14 @@ using Allure.XUnit.Attributes.Steps; ## Attachments Use [`AllureAttachments`](AllureAttachments.cs) class with its methods. (AttachmentAttribute coming soon) -## Running - -Just run `dotnet test`. - -`allure-results` directory with result appears after running tests in the target directory. - -## Known issues - -### Incompatibility with other runner reporters ([#368]) - -Allure-xunit is implemented as an xunit runner reporter, hence it's incompatible -with other runner reporters such as `teamcity`, `json` or `verbose` (from -[xunit.runner.reporters]). Only one reporter could be active at a time. - -If you have other reporter active but want to use allure-xunit, you have to -manually enable the `allure` reporter by running `dotnet test` with the -`RunConfiguration.ReporterSwitch` run setting set to `allure`: +## Known issues and limitations -```shell -dotnet test -- RunConfiguration.ReporterSwitch=allure -``` - -Alternatively, you may add this setting to your `.runsettings` file: - -```xml - - - - allure - - -``` - -Use this file from CLI: +### allureConfig.json is required even if no config properties are present -```shell -dotnet test -s -``` +The configuration file must be present in the output directory. Allure.XUnit +throws otherwise. This requirement will be lifted in the near future. -Or apply it via your IDE. +Here is the issue to track the progress: [#381]. ### Arguments of some theories might be unreported @@ -144,6 +212,5 @@ workaround until we come up with a solution. See [Examples](../Allure.XUnit.Examples). -[xunit.runner.reporters]: https://www.nuget.org/packages/xunit.runner.reporters/ -[#368]: https://github.com/allure-framework/allure-csharp/issues/368 [#369]: https://github.com/allure-framework/allure-csharp/issues/369 +[#381]: https://github.com/allure-framework/allure-csharp/issues/381 diff --git a/Directory.Build.props b/Directory.Build.props new file mode 100644 index 00000000..9e53f14b --- /dev/null +++ b/Directory.Build.props @@ -0,0 +1,38 @@ + + + + 2.10-SNAPSHOT + Qameta Software + https://github.com/allure-framework/allure-csharp + git + + + + + 11 + false + false + true + false + + + + + false + $(MSBuildThisFileDirectory)key.snk + + + + + true + portable + true + snupkg + true + + + + + + + \ No newline at end of file diff --git a/allure-csharp.sln b/allure-csharp.sln index e500376e..a6d071ac 100644 --- a/allure-csharp.sln +++ b/allure-csharp.sln @@ -1,13 +1,16 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26730.12 +# Visual Studio Version 17 +VisualStudioVersion = 17.7.34024.191 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Allure.Net.Commons", "Allure.Net.Commons\Allure.Net.Commons.csproj", "{C84000AF-0B78-4E87-B99B-064E15C601C7}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Allure.Net.Commons.Tests", "Allure.Net.Commons.Tests\Allure.Net.Commons.Tests.csproj", "{2E3DF5C2-8A38-4A03-86D7-8D463C917E47}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "commons", "commons", "{E0035B29-14C0-4270-B11F-DD2544D37FF6}" + ProjectSection(SolutionItems) = preProject + Directory.Build.props = Directory.Build.props + EndProjectSection EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "specflow", "specflow", "{9AC8581F-7E9E-46B1-A30A-5A815966C820}" EndProject @@ -15,19 +18,21 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Allure.SpecFlowPlugin", "Al EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Allure.SpecFlowPlugin.Tests", "Allure.SpecFlowPlugin.Tests\Allure.SpecFlowPlugin.Tests.csproj", "{69C462C3-E955-4B0C-9F1F-2ED5AE1BF270}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Allure.Features", "Allure.Features\Allure.Features.csproj", "{9F2B97FF-6798-4A69-9520-CE3491396F3F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Allure.Features", "Allure.Features\Allure.Features.csproj", "{9F2B97FF-6798-4A69-9520-CE3491396F3F}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "allure-xunit", "allure-xunit", "{138A76FC-B163-423C-8FF8-D374F1C7EC2F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Allure.XUnit", "Allure.XUnit\Allure.XUnit.csproj", "{D278CE6B-F3D1-4FEF-BE5F-5AC6F6C53879}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Allure.XUnit", "Allure.XUnit\Allure.XUnit.csproj", "{D278CE6B-F3D1-4FEF-BE5F-5AC6F6C53879}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Allure.XUnit.Examples", "Allure.XUnit.Examples\Allure.XUnit.Examples.csproj", "{38CF463E-F564-477D-A853-407F0648E0DD}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Allure.XUnit.Examples", "Allure.XUnit.Examples\Allure.XUnit.Examples.csproj", "{38CF463E-F564-477D-A853-407F0648E0DD}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "allure-nunit", "allure-nunit", "{D0D75FDF-4884-4AC1-868F-B3F248CB74ED}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Allure.NUnit", "Allure.NUnit\Allure.NUnit.csproj", "{81F804C5-C437-4079-9731-97C6A2A86C48}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Allure.NUnit", "Allure.NUnit\Allure.NUnit.csproj", "{81F804C5-C437-4079-9731-97C6A2A86C48}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Allure.NUnit.Examples", "Allure.NUnit.Examples\Allure.NUnit.Examples.csproj", "{77893A8D-4313-4211-AFF1-642E866A07C7}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Allure.NUnit.Examples", "Allure.NUnit.Examples\Allure.NUnit.Examples.csproj", "{77893A8D-4313-4211-AFF1-642E866A07C7}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Allure.XUnit.Reporters", "Allure.XUnit.Reporters\Allure.XUnit.Reporters.csproj", "{5A5F20A0-9728-4554-8CD7-850698A0061F}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -104,6 +109,14 @@ Global {77893A8D-4313-4211-AFF1-642E866A07C7}.Debug|Any CPU.Build.0 = Debug|Any CPU {77893A8D-4313-4211-AFF1-642E866A07C7}.Release|Any CPU.ActiveCfg = Release|Any CPU {77893A8D-4313-4211-AFF1-642E866A07C7}.Release|Any CPU.Build.0 = Release|Any CPU + {5A5F20A0-9728-4554-8CD7-850698A0061F}.Adapters|Any CPU.ActiveCfg = Debug|Any CPU + {5A5F20A0-9728-4554-8CD7-850698A0061F}.Adapters|Any CPU.Build.0 = Debug|Any CPU + {5A5F20A0-9728-4554-8CD7-850698A0061F}.Commons|Any CPU.ActiveCfg = Debug|Any CPU + {5A5F20A0-9728-4554-8CD7-850698A0061F}.Commons|Any CPU.Build.0 = Debug|Any CPU + {5A5F20A0-9728-4554-8CD7-850698A0061F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5A5F20A0-9728-4554-8CD7-850698A0061F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5A5F20A0-9728-4554-8CD7-850698A0061F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5A5F20A0-9728-4554-8CD7-850698A0061F}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -118,6 +131,7 @@ Global {38CF463E-F564-477D-A853-407F0648E0DD} = {138A76FC-B163-423C-8FF8-D374F1C7EC2F} {81F804C5-C437-4079-9731-97C6A2A86C48} = {D0D75FDF-4884-4AC1-868F-B3F248CB74ED} {77893A8D-4313-4211-AFF1-642E866A07C7} = {D0D75FDF-4884-4AC1-868F-B3F248CB74ED} + {5A5F20A0-9728-4554-8CD7-850698A0061F} = {138A76FC-B163-423C-8FF8-D374F1C7EC2F} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {54ACFEA9-DB76-4FC0-B216-B8033996DB79}