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

expand property aliases support (#1384) #2581

Merged
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
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