Skip to content

Commit

Permalink
expand property aliases support (#1384)
Browse files Browse the repository at this point in the history
  • Loading branch information
Emil Tzvetkov committed Apr 11, 2022
1 parent 05871ab commit aa70112
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 53 deletions.
13 changes: 7 additions & 6 deletions TechTalk.SpecFlow/Assist/SetComparer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,12 +172,13 @@ private static List<T> GetTheActualItems(IEnumerable<T> set)

private void AssertThatAllColumnsInTheTableMatchToPropertiesOnTheType()
{
var normalizedPropertyNames = new HashSet<string>(from property in typeof(T).GetProperties()
select TEHelpers.NormalizePropertyNameToMatchAgainstAColumnName(property.Name));
var normalizedColumnNames = new HashSet<string>(from columnHeader in table.Header
select TEHelpers.NormalizePropertyNameToMatchAgainstAColumnName(TEHelpers.RemoveAllCharactersThatAreNotValidInAPropertyName(columnHeader)));

var propertiesThatDoNotExist = normalizedColumnNames.Except(normalizedPropertyNames, StringComparer.OrdinalIgnoreCase).ToArray();
var propertyInfos = typeof(T).GetProperties();
var propertiesThatDoNotExist
= table.Header
.Where(
columnHeader => !propertyInfos.Any(
property => TEHelpers.IsMemberMatchingToColumnName(property, columnHeader)))
.ToList();

if (propertiesThatDoNotExist.Any())
throw new ComparisonException($@"The following fields do not exist:{Environment.NewLine}{string.Join(Environment.NewLine, propertiesThatDoNotExist)}");
Expand Down
9 changes: 4 additions & 5 deletions TechTalk.SpecFlow/Assist/TEHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ from parameter in constructor.GetParameters()

internal static bool IsMemberMatchingToColumnName(MemberInfo member, string columnName)
{
return member.Name.MatchesThisColumnName(columnName);
return member.Name.MatchesThisColumnName(columnName)
|| IsMatchingAlias(member, columnName);
}

internal static bool MatchesThisColumnName(this string propertyName, string columnName)
Expand Down Expand Up @@ -128,16 +129,14 @@ internal static List<MemberHandler> GetMembersThatNeedToBeSet(Table table, Type
var properties = (from property in type.GetProperties()
from row in table.Rows
where TheseTypesMatch(type, property.PropertyType, row)
&& (IsMemberMatchingToColumnName(property, row.Id())
|| IsMatchingAlias(property, row.Id()))
&& IsMemberMatchingToColumnName(property, row.Id())
select new MemberHandler { Type = type, Row = row, MemberName = property.Name, PropertyType = property.PropertyType, Setter = (i, v) => property.SetValue(i, v, null) }).ToList();

var fieldInfos = type.GetFields();
var fields = (from field in fieldInfos
from row in table.Rows
where TheseTypesMatch(type, field.FieldType, row)
&& (IsMemberMatchingToColumnName(field, row.Id()) ||
IsMatchingAlias(field, row.Id()))
&& IsMemberMatchingToColumnName(field, row.Id())
select new MemberHandler { Type = type, Row = row, MemberName = field.Name, PropertyType = field.FieldType, Setter = (i, v) => field.SetValue(i, v) }).ToList();

var memberHandlers = new List<MemberHandler>(properties.Capacity + fields.Count);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
using Xunit;
using FluentAssertions;
using TechTalk.SpecFlow.Assist;
using TechTalk.SpecFlow.Assist.Attributes;
using TechTalk.SpecFlow.RuntimeTests.AssistTests.ExampleEntities;
using TechTalk.SpecFlow.RuntimeTests.AssistTests.TestInfrastructure;


namespace TechTalk.SpecFlow.RuntimeTests.AssistTests
Expand Down Expand Up @@ -408,7 +408,7 @@ public void Uses_property_aliases()
var table = new Table("AliasOne", "AliasTwo", "AliasThree");
table.AddRow("PropertyOne", "PropertyTwo", "PropertyThree");

var test = table.CreateInstance<AliasedClass>();
var test = table.CreateInstance<AliasedTestObject>();
test.PropertyOne.Should().Be("PropertyOne");
test.PropertyTwo.Should().Be("PropertyTwo");
test.PropertyThree.Should().Be("PropertyThree");
Expand All @@ -420,7 +420,7 @@ public void Uses_field_aliases()
var table = new Table("FieldAliasOne", "FieldAliasTwo", "FieldAliasThree");
table.AddRow("FieldOne", "FieldTwo", "FieldThree");

var test = table.CreateInstance<AliasedClass>();
var test = table.CreateInstance<AliasedTestObject>();
test.FieldOne.Should().Be("FieldOne");
test.FieldTwo.Should().Be("FieldTwo");
test.FieldThree.Should().Be("FieldThree");
Expand All @@ -432,7 +432,7 @@ public void Property_aliases_allow_multiple_property_population()
var table = new Table("AliasOne", "AliasTwo", "AliasThree");
table.AddRow("PropertyOne", "PropertyTwo", "PropertyThree");

var test = table.CreateInstance<AliasedClass>();
var test = table.CreateInstance<AliasedTestObject>();
test.PropertyOne.Should().Be("PropertyOne");
test.AnotherPropertyWithSameAlias.Should().Be("PropertyOne");
}
Expand All @@ -443,7 +443,7 @@ public void Property_aliases_do_not_allow_type_mismatch_property_population()
var table = new Table("AliasOne", "AliasTwo", "AliasThree");
table.AddRow("PropertyOne", "PropertyTwo", "PropertyThree");

var test = table.CreateInstance<AliasedClass>();
var test = table.CreateInstance<AliasedTestObject>();
test.PropertyOne.Should().Be("PropertyOne");
test.AliasedButTypeMismatch.Should().Be(0);
}
Expand All @@ -456,7 +456,7 @@ public void Property_aliases_work_for_vertical_format()
table.AddRow("AliasTwo", "World");
table.AddRow("AliasThree", "From Rich");

var test = table.CreateInstance<AliasedClass>();
var test = table.CreateInstance<AliasedTestObject>();
test.PropertyOne.Should().Be("Hello");
test.PropertyTwo.Should().Be("World");
test.PropertyThree.Should().Be("From Rich");
Expand All @@ -474,7 +474,7 @@ public void Property_can_have_many_aliases_and_uses_regex_to_match_business_jarg
table.AddRow(middleNameAlias, "David");
table.AddRow(lastNameAlias, "Linnell");

var test = table.CreateInstance<AliasedClass>();
var test = table.CreateInstance<AliasedTestObject>();
test.PropertyOne.Should().Be("Richard");
test.PropertyTwo.Should().Be("David");
test.PropertyThree.Should().Be("Linnell");
Expand All @@ -491,35 +491,5 @@ private class Snake
public string Look_at_me { get; set; }
public string this_is_so_long { get; set; }
}

private class AliasedClass
{
[TableAliases("Alias[ ]*One", "First[ ]?Name", "^Known As$")]
public string PropertyOne { get; set; }

[TableAliases("Alias[ ]*Two", "Middle[ ]?Name", "^Never Known As$")]
public string PropertyTwo { get; set; }

[TableAliases("AliasThree")]
[TableAliases("Surname")]
[TableAliases("Last[ ]?name")]
[TableAliases("Dad's Last Name")]
public string PropertyThree { get; set; }

#pragma warning disable 649
[TableAliases("FieldAliasOne")]
public string FieldOne;
[TableAliases("FieldAliasTwo")]
public string FieldTwo;
[TableAliases("FieldAliasThree")]
public string FieldThree;
#pragma warning restore 649

[TableAliases("AliasOne")]
public string AnotherPropertyWithSameAlias { get; set; }

[TableAliases("AliasOne")]
public long AliasedButTypeMismatch { get; set; }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,24 @@ public void Ignores_casing_when_matching_property_name()
comparisonResult.ExceptionWasThrown.Should().BeFalse(comparisonResult.ExceptionMessage);
}

[Fact]
public void Uses_property_aliases()
{
var table = new Table("AliasOne", "AliasTwo", "AliasThree");
table.AddRow("PropertyOneValue", "PropertyTwoValue", "PropertyThreeValue");

var test = new AliasedTestObject
{
PropertyOne = "PropertyOneValue",
PropertyTwo = "PropertyTwoValue",
PropertyThree = "PropertyThreeValue"
};

var comparisonResult = ExceptionWasThrownByThisComparison(table, test);

comparisonResult.ExceptionWasThrown.Should().BeFalse(comparisonResult.ExceptionMessage);
}

[Fact]
public void Can_compare_a_horizontal_table()
{
Expand Down Expand Up @@ -368,7 +386,7 @@ private static ComparisonException GetExceptionThrownByThisComparison(Table tabl
return null;
}

private static ComparisonTestResult ExceptionWasThrownByThisComparison(Table table, InstanceComparisonTestObject test)
private static ComparisonTestResult ExceptionWasThrownByThisComparison<T>(Table table, T test)
{
var result = new ComparisonTestResult { ExceptionWasThrown = false };
try
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,28 @@ public void Can_compare_guids_properly()
comparisonResult.ExceptionWasThrown.Should().BeFalse(comparisonResult.ExceptionMessage);
}

protected ComparisonTestResult DetermineIfExceptionWasThrownByComparingThese(Table table, SetComparisonTestObject[] items)
[Fact]
public void Uses_property_aliases()
{
var table = new Table("AliasOne", "AliasTwo", "AliasThree");
table.AddRow("PropertyOneValue", "PropertyTwoValue", "PropertyThreeValue");

var items = new[]
{
new AliasedTestObject
{
PropertyOne = "PropertyOneValue",
PropertyTwo = "PropertyTwoValue",
PropertyThree = "PropertyThreeValue"
}
};

var comparisonResult = DetermineIfExceptionWasThrownByComparingThese(table, items);

comparisonResult.ExceptionWasThrown.Should().BeFalse(comparisonResult.ExceptionMessage);
}

protected ComparisonTestResult DetermineIfExceptionWasThrownByComparingThese<T>(Table table, T[] items)
{
var result = new ComparisonTestResult { ExceptionWasThrown = false };
try
Expand All @@ -351,7 +372,7 @@ protected ComparisonTestResult DetermineIfExceptionWasThrownByComparingThese(Tab
return result;
}

protected abstract void CallComparison(Table table, SetComparisonTestObject[] items);
protected abstract void CallComparison<T>(Table table, T[] items);
}


Expand All @@ -377,7 +398,7 @@ public void Does_not_throw_exception_if_all_items_match_but_not_in_the_same_orde
comparisonResult.ExceptionWasThrown.Should().BeFalse(comparisonResult.ExceptionMessage);
}

protected override void CallComparison(Table table, SetComparisonTestObject[] items)
protected override void CallComparison<T>(Table table, T[] items)
{
table.CompareToSet(items);
}
Expand Down Expand Up @@ -406,7 +427,7 @@ public void Throws_an_exception_if_all_items_match_but_not_in_the_same_order()
comparisonResult.ExceptionWasThrown.Should().BeTrue(comparisonResult.ExceptionMessage);
}

protected override void CallComparison(Table table, SetComparisonTestObject[] items)
protected override void CallComparison<T>(Table table, T[] items)
{
table.CompareToSet(items, sequentialEquality: true);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using TechTalk.SpecFlow.Assist.Attributes;

namespace TechTalk.SpecFlow.RuntimeTests.AssistTests.TestInfrastructure
{
public class AliasedTestObject
{
[TableAliases("Alias[ ]*One", "First[ ]?Name", "^Known As$")]
public string PropertyOne { get; set; }

[TableAliases("Alias[ ]*Two", "Middle[ ]?Name", "^Never Known As$")]
public string PropertyTwo { get; set; }

[TableAliases("AliasThree")]
[TableAliases("Surname")]
[TableAliases("Last[ ]?name")]
[TableAliases("Dad's Last Name")]
public string PropertyThree { get; set; }

#pragma warning disable 649
[TableAliases("FieldAliasOne")]
public string FieldOne;
[TableAliases("FieldAliasTwo")]
public string FieldTwo;
[TableAliases("FieldAliasThree")]
public string FieldThree;
#pragma warning restore 649

[TableAliases("AliasOne")]
public string AnotherPropertyWithSameAlias { get; set; }

[TableAliases("AliasOne")]
public long AliasedButTypeMismatch { get; set; }
}
}
3 changes: 3 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ after 3.9,58
Features:
+ Introduce ability to register and resolve global dependencies using Autofac

Fixes:
+ Support [TableAliases] also outside `CreateInstance`&`CreateSet`. Fixes #1384

3.9.58

Changes:
Expand Down

0 comments on commit aa70112

Please sign in to comment.