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

Prioritize Runtime Plugins based on alphabetic ordering of location paths #2705

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public virtual void RegisterGlobalContainerDefaults(ObjectContainer container)
container.RegisterTypeAs<RuntimePluginLoader, IRuntimePluginLoader>();
container.RegisterTypeAs<RuntimePluginLocator, IRuntimePluginLocator>();
container.RegisterTypeAs<RuntimePluginLocationMerger, IRuntimePluginLocationMerger>();
container.RegisterTypeAs<RuntimePluginPrioritizer, IRuntimePluginPrioritizer>();

container.RegisterTypeAs<BindingAssemblyLoader, IBindingAssemblyLoader>();

Expand Down
8 changes: 8 additions & 0 deletions TechTalk.SpecFlow/Plugins/IRuntimePluginPrioritizer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using System.Collections.Generic;

namespace TechTalk.SpecFlow.Plugins;

public interface IRuntimePluginPrioritizer
{
IReadOnlyList<string> Prioritize(IReadOnlyList<string> pluginPaths);
}
6 changes: 4 additions & 2 deletions TechTalk.SpecFlow/Plugins/RuntimePluginLocator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ namespace TechTalk.SpecFlow.Plugins
internal sealed class RuntimePluginLocator : IRuntimePluginLocator
{
private readonly IRuntimePluginLocationMerger _runtimePluginLocationMerger;
private readonly IRuntimePluginPrioritizer _runtimePluginPrioritizer;
private readonly ISpecFlowPath _specFlowPath;
private readonly Assembly _testAssembly;

public RuntimePluginLocator(IRuntimePluginLocationMerger runtimePluginLocationMerger, ISpecFlowPath specFlowPath, ITestAssemblyProvider testAssemblyProvider)
public RuntimePluginLocator(IRuntimePluginLocationMerger runtimePluginLocationMerger, IRuntimePluginPrioritizer runtimePluginPrioritizer, ISpecFlowPath specFlowPath, ITestAssemblyProvider testAssemblyProvider)
{
_runtimePluginLocationMerger = runtimePluginLocationMerger;
_runtimePluginPrioritizer = runtimePluginPrioritizer;
_specFlowPath = specFlowPath;
_testAssembly = testAssemblyProvider.TestAssembly;
}
Expand Down Expand Up @@ -46,7 +48,7 @@ public IReadOnlyList<string> GetAllRuntimePlugins()
}
}

return _runtimePluginLocationMerger.Merge(allRuntimePlugins);
return _runtimePluginPrioritizer.Prioritize(_runtimePluginLocationMerger.Merge(allRuntimePlugins));
}

private static IEnumerable<string> SearchPluginsInFolder(string folder)
Expand Down
18 changes: 18 additions & 0 deletions TechTalk.SpecFlow/Plugins/RuntimePluginPrioritizer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System.Collections.Generic;
using System.Linq;

namespace TechTalk.SpecFlow.Plugins;

public class RuntimePluginPrioritizer : IRuntimePluginPrioritizer
{
public IReadOnlyList<string> Prioritize(IReadOnlyList<string> pluginList)
{
if (pluginList is List<string> list)
{
list.Sort();
return list;
}

return pluginList.OrderBy(x => x).ToList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public void LoadPlugins_Find_TestAssembly()
testAssemblyProvider.RegisterTestAssembly(testAssembly);

//ARRANGE
var runtimePluginLocator = new RuntimePluginLocator(new RuntimePluginLocationMerger(), new SpecFlowPath(), testAssemblyProvider);
var runtimePluginLocator = new RuntimePluginLocator(new RuntimePluginLocationMerger(), new RuntimePluginPrioritizer(), new SpecFlowPath(), testAssemblyProvider);

//ACT
var plugins = runtimePluginLocator.GetAllRuntimePlugins();
Expand All @@ -38,7 +38,7 @@ public void LoadPlugins_Find_All_Referenced_Plugins()
testAssemblyProvider.RegisterTestAssembly(testAssembly);

//ARRANGE
var runtimePluginLocator = new RuntimePluginLocator(new RuntimePluginLocationMerger(), new SpecFlowPath(), testAssemblyProvider);
var runtimePluginLocator = new RuntimePluginLocator(new RuntimePluginLocationMerger(), new RuntimePluginPrioritizer(), new SpecFlowPath(), testAssemblyProvider);

//ACT
var plugins = runtimePluginLocator.GetAllRuntimePlugins();
Expand Down Expand Up @@ -103,4 +103,4 @@ private List<string> GetProjectReferences()
}

}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public void LoadPlugins_Doesnt_load_too_much_assemblies()
var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
var testAssemblyProvider = new TestAssemblyProvider();
testAssemblyProvider.RegisterTestAssembly(Assembly.GetExecutingAssembly());
var runtimePluginLocator = new RuntimePluginLocator(new RuntimePluginLocationMerger(), new SpecFlowPath(), testAssemblyProvider);
var runtimePluginLocator = new RuntimePluginLocator(new RuntimePluginLocationMerger(), new RuntimePluginPrioritizer(), new SpecFlowPath(), testAssemblyProvider);

//ACT
runtimePluginLocator.GetAllRuntimePlugins();
Expand All @@ -28,4 +28,4 @@ public void LoadPlugins_Doesnt_load_too_much_assemblies()
nowLoadedAssemblies.Should().BeEquivalentTo(loadedAssemblies);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices;
using FluentAssertions;
using TechTalk.SpecFlow.Plugins;
using Xunit;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
using System.Runtime.InteropServices;
using FluentAssertions;
using TechTalk.SpecFlow.Plugins;
using Xunit;

namespace TechTalk.SpecFlow.RuntimeTests.Infrastructure
{
public class RuntimePluginPrioritizerTests
{
[Fact]
public void Prioritize_EmptyList_EmptyList()
{
//ARRANGE
var runtimePluginPrioritizer = new RuntimePluginPrioritizer();


//ACT
var result = runtimePluginPrioritizer.Prioritize(new string[] { });


//ASSERT
result.Should().HaveCount(0);
}

[SkippableFact]
public void Prioritize_SingleEntry_ThisIsReturned_Windows()
{
Skip.IfNot(RuntimeInformation.IsOSPlatform(OSPlatform.Windows));

//ARRANGE
var runtimePluginPrioritizer = new RuntimePluginPrioritizer();


//ACT
var result = runtimePluginPrioritizer.Prioritize(new[]{ "C:\\temp\\Plugin.SpecFlowPlugin.dll" } );


//ASSERT
result.Should().HaveCount(1);
result[0].Should().Be("C:\\temp\\Plugin.SpecFlowPlugin.dll");
}

[SkippableFact]
public void Prioritize_SingleEntry_ThisIsReturned_Unix()
{
Skip.IfNot(RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ||RuntimeInformation.IsOSPlatform(OSPlatform.OSX));

//ARRANGE
var runtimePluginPrioritizer = new RuntimePluginPrioritizer();


//ACT
var result = runtimePluginPrioritizer.Prioritize(new[] { "/temp/Plugin.SpecFlowPlugin.dll" });


//ASSERT
result.Should().HaveCount(1);
result[0].Should().Be("/temp/Plugin.SpecFlowPlugin.dll");
}


[SkippableFact]
public void Prioritize_MultiplePath_ReturnedByPath_Windows()
{
Skip.IfNot(RuntimeInformation.IsOSPlatform(OSPlatform.Windows));

//ARRANGE
var runtimePluginPrioritizer = new RuntimePluginPrioritizer();


//ACT
var result = runtimePluginPrioritizer.Prioritize(new[] { "C:\\temp\\Plugin.SpecFlowPlugin.dll", "C:\\temp\\AnotherPlugin.SpecFlowPlugin.dll" });


//ASSERT
result.Should().HaveCount(2);
result[0].Should().Be("C:\\temp\\AnotherPlugin.SpecFlowPlugin.dll");
result[1].Should().Be("C:\\temp\\Plugin.SpecFlowPlugin.dll");
}


[SkippableFact]
public void Prioritize_MultiplePath_ReturnedByPath__Unix()
{
Skip.IfNot(RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX));

//ARRANGE
var runtimePluginPrioritizer = new RuntimePluginPrioritizer();


//ACT
var result = runtimePluginPrioritizer.Prioritize(new[] { "/temp/Plugin.SpecFlowPlugin.dll", "/temp/AnotherPlugin.SpecFlowPlugin.dll" });


//ASSERT
result.Should().HaveCount(2);
result[0].Should().Be("/temp/AnotherPlugin.SpecFlowPlugin.dll");
result[1].Should().Be("/temp/Plugin.SpecFlowPlugin.dll");
}
}
}
5 changes: 3 additions & 2 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Features:
+ Support for ValueTask and ValueTask<T> binding methods (step definitions, hooks, step argument transformations)
+ Rules now support Background blocks
+ Collect binding errors (type load, binding, step definition) and report them as exception when any of the tests are executed.
+ Runtime Plugins are loaded in alphabetical order of their location paths, new interface IRuntimePluginPrioritizer

Changes:
+ Existing step definition expressions detected to be either regular or cucumber expression. Check https://docs.specflow.org/projects/specflow/en/latest/Guides/UpgradeSpecFlow3To4.html for potential upgrade issues.
Expand Down Expand Up @@ -114,7 +115,7 @@ Fixes:
+ Fixed context injection in static methods for Autofac plugin https://github.com/SpecFlowOSS/SpecFlow/issues/2307

Changes:
+ Ignore tag handling: generate test framework specific ignore attributes
+ Ignore tag handling: generate test framework specific ignore attributes

3.6

Expand Down Expand Up @@ -966,4 +967,4 @@ Fixed issues:

1.0.1 - 2009-10-13

Initial publish on https://www.specflow.org
Initial publish on https://www.specflow.org