Skip to content

Commit

Permalink
Added argument transformation prototype
Browse files Browse the repository at this point in the history
  • Loading branch information
Romfos committed Jan 13, 2024
1 parent eaa4844 commit 225c432
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 8 deletions.
32 changes: 24 additions & 8 deletions src/NGherkin.TestAdapter/NGherkinTestExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ public void RunTests(IEnumerable<TestCase>? tests, IRunContext? runContext, IFra
if (testNames.Contains(testCase.FullyQualifiedName))
{
using var scopedServiceProvider = serviceProvider.CreateScope();
RunTest(frameworkHandle, scopedServiceProvider.ServiceProvider, gherkinStep, testCase);
var argumentTransformations = scopedServiceProvider.ServiceProvider.GetServices<ArgumentTransformation>();
RunTest(frameworkHandle, scopedServiceProvider.ServiceProvider, gherkinStep, argumentTransformations, testCase);
}
}
}
Expand Down Expand Up @@ -78,7 +79,8 @@ public void RunTests(IEnumerable<string>? sources, IRunContext? runContext, IFra
foreach (var testCase in NGherkinTestDiscoverer.GetTestCases(source, serviceProvider))
{
using var scopedServiceProvider = serviceProvider.CreateScope();
RunTest(frameworkHandle, scopedServiceProvider.ServiceProvider, gherkinStep, testCase);
var argumentTransformations = scopedServiceProvider.ServiceProvider.GetServices<ArgumentTransformation>();
RunTest(frameworkHandle, scopedServiceProvider.ServiceProvider, gherkinStep, argumentTransformations, testCase);
}
}
catch (Exception exception)
Expand All @@ -92,6 +94,7 @@ public void RunTests(IEnumerable<string>? sources, IRunContext? runContext, IFra
IFrameworkHandle frameworkHandle,
IServiceProvider serviceProvider,
IEnumerable<GherkinStep> gherkinSteps,
IEnumerable<ArgumentTransformation> argumentTransformations,
TestCase testCase)
{
frameworkHandle.RecordStart(testCase);
Expand All @@ -109,7 +112,7 @@ public void RunTests(IEnumerable<string>? sources, IRunContext? runContext, IFra

foreach (var stepExecutionContext in stepExecutionContexts)
{
RunTestStep(stepExecutionContext);
RunTestStep(stepExecutionContext, argumentTransformations);
}

testResult.Outcome = TestOutcome.Passed;
Expand Down Expand Up @@ -201,9 +204,9 @@ public void RunTests(IEnumerable<string>? sources, IRunContext? runContext, IFra
return stepExecutionContext;
}

private void RunTestStep(StepExecutionContext stepExecutionContext)
private void RunTestStep(StepExecutionContext stepExecutionContext, IEnumerable<ArgumentTransformation> argumentTransformations)
{
var arguments = ParseStepArguments(stepExecutionContext);
var arguments = ParseStepArguments(stepExecutionContext, argumentTransformations);

var result = stepExecutionContext.Method.Invoke(stepExecutionContext.Service, arguments);
if (result?.GetType().GetMethod("GetAwaiter") is MethodInfo getAwaiter)
Expand Down Expand Up @@ -245,16 +248,29 @@ private string GetRealStepText(Step step, TestExecutionContext testExecutionCont
return stepText;
}

private object[] ParseStepArguments(StepExecutionContext stepExecutionContext)
private object[] ParseStepArguments(StepExecutionContext stepExecutionContext, IEnumerable<ArgumentTransformation> argumentTransformations)
{
try
{
var parameters = stepExecutionContext.Method.GetParameters();
var arguments = stepExecutionContext.Parameters.Select((value, index) => Convert.ChangeType(value, parameters[index].ParameterType));
var arguments = stepExecutionContext.Parameters.Select((value, index) =>
{
var argumentValue = argumentTransformations
.Select(argumentTransformation => argumentTransformation(value, parameters[index].ParameterType))
.FirstOrDefault(x => x != null) ?? Convert.ChangeType(value, parameters[index].ParameterType);
return argumentValue;
});

if (stepExecutionContext.StepArgument != null)
{
arguments = arguments.Concat([stepExecutionContext.StepArgument]);
var argumentValue = argumentTransformations
.Select(argumentTransformation => argumentTransformation(stepExecutionContext.StepArgument, parameters.Last().ParameterType))
.FirstOrDefault(x => x != null) ?? stepExecutionContext.StepArgument;

arguments = arguments.Concat([argumentValue]);
}

return arguments.ToArray();
}
catch (Exception exception)
Expand Down
4 changes: 4 additions & 0 deletions src/NGherkin.Tests/Features/Feature1.feature
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ Scenario: this is scenario
When this is second when step with date '01/01/2020' argument
And this is when step with async task
Then this is then step
When step with model transformation
| Key | Value |
| 1 | One |
| 2 | Two |

Scenario Outline: this is scenario outline
When this is when step with with argument '<number>' and value '<text>'
Expand Down
13 changes: 13 additions & 0 deletions src/NGherkin.Tests/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Gherkin.Ast;
using Microsoft.Extensions.DependencyInjection;

namespace NGherkin.Tests;
Expand All @@ -8,5 +9,17 @@ public override void Configure(IServiceCollection services)
{
services.AddGherkinFeatures();
services.AddGherkinSteps();

services.AddArgumentTransformation(value =>
{
if (value is DataTable dataTable
&& dataTable.Rows.Count() > 2
&& dataTable.Rows.First().Cells.Count() == 2)
{
return dataTable.Rows.Skip(1).ToDictionary(x => int.Parse(x.Cells.First().Value), x => x.Cells.Last().Value);
}
return null;
});
}
}
9 changes: 9 additions & 0 deletions src/NGherkin.Tests/Steps/StepClass.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,15 @@ public async Task When3()
await Task.Yield();
}

[When("step with model transformation")]
public void When4(Dictionary<int, string> dictionary)
{
if (dictionary.Count != 2 || dictionary[1] != "One" || dictionary[2] != "Two")
{
throw new ArgumentException(nameof(dictionary));
}
}

[When("this is when step with with argument '(.*)' and value '(.*)'")]
public void When4(int number, string text)
{
Expand Down
3 changes: 3 additions & 0 deletions src/NGherkin/ArgumentTransformation.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace NGherkin;

public delegate object? ArgumentTransformation(object value, Type targetType);
14 changes: 14 additions & 0 deletions src/NGherkin/ServiceCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,20 @@ namespace NGherkin;

public static class ServiceCollectionExtensions
{
public static void AddArgumentTransformation<T>(this IServiceCollection services, Func<object, T?> converter)
{
ArgumentTransformation argumentTransformation = (object value, Type targetType) =>
{
if (targetType == typeof(T))
{
return converter(value);
}
return null;
};

services.AddSingleton(argumentTransformation);
}

public static void AddGherkinFeatures(this IServiceCollection services)
{
var assembly = Assembly.GetCallingAssembly() ?? throw new Exception("Unable to get calling assembly");
Expand Down

0 comments on commit 225c432

Please sign in to comment.