diff --git a/IdeIntegration/Vs2010Integration/UI/GenerateStepDefinitionSkeletonForm.Designer.cs b/IdeIntegration/Vs2010Integration/UI/GenerateStepDefinitionSkeletonForm.Designer.cs
index 70dc7a5e5..7c20cfa7e 100644
--- a/IdeIntegration/Vs2010Integration/UI/GenerateStepDefinitionSkeletonForm.Designer.cs
+++ b/IdeIntegration/Vs2010Integration/UI/GenerateStepDefinitionSkeletonForm.Designer.cs
@@ -197,6 +197,7 @@ private void InitializeComponent()
//
// helpLinkLabel
//
+ this.helpLinkLabel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.helpLinkLabel.AutoSize = true;
this.helpLinkLabel.Location = new System.Drawing.Point(286, 312);
this.helpLinkLabel.Name = "helpLinkLabel";
diff --git a/Languages.xml b/Languages.xml
index 0a464a277..c797cc5f6 100644
--- a/Languages.xml
+++ b/Languages.xml
@@ -91,6 +91,7 @@
Beispiele
Angenommen
Gegeben sei
+ Gegeben seien
Wenn
Dann
Und
@@ -111,16 +112,16 @@
But
- Crikey
- Background
- Mate
- Blokes
- Cobber
- Ya know how
- When
- Ya gotta
- N
- Cept
+ Pretty much
+ First off
+ Awww, look mate
+ Reckon it's like
+ You'll wanna
+ Y'know
+ It's just unbelievable
+ But at the end of the day I reckon
+ Too right
+ Yeah nah
OH HAI
@@ -662,4 +663,4 @@
並且
但是
-
\ No newline at end of file
+
diff --git a/Reporting/MsTestExecutionReport/MsTestToNUnit.xslt b/Reporting/MsTestExecutionReport/MsTestToNUnit.xslt
index 87c931941..a7e088db8 100644
--- a/Reporting/MsTestExecutionReport/MsTestToNUnit.xslt
+++ b/Reporting/MsTestExecutionReport/MsTestToNUnit.xslt
@@ -1,8 +1,8 @@
-
+
@@ -33,7 +34,8 @@
-
+
+
@@ -46,7 +48,7 @@
-
+
@@ -89,12 +91,12 @@
0.000
0
-
+
-
+
@@ -190,7 +192,8 @@
-
+
+
.
@@ -252,7 +255,21 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -263,8 +280,8 @@
-
+
-
+
diff --git a/Runtime/Assist/EnumerableProjection.cs b/Runtime/Assist/EnumerableProjection.cs
index bb188cac8..bbf17f290 100644
--- a/Runtime/Assist/EnumerableProjection.cs
+++ b/Runtime/Assist/EnumerableProjection.cs
@@ -98,7 +98,7 @@ public void Reset()
public class Projection
{
private readonly T item;
- private IEnumerable properties;
+ private readonly IEnumerable properties;
public Projection(T item, IEnumerable properties)
{
@@ -106,6 +106,16 @@ public Projection(T item, IEnumerable properties)
this.properties = properties;
}
+ public T Value
+ {
+ get { return item; }
+ }
+
+ public object this[string key]
+ {
+ get { return item.GetMemberValue(key); }
+ }
+
public override bool Equals(object obj)
{
if (obj is Projection)
@@ -113,7 +123,7 @@ public override bool Equals(object obj)
var otherProjection = obj as Projection;
if (item != null && otherProjection.item != null)
{
- IEnumerable properties = this.properties;
+ var properties = this.properties;
if (otherProjection.properties != null)
{
if (properties == null)
@@ -146,8 +156,8 @@ private static bool Compare(T t1, T t2, IEnumerable properties)
if (t1.GetType().GetProperty(property) == null || t2.GetType().GetProperty(property) == null)
return false;
- var thisValue = t1.GetPropertyValue(property);
- var otherValue = t2.GetPropertyValue(property);
+ var thisValue = t1.GetMemberValue(property);
+ var otherValue = t2.GetMemberValue(property);
if (thisValue != null)
{
if (otherValue == null)
diff --git a/Runtime/Assist/InstanceComparisonExtensionMethods.cs b/Runtime/Assist/InstanceComparisonExtensionMethods.cs
index 57f36bb20..aa7769d4b 100644
--- a/Runtime/Assist/InstanceComparisonExtensionMethods.cs
+++ b/Runtime/Assist/InstanceComparisonExtensionMethods.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Generic;
using System.Linq;
using TechTalk.SpecFlow.Assist.ValueComparers;
@@ -50,10 +50,22 @@ private static string DescribeTheErrorForThisDifference(Difference difference)
private static IEnumerable FindAnyDifferences(Table table, T instance)
{
return from row in table.Rows
- where ThePropertyDoesNotExist(instance, row) || TheValuesDoNotMatch(instance, row)
+ where TheMemberDoesNotExist(instance, row) || TheValuesDoNotMatch(instance, row)
select CreateDifferenceForThisRow(instance, row);
}
+ private static bool TheMemberDoesNotExist(T instance, TableRow row)
+ {
+ return ThePropertyDoesNotExist(instance, row) && TheFieldDoesNotExist(instance, row);
+ }
+
+ private static bool TheFieldDoesNotExist(T instance, TableRow row)
+ {
+ return instance.GetType().GetFields()
+ .Any(property => TEHelpers.IsMemberMatchingToColumnName(property, row.Id())) == false;
+ }
+
+
private static bool ThereAreAnyDifferences(IEnumerable differences)
{
return differences.Count() > 0;
@@ -68,7 +80,7 @@ private static bool ThePropertyDoesNotExist(T instance, TableRow row)
private static bool TheValuesDoNotMatch(T instance, TableRow row)
{
var expected = GetTheExpectedValue(row);
- var propertyValue = instance.GetPropertyValue(row.Id());
+ var propertyValue = instance.GetMemberValue(row.Id());
var valueComparers = new IValueComparer[]
{
@@ -93,19 +105,19 @@ private static string GetTheExpectedValue(TableRow row)
private static Difference CreateDifferenceForThisRow(T instance, TableRow row)
{
- if (ThePropertyDoesNotExist(instance, row))
+ if (TheMemberDoesNotExist(instance, row))
return new Difference
- {
- Property = row.Id(),
- DoesNotExist = true
- };
+ {
+ Property = row.Id(),
+ DoesNotExist = true
+ };
return new Difference
- {
- Property = row.Id(),
- Expected = row.Value(),
- Actual = instance.GetPropertyValue(row.Id())
- };
+ {
+ Property = row.Id(),
+ Expected = row.Value(),
+ Actual = instance.GetMemberValue(row.Id())
+ };
}
private class Difference
@@ -137,4 +149,5 @@ public ComparisonException(string message)
{
}
}
-}
\ No newline at end of file
+}
+
diff --git a/Runtime/Assist/MemberExtensionMethods.cs b/Runtime/Assist/MemberExtensionMethods.cs
new file mode 100644
index 000000000..d43772a50
--- /dev/null
+++ b/Runtime/Assist/MemberExtensionMethods.cs
@@ -0,0 +1,53 @@
+using System.Linq;
+using System.Reflection;
+
+namespace TechTalk.SpecFlow.Assist
+{
+ internal static class MemberExtensionMethods
+ {
+ public static object GetMemberValue(this object @object, string memberName)
+ {
+ var property = GetThePropertyOnThisObject(@object, memberName);
+
+ if (property != null)
+ {
+ return property.GetValue(@object, null);
+ }
+
+ var field = GetTheFieldOnThisObject(@object, memberName);
+ return field.GetValue(@object);
+
+ }
+
+ public static void SetMemberValue(this object @object, string propertyName, object value)
+ {
+ var property = GetThePropertyOnThisObject(@object, propertyName);
+
+ if (property != null)
+ {
+ property.SetValue(@object, value, null);
+ return;
+ }
+
+ var field = GetTheFieldOnThisObject(@object, propertyName);
+ field.SetValue(@object, value);
+
+ }
+
+
+ private static FieldInfo GetTheFieldOnThisObject(object @object, string fieldName)
+ {
+ var type = @object.GetType();
+ return type.GetFields()
+ .FirstOrDefault(x => TEHelpers.IsMemberMatchingToColumnName(x, fieldName));
+
+ }
+
+ private static PropertyInfo GetThePropertyOnThisObject(object @object, string propertyName)
+ {
+ var type = @object.GetType();
+ return type.GetProperties()
+ .FirstOrDefault(x => TEHelpers.IsMemberMatchingToColumnName(x, propertyName));
+ }
+ }
+}
\ No newline at end of file
diff --git a/Runtime/Assist/ProjectionExtensionMethods.cs b/Runtime/Assist/ProjectionExtensionMethods.cs
index f3740a3f7..7da695087 100644
--- a/Runtime/Assist/ProjectionExtensionMethods.cs
+++ b/Runtime/Assist/ProjectionExtensionMethods.cs
@@ -1,4 +1,6 @@
-using System.Collections.Generic;
+using System;
+using System.Collections.Generic;
+using System.Linq;
namespace TechTalk.SpecFlow.Assist
{
@@ -22,6 +24,45 @@ public static IEnumerable> ToProjectionOfSet(this Table table,
public static IEnumerable> ToProjectionOfInstance(this Table table, T instance)
{
return new EnumerableProjection(table);
- }
+ }
+
+ public static void CompareToProjectionOfSet(
+ this Table table,
+ IEnumerable query,
+ Func>, IEnumerable>, bool> compare)
+ {
+ var tableProjection = table.ToProjectionOfSet(query);
+ var queryProjection = query.ToProjection();
+ if (!compare(tableProjection, queryProjection))
+ {
+ throw new ComparisonException(@"Set projections do not match");
+ }
+ }
+
+ public static void CompareToProjectionOfSet(
+ this Table table,
+ IEnumerable query,
+ Func>, IEnumerable>, IEnumerable>> diff,
+ string identProperty)
+ {
+ var tableProjection = table.ToProjectionOfSet(query);
+ var queryProjection = query.ToProjection();
+ var setDifference = diff(tableProjection, queryProjection);
+ if (setDifference.Any())
+ {
+ var idents = string.Join(",", setDifference.Select(x => x[identProperty].ToString()).ToArray());
+ throw new ComparisonException(string.Format(@"The following row projections do not match: {0}", idents));
+ }
+ }
+
+ public static void CompareToProjectionOfInstance(this Table table, T instance)
+ {
+ var tableProjection = table.ToProjectionOfInstance(instance);
+ var instanceProjection = (new List() {instance}).ToProjection();
+ if (!tableProjection.Equals(instanceProjection))
+ {
+ throw new ComparisonException(@"Instance projections do not match");
+ }
+ }
}
-}
\ No newline at end of file
+}
diff --git a/Runtime/Assist/PropertyExtensionMethods.cs b/Runtime/Assist/PropertyExtensionMethods.cs
deleted file mode 100644
index 966b7a602..000000000
--- a/Runtime/Assist/PropertyExtensionMethods.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using System.Linq;
-using System.Reflection;
-
-namespace TechTalk.SpecFlow.Assist
-{
- internal static class PropertyExtensionMethods
- {
- public static object GetPropertyValue(this object @object, string propertyName)
- {
- var property = GetThePropertyOnThisObject(@object, propertyName);
- return property.GetValue(@object, null);
- }
-
- public static void SetPropertyValue(this object @object, string propertyName, object value)
- {
- var property = GetThePropertyOnThisObject(@object, propertyName);
- property.SetValue(@object, value, null);
- }
-
- private static PropertyInfo GetThePropertyOnThisObject(object @object, string propertyName)
- {
- var type = @object.GetType();
- return type.GetProperties()
- .FirstOrDefault(x => TEHelpers.IsMemberMatchingToColumnName(x, propertyName));
- }
- }
-}
diff --git a/Runtime/Assist/SetComparer.cs b/Runtime/Assist/SetComparer.cs
index 8e2dc9e70..2a9f7753f 100644
--- a/Runtime/Assist/SetComparer.cs
+++ b/Runtime/Assist/SetComparer.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
+using System.Reflection;
namespace TechTalk.SpecFlow.Assist
{
@@ -141,14 +142,20 @@ private static List GetTheActualItems(IEnumerable set)
private void AssertThatAllColumnsInTheTableMatchToPropertiesOnTheType()
{
- var propertiesThatDoNotExist = from columnHeader in table.Header
- where (typeof (T).GetProperties().Any(property => TEHelpers.IsMemberMatchingToColumnName(property, columnHeader)) == false)
- select columnHeader;
+ var type = typeof(T);
+ var memberList = new List();
+ memberList.AddRange(type.GetProperties());
+ memberList.AddRange(type.GetFields());
- if (propertiesThatDoNotExist.Any())
+ var membersThatDontExist = from columnHeader in table.Header
+ where (memberList.Any(member => TEHelpers.IsMemberMatchingToColumnName(member, columnHeader)) == false)
+ select columnHeader;
+
+ if (membersThatDontExist.Any())
throw new ComparisonException(
- propertiesThatDoNotExist.Aggregate(@"The following fields do not exist:",
+ membersThatDontExist.Aggregate(@"The following fields do not exist:",
(running, next) => running + string.Format("{0}{1}", Environment.NewLine, next)));
}
+
}
}
\ No newline at end of file
diff --git a/Runtime/Assist/TEHelpers.cs b/Runtime/Assist/TEHelpers.cs
index 95c31a257..3724da4e1 100644
--- a/Runtime/Assist/TEHelpers.cs
+++ b/Runtime/Assist/TEHelpers.cs
@@ -65,8 +65,12 @@ internal static bool IsMemberMatchingToColumnName(MemberInfo member, string colu
internal static bool MatchesThisColumnName(this string propertyName, string columnName)
{
- return propertyName.Equals(columnName.Replace(" ", string.Empty), StringComparison.OrdinalIgnoreCase);
+ var cleanedColumnName = columnName
+ .Replace(" ", string.Empty)
+ .Replace("-", string.Empty)
+ .Replace("?", string.Empty);
+ return propertyName.Equals(cleanedColumnName, StringComparison.OrdinalIgnoreCase);
}
internal static void LoadInstanceWithKeyValuePairs(Table table, object instance)
@@ -147,10 +151,23 @@ internal static Dictionary> GetTypeHandlersForField
{typeof (DateTime?), (TableRow row) => new NullableDateTimeValueRetriever(v => new DateTimeValueRetriever().GetValue(v)).GetValue(row[1])},
{typeof (Guid), (TableRow row) => new GuidValueRetriever().GetValue(row[1])},
{typeof (Guid?), (TableRow row) => new NullableGuidValueRetriever(v => new GuidValueRetriever().GetValue(v)).GetValue(row[1])},
- {typeof (Enum), (TableRow row) => new EnumValueRetriever().GetValue(row[1], type.GetProperties().First(x => x.Name.MatchesThisColumnName(row[0])).PropertyType)},
+ {typeof (Enum), (TableRow row) => new EnumValueRetriever().GetValue(row[1], GetMemberType(type, row))},
};
}
+ private static Type GetMemberType(Type type, TableRow row)
+ {
+ // search for property matching on name
+ if (type.GetProperties().Any(x => x.Name.MatchesThisColumnName(row[0])))
+ {
+ return type.GetProperties().First(x => x.Name.MatchesThisColumnName(row[0])).PropertyType;
+ }
+
+ //search for matching field
+ return type.GetFields().First(x => x.Name.MatchesThisColumnName(row[0])).FieldType;
+
+ }
+
internal class MemberHandler
{
public TableRow Row { get; set; }
@@ -190,4 +207,4 @@ private static bool TheFirstRowValueIsTheNameOfAProperty(Table table, Type type)
.Any(property => IsMemberMatchingToColumnName(property, firstRowValue));
}
}
-}
\ No newline at end of file
+}
diff --git a/Runtime/Assist/TableDiffExceptionBuilder.cs b/Runtime/Assist/TableDiffExceptionBuilder.cs
index f0f64e68a..14e13466b 100644
--- a/Runtime/Assist/TableDiffExceptionBuilder.cs
+++ b/Runtime/Assist/TableDiffExceptionBuilder.cs
@@ -29,7 +29,7 @@ public string GetTheTableDiffExceptionMessage(TableDifferenceResults tableDif
{
var line = "+ |";
foreach (var header in tableDifferenceResults.Table.Header)
- line += string.Format(" {0} |", item.GetPropertyValue(header));
+ line += string.Format(" {0} |", item.GetMemberValue(header));
realData.AppendLine(line);
}
diff --git a/Runtime/Assist/TableExtensionMethods.cs b/Runtime/Assist/TableExtensionMethods.cs
index d74e5214b..c581ae141 100644
--- a/Runtime/Assist/TableExtensionMethods.cs
+++ b/Runtime/Assist/TableExtensionMethods.cs
@@ -55,5 +55,20 @@ public static IEnumerable CreateSet(this Table table, Func methodToCrea
return list;
}
+
+ public static IEnumerable CreateSet(this Table table, Func methodToCreateEachInstance)
+ {
+ var list = new List();
+
+ var pivotTable = new PivotTable(table);
+ for (var index = 0; index < table.Rows.Count(); index++)
+ {
+ var instance = methodToCreateEachInstance(table.Rows[index]);
+ pivotTable.GetInstanceTable(index).FillInstance(instance);
+ list.Add(instance);
+ }
+
+ return list;
+ }
}
}
\ No newline at end of file
diff --git a/Runtime/Assist/ValueRetrievers/EnumValueRetriever.cs b/Runtime/Assist/ValueRetrievers/EnumValueRetriever.cs
index f4e054d4d..d4b7407a8 100644
--- a/Runtime/Assist/ValueRetrievers/EnumValueRetriever.cs
+++ b/Runtime/Assist/ValueRetrievers/EnumValueRetriever.cs
@@ -13,6 +13,9 @@ public object GetValue(string value, Type enumType)
private object ConvertTheStringToAnEnum(string value, Type enumType)
{
+ if (!ThisIsNotANullableEnum(enumType) && string.IsNullOrEmpty(value))
+ return null;
+
return Enum.Parse(GetTheEnumType(enumType), ParseTheValue(value), true);
}
diff --git a/Runtime/Bindings/BindingInvoker.cs b/Runtime/Bindings/BindingInvoker.cs
index ff93dabce..2f7113520 100644
--- a/Runtime/Bindings/BindingInvoker.cs
+++ b/Runtime/Bindings/BindingInvoker.cs
@@ -5,6 +5,7 @@
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
+using System.Threading.Tasks;
using TechTalk.SpecFlow.Bindings.Reflection;
using TechTalk.SpecFlow.Compatibility;
using TechTalk.SpecFlow.Configuration;
@@ -43,6 +44,12 @@ public object InvokeBinding(IBinding binding, IContextManager contextManager, ob
Array.Copy(arguments, 0, invokeArgs, 1, arguments.Length);
invokeArgs[0] = contextManager;
result = bindingAction.DynamicInvoke(invokeArgs);
+
+ if (result is Task)
+ {
+ ((Task) result).Wait();
+ }
+
stopwatch.Stop();
}
@@ -64,6 +71,12 @@ public object InvokeBinding(IBinding binding, IContextManager contextManager, ob
ex = ex.PreserveStackTrace(errorProvider.GetMethodText(binding.Method));
throw ex;
}
+ catch (AggregateException agEx) //from Task.Wait();
+ {
+ var ex = agEx.InnerExceptions.First();
+ ex = ex.PreserveStackTrace(errorProvider.GetMethodText(binding.Method));
+ throw ex;
+ }
}
private CultureInfoScope CreateCultureInfoScope(IContextManager contextManager)
diff --git a/Runtime/Bindings/HorizontalTableConverter.cs b/Runtime/Bindings/HorizontalTableConverter.cs
new file mode 100644
index 000000000..6278c9f89
--- /dev/null
+++ b/Runtime/Bindings/HorizontalTableConverter.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Collections.Generic;
+using TechTalk.SpecFlow.Bindings.Reflection;
+using System.Globalization;
+using TechTalk.SpecFlow.Assist;
+
+namespace TechTalk.SpecFlow.Bindings
+{
+ internal class HorizontalTableConverter : TableConverterBase
+ {
+ private readonly IStepArgumentTypeConverter stepArgumentTypeConverter;
+
+ public HorizontalTableConverter(IStepArgumentTypeConverter stepArgumentTypeConverter)
+ {
+ this.stepArgumentTypeConverter = stepArgumentTypeConverter;
+ }
+
+ protected override object Convert(Table table, IBindingType typeToConvertTo, CultureInfo cultureInfo)
+ {
+ var itemRuntimeType = GetItemRuntimeType(typeToConvertTo);
+ var rowFetcher = GetValidRowFetcherDelegate(table, itemRuntimeType, cultureInfo);
+ var result = Array.CreateInstance(itemRuntimeType.Type, table.RowCount);
+
+ for (int i = 0; i < result.Length; i++)
+ {
+ var item = stepArgumentTypeConverter.Convert(rowFetcher(i), itemRuntimeType, cultureInfo);
+ result.SetValue(item, i);
+ }
+
+ return result;
+ }
+
+ protected override bool CanConvert(Table table, IBindingType typeToConvertTo, CultureInfo cultureInfo)
+ {
+ var itemRuntimeType = GetItemRuntimeType(typeToConvertTo);
+ if (itemRuntimeType == null || IsVerticalTable(table, itemRuntimeType))
+ return false;
+
+ var rowFetcher = GetValidRowFetcherDelegate(table, itemRuntimeType, cultureInfo);
+ return rowFetcher != null;
+ }
+
+ private RuntimeBindingType GetItemRuntimeType(IBindingType typeToConvertTo)
+ {
+ var runtimeType = typeToConvertTo as RuntimeBindingType;
+ if (runtimeType == null)
+ return null;
+
+ var type = runtimeType.Type;
+
+ if (type.IsArray && type.GetArrayRank() == 1)
+ return new RuntimeBindingType(type.GetElementType());
+
+ if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
+ return new RuntimeBindingType(type.GetGenericArguments()[0]);
+
+ return null;
+ }
+
+ private Func GetValidRowFetcherDelegate(Table table, IBindingType typeToConvertTo, CultureInfo cultureInfo)
+ {
+ if (table.RowCount == 0)
+ return x => null;
+
+ var pivotTable = new PivotTable(table);
+ if (stepArgumentTypeConverter.CanConvert(pivotTable.GetInstanceTable(0), typeToConvertTo, cultureInfo))
+ return x => pivotTable.GetInstanceTable(x);
+
+ if (table.Header.Count == 1 &&
+ stepArgumentTypeConverter.CanConvert(table.Rows[0][0], typeToConvertTo, cultureInfo))
+ return x => table.Rows[x][0];
+
+ return null;
+ }
+ }
+}
diff --git a/Runtime/Bindings/IndentityConverter.cs b/Runtime/Bindings/IndentityConverter.cs
new file mode 100644
index 000000000..08d6ed90e
--- /dev/null
+++ b/Runtime/Bindings/IndentityConverter.cs
@@ -0,0 +1,18 @@
+using System.Globalization;
+using TechTalk.SpecFlow.Bindings.Reflection;
+
+namespace TechTalk.SpecFlow.Bindings
+{
+ internal class IndentityConverter : IStepArgumentTypeConverter
+ {
+ public object Convert(object value, IBindingType typeToConvertTo, CultureInfo cultureInfo)
+ {
+ return value;
+ }
+
+ public bool CanConvert(object value, IBindingType typeToConvertTo, CultureInfo cultureInfo)
+ {
+ return typeToConvertTo.IsAssignableTo(value.GetType());
+ }
+ }
+}
diff --git a/Runtime/Bindings/SimpleConverter.cs b/Runtime/Bindings/SimpleConverter.cs
new file mode 100644
index 000000000..049c119f7
--- /dev/null
+++ b/Runtime/Bindings/SimpleConverter.cs
@@ -0,0 +1,54 @@
+using System;
+using System.Globalization;
+using TechTalk.SpecFlow.Assist.ValueRetrievers;
+using TechTalk.SpecFlow.Bindings.Reflection;
+
+namespace TechTalk.SpecFlow.Bindings
+{
+ internal class SimpleConverter : IStepArgumentTypeConverter
+ {
+ public object Convert(object value, IBindingType typeToConvertTo, CultureInfo cultureInfo)
+ {
+ var runtimeType = (RuntimeBindingType)typeToConvertTo;
+
+ if (runtimeType.Type.IsEnum && value is string)
+ return Enum.Parse(runtimeType.Type, ((string)value).Replace(" ", ""), true);
+
+ if (runtimeType.Type == typeof(Guid?) && string.IsNullOrEmpty(value as string))
+ return null;
+
+ if (runtimeType.Type == typeof(Guid) || runtimeType.Type == typeof(Guid?))
+ return new GuidValueRetriever().GetValue(value as string);
+
+ return System.Convert.ChangeType(value, runtimeType.Type, cultureInfo);
+ }
+
+ public bool CanConvert(object value, IBindingType typeToConvertTo, CultureInfo cultureInfo)
+ {
+ if (!(typeToConvertTo is RuntimeBindingType))
+ return false;
+
+ try
+ {
+ Convert(value, typeToConvertTo, cultureInfo);
+ return true;
+ }
+ catch (InvalidCastException)
+ {
+ return false;
+ }
+ catch (OverflowException)
+ {
+ return false;
+ }
+ catch (FormatException)
+ {
+ return false;
+ }
+ catch (ArgumentException)
+ {
+ return false;
+ }
+ }
+ }
+}
diff --git a/Runtime/Bindings/StepArgumentTransformationConverter.cs b/Runtime/Bindings/StepArgumentTransformationConverter.cs
new file mode 100644
index 000000000..1d8dafb65
--- /dev/null
+++ b/Runtime/Bindings/StepArgumentTransformationConverter.cs
@@ -0,0 +1,90 @@
+using System;
+using System.Globalization;
+using System.Linq;
+using System.Text.RegularExpressions;
+using TechTalk.SpecFlow.Bindings.Reflection;
+using TechTalk.SpecFlow.Infrastructure;
+using TechTalk.SpecFlow.Tracing;
+
+namespace TechTalk.SpecFlow.Bindings
+{
+ internal class StepArgumentTransformationConverter : IStepArgumentTypeConverter
+ {
+ private readonly IStepArgumentTypeConverter stepArgumentTypeConverter;
+ private readonly ITestTracer testTracer;
+ private readonly IBindingRegistry bindingRegistry;
+ private readonly IContextManager contextManager;
+ private readonly IBindingInvoker bindingInvoker;
+
+ public StepArgumentTransformationConverter(IStepArgumentTypeConverter stepArgumentTypeConverter, ITestTracer testTracer, IBindingRegistry bindingRegistry, IContextManager contextManager, IBindingInvoker bindingInvoker)
+ {
+ this.stepArgumentTypeConverter = stepArgumentTypeConverter;
+ this.testTracer = testTracer;
+ this.bindingRegistry = bindingRegistry;
+ this.contextManager = contextManager;
+ this.bindingInvoker = bindingInvoker;
+ }
+
+ public object Convert(object value, IBindingType typeToConvertTo, CultureInfo cultureInfo)
+ {
+ var stepTransformation = GetMatchingStepTransformation(value, typeToConvertTo, true);
+
+ if (stepTransformation == null)
+ throw new SpecFlowException("The StepTransformationConverter cannot convert the specified value.");
+
+ return DoTransform(stepTransformation, value, cultureInfo);
+ }
+
+ public bool CanConvert(object value, IBindingType typeToConvertTo, CultureInfo cultureInfo)
+ {
+ return GetMatchingStepTransformation(value, typeToConvertTo, false) != null;
+ }
+
+ private IStepArgumentTransformationBinding GetMatchingStepTransformation(object value, IBindingType typeToConvertTo, bool traceWarning)
+ {
+ var stepTransformations = bindingRegistry.GetStepTransformations().Where(t => CanConvert(t, value, typeToConvertTo)).ToArray();
+
+ if (stepTransformations.Length > 1 && traceWarning)
+ {
+ testTracer.TraceWarning(string.Format("Multiple step transformation matches to the input ({0}, target type: {1}). We use the first.", value, typeToConvertTo));
+ }
+
+ return stepTransformations.FirstOrDefault();
+ }
+
+ private bool CanConvert(IStepArgumentTransformationBinding stepTransformationBinding, object value, IBindingType typeToConvertTo)
+ {
+ if (!stepTransformationBinding.Method.ReturnType.TypeEquals(typeToConvertTo))
+ return false;
+
+ if (stepTransformationBinding.Regex != null)
+ {
+ return value is string && stepTransformationBinding.Regex.IsMatch((string)value);
+ }
+
+ return stepTransformationBinding.Method.Parameters.Count() == 1;
+ }
+
+ private object DoTransform(IStepArgumentTransformationBinding stepTransformation, object value, CultureInfo cultureInfo)
+ {
+ object[] arguments;
+ if (stepTransformation.Regex != null && value is string)
+ arguments = GetStepTransformationArgumentsFromRegex(stepTransformation, (string)value, cultureInfo);
+ else
+ arguments = new object[] { value };
+
+ TimeSpan duration;
+ return bindingInvoker.InvokeBinding(stepTransformation, contextManager, arguments, testTracer, out duration);
+ }
+
+ private object[] GetStepTransformationArgumentsFromRegex(IStepArgumentTransformationBinding stepTransformation, string stepSnippet, CultureInfo cultureInfo)
+ {
+ var match = stepTransformation.Regex.Match(stepSnippet);
+ var argumentStrings = match.Groups.Cast().Skip(1).Select(g => g.Value);
+ var bindingParameters = stepTransformation.Method.Parameters.ToArray();
+ return argumentStrings
+ .Select((arg, argIndex) => stepArgumentTypeConverter.Convert(arg, bindingParameters[argIndex].Type, cultureInfo))
+ .ToArray();
+ }
+ }
+}
diff --git a/Runtime/Bindings/StepArgumentTypeConverter.cs b/Runtime/Bindings/StepArgumentTypeConverter.cs
index e603e1cc2..067cd9f14 100644
--- a/Runtime/Bindings/StepArgumentTypeConverter.cs
+++ b/Runtime/Bindings/StepArgumentTypeConverter.cs
@@ -1,11 +1,9 @@
-using System;
using System.Globalization;
using System.Linq;
-using System.Text.RegularExpressions;
-using TechTalk.SpecFlow.Assist.ValueRetrievers;
using TechTalk.SpecFlow.Bindings.Reflection;
using TechTalk.SpecFlow.Infrastructure;
using TechTalk.SpecFlow.Tracing;
+using System.Collections.Generic;
namespace TechTalk.SpecFlow.Bindings
{
@@ -17,135 +15,34 @@ public interface IStepArgumentTypeConverter
public class StepArgumentTypeConverter : IStepArgumentTypeConverter
{
- private readonly ITestTracer testTracer;
- private readonly IBindingRegistry bindingRegistry;
- private readonly IContextManager contextManager;
- private readonly IBindingInvoker bindingInvoker;
+ private readonly IEnumerable converters;
public StepArgumentTypeConverter(ITestTracer testTracer, IBindingRegistry bindingRegistry, IContextManager contextManager, IBindingInvoker bindingInvoker)
{
- this.testTracer = testTracer;
- this.bindingRegistry = bindingRegistry;
- this.contextManager = contextManager;
- this.bindingInvoker = bindingInvoker;
- }
-
- protected virtual IStepArgumentTransformationBinding GetMatchingStepTransformation(object value, IBindingType typeToConvertTo, bool traceWarning)
- {
- var stepTransformations = bindingRegistry.GetStepTransformations().Where(t => CanConvert(t, value, typeToConvertTo)).ToArray();
- if (stepTransformations.Length > 1 && traceWarning)
+ converters = new IStepArgumentTypeConverter[]
{
- testTracer.TraceWarning(string.Format("Multiple step transformation matches to the input ({0}, target type: {1}). We use the first.", value, typeToConvertTo));
- }
-
- return stepTransformations.Length > 0 ? stepTransformations[0] : null;
+ new IndentityConverter(),
+ new StepArgumentTransformationConverter(this, testTracer, bindingRegistry, contextManager, bindingInvoker),
+ new VerticalTableConverter(this),
+ new HorizontalTableConverter(this),
+ new SimpleConverter()
+ };
}
public object Convert(object value, IBindingType typeToConvertTo, CultureInfo cultureInfo)
{
- if (value == null) throw new ArgumentNullException("value");
-
- if (typeToConvertTo == value.GetType())
- return value;
-
- var stepTransformation = GetMatchingStepTransformation(value, typeToConvertTo, true);
- if (stepTransformation != null)
- return DoTransform(stepTransformation, value, cultureInfo);
-
- return ConvertSimple(typeToConvertTo, value, cultureInfo);
- }
-
- private object DoTransform(IStepArgumentTransformationBinding stepTransformation, object value, CultureInfo cultureInfo)
- {
- object[] arguments;
- if (stepTransformation.Regex != null && value is string)
- arguments = GetStepTransformationArgumentsFromRegex(stepTransformation, (string)value, cultureInfo);
- else
- arguments = new object[] {value};
-
- TimeSpan duration;
- return bindingInvoker.InvokeBinding(stepTransformation, contextManager, arguments, testTracer, out duration);
- }
-
- private object[] GetStepTransformationArgumentsFromRegex(IStepArgumentTransformationBinding stepTransformation, string stepSnippet, CultureInfo cultureInfo)
- {
- var match = stepTransformation.Regex.Match(stepSnippet);
- var argumentStrings = match.Groups.Cast().Skip(1).Select(g => g.Value);
- var bindingParameters = stepTransformation.Method.Parameters.ToArray();
- return argumentStrings
- .Select((arg, argIndex) => this.Convert(arg, bindingParameters[argIndex].Type, cultureInfo))
- .ToArray();
+ var converter = GetConverter(value, typeToConvertTo, cultureInfo);
+ return converter.Convert(value, typeToConvertTo, cultureInfo);
}
public bool CanConvert(object value, IBindingType typeToConvertTo, CultureInfo cultureInfo)
{
- if (value == null) throw new ArgumentNullException("value");
-
- if (typeToConvertTo == value.GetType())
- return true;
-
- var stepTransformation = GetMatchingStepTransformation(value, typeToConvertTo, false);
- if (stepTransformation != null)
- return true;
-
- return CanConvertSimple(typeToConvertTo, value, cultureInfo);
- }
-
- private bool CanConvert(IStepArgumentTransformationBinding stepTransformationBinding, object value, IBindingType typeToConvertTo)
- {
- if (!stepTransformationBinding.Method.ReturnType.TypeEquals(typeToConvertTo))
- return false;
-
- if (stepTransformationBinding.Regex != null && value is string)
- return stepTransformationBinding.Regex.IsMatch((string) value);
- return true;
- }
-
- private static object ConvertSimple(IBindingType typeToConvertTo, object value, CultureInfo cultureInfo)
- {
- if (!(typeToConvertTo is RuntimeBindingType))
- throw new SpecFlowException("The StepArgumentTypeConverter can be used with runtime types only.");
-
- return ConvertSimple(((RuntimeBindingType) typeToConvertTo).Type, value, cultureInfo);
- }
-
- private static object ConvertSimple(Type typeToConvertTo, object value, CultureInfo cultureInfo)
- {
- if (typeToConvertTo.IsEnum && value is string)
- return Enum.Parse(typeToConvertTo, (string)value, true);
-
- if (typeToConvertTo == typeof(Guid?) && string.IsNullOrEmpty(value as string))
- return null;
-
- if (typeToConvertTo == typeof(Guid) || typeToConvertTo == typeof(Guid?))
- return new GuidValueRetriever().GetValue(value as string);
-
- return System.Convert.ChangeType(value, typeToConvertTo, cultureInfo);
+ return GetConverter(value, typeToConvertTo, cultureInfo) != null;
}
- public static bool CanConvertSimple(IBindingType typeToConvertTo, object value, CultureInfo cultureInfo)
+ private IStepArgumentTypeConverter GetConverter(object value, IBindingType typeToConvertTo, CultureInfo cultureInfo)
{
- try
- {
- ConvertSimple(typeToConvertTo, value, cultureInfo);
- return true;
- }
- catch (InvalidCastException)
- {
- return false;
- }
- catch (OverflowException)
- {
- return false;
- }
- catch (FormatException)
- {
- return false;
- }
- catch (ArgumentException)
- {
- return false;
- }
+ return converters.FirstOrDefault(x => x.CanConvert(value, typeToConvertTo, cultureInfo));
}
}
}
diff --git a/Runtime/Bindings/TableConverterBase.cs b/Runtime/Bindings/TableConverterBase.cs
new file mode 100644
index 000000000..d83d40f72
--- /dev/null
+++ b/Runtime/Bindings/TableConverterBase.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using TechTalk.SpecFlow.Bindings.Reflection;
+using System.Globalization;
+using System.Reflection;
+
+namespace TechTalk.SpecFlow.Bindings
+{
+ internal abstract class TableConverterBase : IStepArgumentTypeConverter
+ {
+ protected abstract object Convert(Table table, IBindingType typeToConvertTo, CultureInfo cultureInfo);
+
+ protected abstract bool CanConvert(Table table, IBindingType typeToConvertTo, CultureInfo cultureInfo);
+
+ public object Convert(object value, IBindingType typeToConvertTo, CultureInfo cultureInfo)
+ {
+ return Convert((Table)value, typeToConvertTo, cultureInfo);
+ }
+
+ public bool CanConvert(object value, IBindingType typeToConvertTo, CultureInfo cultureInfo)
+ {
+ var table = value as Table;
+ if (table == null)
+ return false;
+
+ return CanConvert(table, typeToConvertTo, cultureInfo);
+ }
+
+ protected static bool IsVerticalTable(Table table, RuntimeBindingType runtimeBindingType)
+ {
+ if (table.Header.Count != 2)
+ return false;
+
+ if (table.RowCount == 0)
+ return true;
+
+ var writableProperties = GetWritableProperties(runtimeBindingType.Type);
+ return writableProperties.ContainsKey(SanitizePropertyName(table.Rows[0][0]));
+ }
+
+ protected static Dictionary GetWritableProperties(Type type)
+ {
+ return type.GetProperties().Where(x => x.CanWrite).ToDictionary(x => SanitizePropertyName(x.Name));
+ }
+
+ protected static string SanitizePropertyName(string name)
+ {
+ return name.Replace(" ", "").ToLowerInvariant();
+ }
+ }
+}
diff --git a/Runtime/Bindings/VerticalTableConverter.cs b/Runtime/Bindings/VerticalTableConverter.cs
new file mode 100644
index 000000000..d97bc31eb
--- /dev/null
+++ b/Runtime/Bindings/VerticalTableConverter.cs
@@ -0,0 +1,142 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using TechTalk.SpecFlow.Bindings.Reflection;
+using System.Globalization;
+using System.Reflection;
+using TechTalk.SpecFlow.Assist;
+
+namespace TechTalk.SpecFlow.Bindings
+{
+ internal class VerticalTableConverter : TableConverterBase
+ {
+ private readonly IStepArgumentTypeConverter stepArgumentTypeConverter;
+
+ public VerticalTableConverter(IStepArgumentTypeConverter stepArgumentTypeConverter)
+ {
+ this.stepArgumentTypeConverter = stepArgumentTypeConverter;
+ }
+
+ protected override object Convert(Table table, IBindingType typeToConvertTo, CultureInfo cultureInfo)
+ {
+ var runtimeBindingType = (RuntimeBindingType)typeToConvertTo;
+ var verticalTable = GetVerticalTable(table, runtimeBindingType);
+ var values = GetValues(verticalTable);
+ var objectInitializationData = GetObjectInitializationData(values.Keys, runtimeBindingType.Type);
+ var bindingTypes = objectInitializationData.GetBindingTypes();
+
+ var convertedValues = values
+ .Where(x => bindingTypes.ContainsKey(x.Key))
+ .ToDictionary(
+ x => x.Key,
+ x => stepArgumentTypeConverter.Convert(x.Value, bindingTypes[x.Key], cultureInfo));
+ var constructorParameters = objectInitializationData.Constructor.GetParameters()
+ .Select(x => convertedValues[SanitizePropertyName(x.Name)]).ToArray();
+ var result = objectInitializationData.Constructor.Invoke(constructorParameters);
+
+ foreach (var property in objectInitializationData.PropertiesToSet)
+ {
+ var value = convertedValues[SanitizePropertyName(property.Name)];
+ property.SetValue(result, value, null);
+ }
+
+ return result;
+ }
+
+ protected override bool CanConvert(Table table, IBindingType typeToConvertTo, CultureInfo cultureInfo)
+ {
+ var runtimeBindingType = typeToConvertTo as RuntimeBindingType;
+ if (runtimeBindingType == null)
+ return false;
+
+ var verticalTable = GetVerticalTable(table, runtimeBindingType);
+ if (verticalTable == null)
+ return false;
+
+ var values = GetValues(verticalTable);
+ var objectInitializationData = GetObjectInitializationData(values.Keys, runtimeBindingType.Type);
+ if (objectInitializationData == null)
+ return false;
+
+ var bindingTypes = objectInitializationData.GetBindingTypes();
+ return values
+ .Where(x => bindingTypes.ContainsKey(x.Key))
+ .All(x => stepArgumentTypeConverter.CanConvert(x.Value, bindingTypes[x.Key], cultureInfo));
+ }
+
+ private Table GetVerticalTable(Table table, RuntimeBindingType runtimeBindingType)
+ {
+ if (IsVerticalTable(table, runtimeBindingType))
+ return table;
+
+ if (table.Rows.Count == 1)
+ {
+ var pivotedTable = new PivotTable(table).GetInstanceTable(0);
+
+ if (IsVerticalTable(pivotedTable, runtimeBindingType))
+ return pivotedTable;
+ }
+
+ return null;
+ }
+
+ private Dictionary GetValues(Table table)
+ {
+ return table.Rows.ToDictionary(x => SanitizePropertyName(x[0]), x => x[1]);
+ }
+
+ private ObjectInitializationData GetObjectInitializationData(IEnumerable columns, Type type)
+ {
+ var writableProperties = GetWritableProperties(type);
+ var requiredParameters = new HashSet(columns.Where(x => !writableProperties.ContainsKey(x)));
+ var optionalParameters = new HashSet(columns.Where(writableProperties.ContainsKey));
+
+ var constructor = GetBestMatchingConstructor(type, requiredParameters, optionalParameters);
+ if (constructor == null)
+ return null;
+
+ var constructorColumns = new HashSet(constructor.GetParameters().Select(x => SanitizePropertyName(x.Name)));
+ var propertiesToSet = columns
+ .Where(x => !constructorColumns.Contains(x) && writableProperties.ContainsKey(x))
+ .Select(x => writableProperties[x]).ToList();
+
+ return new ObjectInitializationData
+ {
+ Constructor = constructor,
+ PropertiesToSet = propertiesToSet
+ };
+ }
+
+ private ConstructorInfo GetBestMatchingConstructor(Type type, HashSet requiredParameters, HashSet optionalParameters)
+ {
+ return type.GetConstructors()
+ .Select(c => new { Constructor = c, Parameters = c.GetParameters().Select(p => SanitizePropertyName(p.Name)).ToList() })
+ .OrderByDescending(x => x.Parameters.Count(requiredParameters.Contains))
+ .ThenBy(x => x.Parameters.Count)
+ .Where(x => x.Parameters.All(p => requiredParameters.Contains(p) || optionalParameters.Contains(p)))
+ .Select(x => x.Constructor)
+ .FirstOrDefault();
+ }
+
+ private class ObjectInitializationData
+ {
+ public ConstructorInfo Constructor { get; set; }
+
+ public List PropertiesToSet { get; set; }
+
+ public Dictionary GetBindingTypes()
+ {
+ var bindingTypes = new Dictionary();
+ foreach (var parameter in Constructor.GetParameters())
+ {
+ bindingTypes.Add(SanitizePropertyName(parameter.Name), new RuntimeBindingType(parameter.ParameterType));
+ }
+ foreach (var property in PropertiesToSet)
+ {
+ bindingTypes.Add(SanitizePropertyName(property.Name), new RuntimeBindingType(property.PropertyType));
+ }
+ return bindingTypes;
+ }
+ }
+ }
+}
diff --git a/Runtime/TechTalk.SpecFlow.csproj b/Runtime/TechTalk.SpecFlow.csproj
index 590300157..3f5066a78 100644
--- a/Runtime/TechTalk.SpecFlow.csproj
+++ b/Runtime/TechTalk.SpecFlow.csproj
@@ -10,10 +10,11 @@
Properties
TechTalk.SpecFlow
TechTalk.SpecFlow
- v3.5
+ v4.0
512
true
..\specflow.snk
+
true
@@ -65,7 +66,7 @@
-
+
@@ -128,10 +129,12 @@
+
+
@@ -148,10 +151,14 @@
+
+
+
+
diff --git a/Tests/RuntimeTests/AssistTests/InstanceComparisonExtensionMethodsTests.cs b/Tests/RuntimeTests/AssistTests/InstanceComparisonExtensionMethodsTests.cs
index e458c4d16..f8d4090ea 100644
--- a/Tests/RuntimeTests/AssistTests/InstanceComparisonExtensionMethodsTests.cs
+++ b/Tests/RuntimeTests/AssistTests/InstanceComparisonExtensionMethodsTests.cs
@@ -17,6 +17,45 @@ public void SetUp()
Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
}
+ [Test]
+ public void Does_not_throw_exception_when_value_of_matching_string_field_matches()
+ {
+ var table = new Table("Field", "Value");
+ table.AddRow("StringField", "Howard Roark");
+
+ var test = new InstanceComparisonTestObjectWithFields { StringField = "Howard Roark" };
+
+ ComparisonTestResult comparisonResult = ExceptionWasThrownByThisComparison(table, test);
+
+ comparisonResult.ExceptionWasThrown.ShouldBeFalse(comparisonResult.ExceptionMessage);
+ }
+
+ [Test]
+ public void Throws_exception_when_field_matching_name_does_not_exist()
+ {
+ var table = new Table("Field", "Value");
+ table.AddRow("DecimalField", "3.5");
+
+ var test = new InstanceComparisonTestObjectWithFields();
+
+ ComparisonTestResult comparisonResult = ExceptionWasThrownByThisComparison(table, test);
+
+ comparisonResult.ExceptionWasThrown.ShouldBeTrue();
+ }
+
+ [Test]
+ public void Throws_exception_when_field_matches_on_name_but_not_on_value()
+ {
+ var table = new Table("Field", "Value");
+ table.AddRow("IntField", "3");
+
+ var test = new InstanceComparisonTestObjectWithFields { IntField = 5 };
+
+ ComparisonTestResult comparisonResult = ExceptionWasThrownByThisComparison(table, test);
+
+ comparisonResult.ExceptionWasThrown.ShouldBeTrue();
+ }
+
[Test]
public void Throws_exception_when_value_of_matching_string_property_does_not_match()
{
@@ -51,10 +90,10 @@ public void Throws_exception_when_first_row_matches_but_second_does_not()
table.AddRow("IntProperty", "20");
var test = new InstanceComparisonTestObject
- {
- StringProperty = "Howard Roark",
- IntProperty = 10
- };
+ {
+ StringProperty = "Howard Roark",
+ IntProperty = 10
+ };
ComparisonTestResult comparisonResult = ExceptionWasThrownByThisComparison(table, test);
@@ -136,10 +175,10 @@ public void Exception_returns_an_exception_for_two_errors_when_there_are_two_dif
table.AddRow("IntProperty", "1");
var test = new InstanceComparisonTestObject
- {
- StringProperty = "Peter Keating",
- IntProperty = 2
- };
+ {
+ StringProperty = "Peter Keating",
+ IntProperty = 2
+ };
var exception = GetExceptionThrownByThisComparison(table, test);
@@ -170,16 +209,16 @@ public void Will_property_handle_true_boolean_matches()
table.AddRow("BoolProperty", "true");
ComparisonTestResult comparisonResult = ExceptionWasThrownByThisComparison(table, new InstanceComparisonTestObject
- {
- BoolProperty = true
- });
+ {
+ BoolProperty = true
+ });
comparisonResult.ExceptionWasThrown.ShouldBeFalse(comparisonResult.ExceptionMessage);
comparisonResult = ExceptionWasThrownByThisComparison(table, new InstanceComparisonTestObject
- {
- BoolProperty = false
- });
+ {
+ BoolProperty = false
+ });
comparisonResult.ExceptionWasThrown.ShouldBeTrue(comparisonResult.ExceptionMessage);
}
@@ -191,9 +230,9 @@ public void Will_match_guids_without_case_insensitivity()
table.AddRow("GuidProperty", "DFFC3F4E-670A-400A-8212-C6841E2EA055");
ComparisonTestResult comparisonResult = ExceptionWasThrownByThisComparison(table, new InstanceComparisonTestObject
- {
- GuidProperty = new Guid("DFFC3F4E-670A-400A-8212-C6841E2EA055")
- });
+ {
+ GuidProperty = new Guid("DFFC3F4E-670A-400A-8212-C6841E2EA055")
+ });
comparisonResult.ExceptionWasThrown.ShouldBeFalse(comparisonResult.ExceptionMessage);
}
@@ -204,9 +243,9 @@ public void Will_match_decimals_regardless_of_trailing_zeroes()
var table = new Table("Field", "Value");
table.AddRow("DecimalProperty", "4.23");
var comparisonResult = ExceptionWasThrownByThisComparison(table, new InstanceComparisonTestObject
- {
- DecimalProperty = 4.23000000M
- });
+ {
+ DecimalProperty = 4.23000000M
+ });
comparisonResult.ExceptionWasThrown.ShouldBeFalse();
}
@@ -264,12 +303,12 @@ public void Can_compare_a_horizontal_table()
table.AddRow("Test", "42", "23.01", "11.56");
var test = new InstanceComparisonTestObject
- {
- StringProperty = "Test",
- IntProperty = 42,
- DecimalProperty = 23.01M,
- FloatProperty = 11.56F
- };
+ {
+ StringProperty = "Test",
+ IntProperty = 42,
+ DecimalProperty = 23.01M,
+ FloatProperty = 11.56F
+ };
var comparisonResult = ExceptionWasThrownByThisComparison(table, test);
comparisonResult.ExceptionWasThrown.ShouldBeFalse(comparisonResult.ExceptionMessage);
@@ -356,35 +395,7 @@ public void Supports_all_standard_types()
comparisonResult.ExceptionWasThrown.ShouldBeFalse(comparisonResult.ExceptionMessage);
}
- private static ComparisonException GetExceptionThrownByThisComparison(Table table, InstanceComparisonTestObject test)
- {
- try
- {
- table.CompareToInstance(test);
- }
- catch (ComparisonException ex)
- {
- return ex;
- }
- return null;
- }
-
- private static ComparisonTestResult ExceptionWasThrownByThisComparison(Table table, InstanceComparisonTestObject test)
- {
- var result = new ComparisonTestResult { ExceptionWasThrown = false };
- try
- {
- table.CompareToInstance(test);
- }
- catch (ComparisonException ex)
- {
- result.ExceptionWasThrown = true;
- result.ExceptionMessage = ex.Message;
- }
- return result;
- }
-
- private static ComparisonException GetExceptionThrownByThisComparison(Table table, StandardTypesComparisonTestObject test)
+ private static ComparisonException GetExceptionThrownByThisComparison(Table table, object test)
{
try
{
@@ -397,7 +408,7 @@ private static ComparisonException GetExceptionThrownByThisComparison(Table tabl
return null;
}
- private static ComparisonTestResult ExceptionWasThrownByThisComparison(Table table, StandardTypesComparisonTestObject test)
+ private static ComparisonTestResult ExceptionWasThrownByThisComparison(Table table, object test)
{
var result = new ComparisonTestResult { ExceptionWasThrown = false };
try
diff --git a/Tests/RuntimeTests/AssistTests/ProjectionTests.cs b/Tests/RuntimeTests/AssistTests/ProjectionTests.cs
index 8ba3ba8aa..7a13a534d 100644
--- a/Tests/RuntimeTests/AssistTests/ProjectionTests.cs
+++ b/Tests/RuntimeTests/AssistTests/ProjectionTests.cs
@@ -1,208 +1,255 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using System.Threading;
-using NUnit.Framework;
-using TechTalk.SpecFlow.Assist;
-using TechTalk.SpecFlow.RuntimeTests.AssistTests.TestInfrastructure;
-
-namespace TechTalk.SpecFlow.RuntimeTests.AssistTests
-{
- [TestFixture]
- public class ProjectionTests
- {
- private SetComparisonTestObject testInstance;
- private IEnumerable testCollection;
- private Guid testGuid1 = Guid.NewGuid();
- private Guid testGuid2 = Guid.NewGuid();
-
- [SetUp]
- public void SetUp()
- {
- Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
-
- testInstance = new SetComparisonTestObject
- {
- DateTimeProperty = DateTime.Today,
- GuidProperty = testGuid1,
- IntProperty = 1,
- StringProperty = "a"
- };
- testCollection = new[]
- {
- testInstance,
- new SetComparisonTestObject
- {
- DateTimeProperty = DateTime.Today,
- GuidProperty = testGuid2,
- IntProperty = 2,
- StringProperty = "b"
- },
- };
- }
-
- [Test]
- public void Table_with_all_columns_same_rows_and_order_should_be_sequence_equal_to_collection()
- {
- var table = CreateTableWithAllColumns();
- table.AddRow(DateTime.Today.ToString(), testGuid1.ToString(), 1.ToString(), "a");
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Threading;
+using NUnit.Framework;
+using TechTalk.SpecFlow.Assist;
+using TechTalk.SpecFlow.RuntimeTests.AssistTests.TestInfrastructure;
+
+namespace TechTalk.SpecFlow.RuntimeTests.AssistTests
+{
+ [TestFixture]
+ public class ProjectionTests
+ {
+ private SetComparisonTestObject testInstance;
+ private IEnumerable testCollection;
+ private Guid testGuid1 = Guid.NewGuid();
+ private Guid testGuid2 = Guid.NewGuid();
+
+ [SetUp]
+ public void SetUp()
+ {
+ Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US");
+
+ testInstance = new SetComparisonTestObject
+ {
+ DateTimeProperty = DateTime.Today,
+ GuidProperty = testGuid1,
+ IntProperty = 1,
+ StringProperty = "a"
+ };
+ testCollection = new[]
+ {
+ testInstance,
+ new SetComparisonTestObject
+ {
+ DateTimeProperty = DateTime.Today,
+ GuidProperty = testGuid2,
+ IntProperty = 2,
+ StringProperty = "b"
+ },
+ };
+ }
+
+ [Test]
+ public void Table_with_all_columns_same_rows_and_order_should_be_sequence_equal_to_collection()
+ {
+ var table = CreateTableWithAllColumns();
+ table.AddRow(DateTime.Today.ToString(), testGuid1.ToString(), 1.ToString(), "a");
table.AddRow(DateTime.Today.ToString(), testGuid2.ToString(), 2.ToString(), "b");
var setProjection = testCollection.ToProjection();
var tableProjection = table.ToProjection();
- Assert.IsTrue(tableProjection.SequenceEqual(setProjection));
- }
-
- [Test]
- public void Table_with_all_columns_same_rows_but_different_order_should_not_be_sequence_equal_to_collection()
- {
- var table = CreateTableWithAllColumns();
- table.AddRow(DateTime.Today.ToString(), testGuid2.ToString(), 2.ToString(), "b");
+ Assert.IsTrue(tableProjection.SequenceEqual(setProjection));
+ }
+
+ [Test]
+ public void Table_with_all_columns_same_rows_but_different_order_should_not_be_sequence_equal_to_collection()
+ {
+ var table = CreateTableWithAllColumns();
+ table.AddRow(DateTime.Today.ToString(), testGuid2.ToString(), 2.ToString(), "b");
table.AddRow(DateTime.Today.ToString(), testGuid1.ToString(), 1.ToString(), "a");
var tableProjection = table.ToProjection();
var setProjection = testCollection.ToProjection();
- Assert.IsFalse(tableProjection.SequenceEqual(setProjection));
- }
-
- [Test]
- public void Intersection_of_matching_table_and_collection_should_have_the_size_of_the_table()
- {
- var table = CreateTableWithAllColumns();
- table.AddRow(DateTime.Today.ToString(), testGuid1.ToString(), 1.ToString(), "a");
+ Assert.IsFalse(tableProjection.SequenceEqual(setProjection));
+ }
+
+ [Test]
+ public void Table_with_all_columns_same_rows_but_different_order_should_throw_comparison_exception_for_sequence_equal()
+ {
+ var table = CreateTableWithAllColumns();
+ table.AddRow(DateTime.Today.ToString(), testGuid2.ToString(), 2.ToString(), "b");
+ table.AddRow(DateTime.Today.ToString(), testGuid1.ToString(), 1.ToString(), "a");
+
+ Assert.Throws(() =>
+ table.CompareToProjectionOfSet(testCollection,
+ (x, y) => x.SequenceEqual(y)));
+ }
+
+ [Test]
+ public void Intersection_of_matching_table_and_collection_should_have_the_size_of_the_table()
+ {
+ var table = CreateTableWithAllColumns();
+ table.AddRow(DateTime.Today.ToString(), testGuid1.ToString(), 1.ToString(), "a");
table.AddRow(DateTime.Today.ToString(), testGuid2.ToString(), 2.ToString(), "b");
var tableProjection = table.ToProjection();
var setProjection = testCollection.ToProjection();
- Assert.AreEqual(table.RowCount, tableProjection.Intersect(setProjection).Count());
- }
-
- [Test]
- public void Table_with_extra_columns_should_not_match_collection()
- {
- var table = CreateTableWithAllColumns();
- table.AddRow(DateTime.Today.AddDays(100).ToString(), Guid.NewGuid().ToString(), 1.ToString(), "a");
- table.AddRow(DateTime.Today.AddDays(200).ToString(), Guid.NewGuid().ToString(), 2.ToString(), "b");
-
- var query = from x in testCollection
+ Assert.AreEqual(table.RowCount, tableProjection.Intersect(setProjection).Count());
+ }
+
+ [Test]
+ public void Table_with_extra_columns_should_not_match_collection()
+ {
+ var table = CreateTableWithAllColumns();
+ table.AddRow(DateTime.Today.AddDays(100).ToString(), Guid.NewGuid().ToString(), 1.ToString(), "a");
+ table.AddRow(DateTime.Today.AddDays(200).ToString(), Guid.NewGuid().ToString(), 2.ToString(), "b");
+
+ var query = from x in testCollection
select new { x.IntProperty, x.StringProperty };
var tableProjection = table.ToProjectionOfSet(query);
var queryProjection = query.ToProjection();
- Assert.AreEqual(table.RowCount, tableProjection.Except(queryProjection).Count());
- }
-
- [Test]
- public void Table_with_subset_of_columns_with_matching_values_should_match_collection()
- {
- var table = CreateTableWithSubsetOfColumns();
- table.AddRow(1.ToString(), "a");
- table.AddRow(2.ToString(), "b");
-
- var query = from x in testCollection
+ Assert.AreEqual(table.RowCount, tableProjection.Except(queryProjection).Count());
+ }
+
+ [Test]
+ public void Table_with_extra_columns_should_throw_comparison_exception_on_except()
+ {
+ var table = CreateTableWithAllColumns();
+ table.AddRow(DateTime.Today.AddDays(100).ToString(), Guid.NewGuid().ToString(), 1.ToString(), "a");
+ table.AddRow(DateTime.Today.AddDays(200).ToString(), Guid.NewGuid().ToString(), 2.ToString(), "b");
+
+ var query = from x in testCollection
+ select new { x.IntProperty, x.StringProperty };
+
+ Assert.Throws(() =>
+ table.CompareToProjectionOfSet(query,
+ (x, y) => x.Except(y), "StringProperty"));
+ }
+
+ [Test]
+ public void Table_with_subset_of_columns_with_matching_values_should_match_collection()
+ {
+ var table = CreateTableWithSubsetOfColumns();
+ table.AddRow(1.ToString(), "a");
+ table.AddRow(2.ToString(), "b");
+
+ var query = from x in testCollection
select new { x.GuidProperty, x.IntProperty, x.StringProperty };
var tableProjection = table.ToProjectionOfSet(query);
var queryProjection = query.ToProjection();
- Assert.AreEqual(0, tableProjection.Except(queryProjection).Count());
- }
-
- [Test]
- public void Table_with_subset_of_columns_with_matching_values_and_order_should_be_sequence_equal_to_collection()
- {
- var table = CreateTableWithSubsetOfColumns();
- table.AddRow(1.ToString(), "a");
- table.AddRow(2.ToString(), "b");
-
- var query = from x in testCollection
+ Assert.AreEqual(0, tableProjection.Except(queryProjection).Count());
+ }
+
+ [Test]
+ public void Table_with_subset_of_columns_with_matching_values_and_order_should_be_sequence_equal_to_collection()
+ {
+ var table = CreateTableWithSubsetOfColumns();
+ table.AddRow(1.ToString(), "a");
+ table.AddRow(2.ToString(), "b");
+
+ var query = from x in testCollection
select new { x.GuidProperty, x.IntProperty, x.StringProperty };
var tableProjection = table.ToProjectionOfSet(query);
var queryProjection = query.ToProjection();
- Assert.IsTrue(tableProjection.SequenceEqual(queryProjection));
- }
-
- [Test]
- public void Table_with_all_columns_same_rows_and_order_should_be_sequence_equal_to_queryable_collection()
- {
- var table = CreateTableWithAllColumns();
- table.AddRow(DateTime.Today.ToString(), testGuid1.ToString(), 1.ToString(), "a");
- table.AddRow(DateTime.Today.ToString(), testGuid2.ToString(), 2.ToString(), "b");
-
+ Assert.IsTrue(tableProjection.SequenceEqual(queryProjection));
+ }
+
+ [Test]
+ public void Table_with_all_columns_same_rows_and_order_should_be_sequence_equal_to_queryable_collection()
+ {
+ var table = CreateTableWithAllColumns();
+ table.AddRow(DateTime.Today.ToString(), testGuid1.ToString(), 1.ToString(), "a");
+ table.AddRow(DateTime.Today.ToString(), testGuid2.ToString(), 2.ToString(), "b");
+
var query = testCollection.AsQueryable();
var tableProjection = table.ToProjectionOfSet(query);
var queryProjection = query.ToProjection();
- Assert.IsTrue(tableProjection.SequenceEqual(queryProjection));
- }
-
- [Test]
- public void Table_with_all_columns_same_rows_and_order_should_be_sequence_equal_to_list()
- {
- var table = CreateTableWithAllColumns();
- table.AddRow(DateTime.Today.ToString(), testGuid1.ToString(), 1.ToString(), "a");
- table.AddRow(DateTime.Today.ToString(), testGuid2.ToString(), 2.ToString(), "b");
-
+ Assert.IsTrue(tableProjection.SequenceEqual(queryProjection));
+ }
+
+ [Test]
+ public void Table_with_all_columns_same_rows_and_order_should_be_sequence_equal_to_list()
+ {
+ var table = CreateTableWithAllColumns();
+ table.AddRow(DateTime.Today.ToString(), testGuid1.ToString(), 1.ToString(), "a");
+ table.AddRow(DateTime.Today.ToString(), testGuid2.ToString(), 2.ToString(), "b");
+
var query = testCollection.ToList();
var tableProjection = table.ToProjectionOfSet(query);
var queryProjection = query.ToProjection();
- Assert.IsTrue(tableProjection.SequenceEqual(queryProjection));
- }
-
- [Test]
- public void Table_with_single_element_and_all_columns_should_be_equal_to_matching_instance()
- {
- var table = CreateTableWithAllColumns();
+ Assert.IsTrue(tableProjection.SequenceEqual(queryProjection));
+ }
+
+ [Test]
+ public void Table_with_single_element_and_all_columns_should_be_equal_to_matching_instance()
+ {
+ var table = CreateTableWithAllColumns();
table.AddRow(DateTime.Today.ToString(), testGuid1.ToString(), 1.ToString(), "a");
var tableProjection = table.ToProjection();
- Assert.AreEqual(tableProjection, testInstance);
- }
-
- [Test]
- public void Table_with_single_element_and_all_columns_should_not_be_equal_to_unmatching_instance()
- {
- var table = CreateTableWithAllColumns();
+ Assert.AreEqual(tableProjection, testInstance);
+ }
+
+ [Test]
+ public void Table_with_single_element_and_all_columns_should_not_be_equal_to_unmatching_instance()
+ {
+ var table = CreateTableWithAllColumns();
table.AddRow(DateTime.Today.ToString(), Guid.NewGuid().ToString(), 1.ToString(), "b");
var tableProjection = table.ToProjection();
- Assert.AreNotEqual(tableProjection, testInstance);
- }
-
- [Test]
- public void Table_with_subset_of_columns_should_be_equal_to_matching_instance()
- {
- var table = CreateTableWithSubsetOfColumns();
- table.AddRow(1.ToString(), "a");
-
+ Assert.AreNotEqual(tableProjection, testInstance);
+ }
+
+ [Test]
+ public void Table_with_single_element_and_all_columns_should_throw_comparison_exception_for_unmatching_instance()
+ {
+ var table = CreateTableWithAllColumns();
+ table.AddRow(DateTime.Today.ToString(), Guid.NewGuid().ToString(), 1.ToString(), "b");
+
+ Assert.Throws(() => table.CompareToProjectionOfInstance(testInstance));
+ }
+
+ [Test]
+ public void Table_with_subset_of_columns_should_be_equal_to_matching_instance()
+ {
+ var table = CreateTableWithSubsetOfColumns();
+ table.AddRow(1.ToString(), "a");
+
var instance = new { IntProperty = testInstance.IntProperty, StringProperty = testInstance.StringProperty };
var tableProjection = table.ToProjectionOfInstance(instance);
- Assert.AreEqual(tableProjection, instance);
- }
-
- [Test]
- public void Table_with_subset_of_columns_should_not_be_equal_to_unmatching_instance()
- {
- var table = CreateTableWithSubsetOfColumns();
- table.AddRow(1.ToString(), "b");
-
+ Assert.AreEqual(tableProjection, instance);
+ }
+
+ [Test]
+ public void Table_with_subset_of_columns_should_not_be_equal_to_unmatching_instance()
+ {
+ var table = CreateTableWithSubsetOfColumns();
+ table.AddRow(1.ToString(), "b");
+
var instance = new { IntProperty = testInstance.IntProperty, StringProperty = testInstance.StringProperty };
var tableProjection = table.ToProjectionOfInstance(instance);
- Assert.AreNotEqual(tableProjection, instance);
- }
-
- private Table CreateTableWithAllColumns()
- {
- return new Table("DateTimeProperty", "GuidProperty", "IntProperty", "StringProperty");
- }
-
- private Table CreateTableWithSubsetOfColumns()
- {
- return new Table("IntProperty", "StringProperty");
- }
- }
-}
+ Assert.AreNotEqual(tableProjection, instance);
+ }
+
+ [Test]
+ public void Table_with_subset_of_columns_should_throw_comparison_exception_for_unmatching_instance()
+ {
+ var table = CreateTableWithSubsetOfColumns();
+ table.AddRow(1.ToString(), "b");
+
+ var instance = new { IntProperty = testInstance.IntProperty, StringProperty = testInstance.StringProperty };
+
+ Assert.Throws(() => table.CompareToProjectionOfInstance(instance));
+ }
+
+ private Table CreateTableWithAllColumns()
+ {
+ return new Table("DateTimeProperty", "GuidProperty", "IntProperty", "StringProperty");
+ }
+
+ private Table CreateTableWithSubsetOfColumns()
+ {
+ return new Table("IntProperty", "StringProperty");
+ }
+ }
+}
diff --git a/Tests/RuntimeTests/AssistTests/PropertyExtensionMethodsTests.cs b/Tests/RuntimeTests/AssistTests/PropertyExtensionMethodsTests.cs
index 87976115f..f81c0dfe1 100644
--- a/Tests/RuntimeTests/AssistTests/PropertyExtensionMethodsTests.cs
+++ b/Tests/RuntimeTests/AssistTests/PropertyExtensionMethodsTests.cs
@@ -14,7 +14,7 @@ public void Can_get_the_property_of_an_object_through_GetPropertyValue()
const string expectedValue = "John Galt";
var person = new Person { FullName = expectedValue };
- var value = person.GetPropertyValue("FullName");
+ var value = person.GetMemberValue("FullName");
Assert.AreEqual(expectedValue, value);
}
@@ -24,7 +24,7 @@ public void Can_get_the_property_of_an_object_even_if_the_name_has_extra_spaces(
{
var person = new Person {FullName = "Howard Roark"};
- person.GetPropertyValue("Full Name")
+ person.GetMemberValue("Full Name")
.ShouldEqual("Howard Roark");
}
@@ -33,7 +33,7 @@ public void Can_get_the_property_of_an_object_even_if_the_casing_is_wrong()
{
var person = new Person { FullName = "Howard Roark" };
- person.GetPropertyValue("fullname")
+ person.GetMemberValue("fullname")
.ShouldEqual("Howard Roark");
}
@@ -43,7 +43,7 @@ public void Can_set_the_value_on_the_property_through_SetPropertyValue()
const string expectedValue = "John Galt";
var person = new Person { FullName = "Howard Roark" };
- person.SetPropertyValue("FullName", expectedValue);
+ person.SetMemberValue("FullName", expectedValue);
Assert.AreEqual(expectedValue, person.FullName);
}
@@ -52,7 +52,7 @@ public void Can_set_the_value_on_the_property_through_SetPropertyValue()
public void Can_set_the_value_on_the_property_regardless_of_spaces()
{
var person = new Person { FullName = "Howard Roark" };
- person.SetPropertyValue("Full Name", "John Galt");
+ person.SetMemberValue("Full Name", "John Galt");
person.FullName.ShouldEqual("John Galt");
}
@@ -61,14 +61,34 @@ public void Can_set_the_value_on_the_property_regardless_of_spaces()
public void Can_set_the_value_on_the_property_regardless_of_casing()
{
var person = new Person { FullName = "Howard Roark" };
- person.SetPropertyValue("full name", "John Galt");
+ person.SetMemberValue("full name", "John Galt");
person.FullName.ShouldEqual("John Galt");
}
+ [Test]
+ public void Can_set_the_value_on_the_property_regardless_of_hyphen()
+ {
+ var person = new Person { NoBreakSupplier = "Howard Roark" };
+ person.SetMemberValue("No-Break Supplier", "John Galt");
+
+ person.NoBreakSupplier.ShouldEqual("John Galt");
+ }
+
+ [Test]
+ public void Can_set_the_value_on_the_property_regardless_of_question_mark()
+ {
+ var person = new Person { ClientProfile = true };
+ person.SetMemberValue("Client Profile?", true);
+
+ person.ClientProfile.ShouldEqual(true);
+ }
+
public class Person
{
- public string FullName { get; set; }
+ public string FullName { get; set; }
+ public string NoBreakSupplier { get; set; }
+ public bool ClientProfile { get; set; }
}
}
}
diff --git a/Tests/RuntimeTests/AssistTests/SetComparisonExtensionMethods_MessageTests.cs b/Tests/RuntimeTests/AssistTests/SetComparisonExtensionMethods_MessageTests.cs
index 4175e4b2e..37caba02e 100644
--- a/Tests/RuntimeTests/AssistTests/SetComparisonExtensionMethods_MessageTests.cs
+++ b/Tests/RuntimeTests/AssistTests/SetComparisonExtensionMethods_MessageTests.cs
@@ -10,6 +10,39 @@ public class SetComparisonExtensionMethods_MessageTests
{
[Test]
public void Returns_the_names_of_any_fields_that_do_not_exist()
+ {
+ var table = new Table("StringField", "AFieldThatDoesNotExist", "AnotherFieldThatDoesNotExist");
+
+ var items = new[] { new SetComparisonTestObjectWithFields(), };
+
+ var exception = GetTheExceptionThrowByComparingThese(table, items);
+
+ exception.Message.AgnosticLineBreak().ShouldEqual(
+ @"The following fields do not exist:
+AFieldThatDoesNotExist
+AnotherFieldThatDoesNotExist".AgnosticLineBreak());
+ }
+
+ [Test]
+ public void Returns_descriptive_message_when_two_results_exist_for_the_field_but_there_should_be_no_results()
+ {
+ var table = new Table("IntField");
+
+ var items = new[] { new SetComparisonTestObjectWithFields(), new SetComparisonTestObjectWithFields(), };
+
+ var exception = GetTheExceptionThrowByComparingThese(table, items);
+
+ exception.Message.AgnosticLineBreak().ShouldEqual(
+ @"
+ | IntField |
++ | 0 |
++ | 0 |
+".AgnosticLineBreak());
+ }
+
+
+ [Test]
+ public void Returns_the_names_of_any_properties_that_do_not_exist()
{
var table = new Table("StringProperty", "AFieldThatDoesNotExist", "AnotherFieldThatDoesNotExist");
@@ -182,5 +215,18 @@ private static ComparisonException GetTheExceptionThrowByComparingThese(Table ta
}
return null;
}
+
+ private static ComparisonException GetTheExceptionThrowByComparingThese(Table table, SetComparisonTestObjectWithFields[] items)
+ {
+ try
+ {
+ table.CompareToSet(items);
+ }
+ catch (ComparisonException ex)
+ {
+ return ex;
+ }
+ return null;
+ }
}
}
\ No newline at end of file
diff --git a/Tests/RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateSetHelperMethodTests_WithFunc.cs b/Tests/RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateSetHelperMethodTests_WithFunc.cs
index 907487d91..17bef9c7e 100644
--- a/Tests/RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateSetHelperMethodTests_WithFunc.cs
+++ b/Tests/RuntimeTests/AssistTests/TableHelperExtensionMethods/CreateSetHelperMethodTests_WithFunc.cs
@@ -71,5 +71,23 @@ public void Still_loads_the_instance_with_the_values_from_the_table()
ObjectAssertExtensions.ShouldEqual(people.First().FirstName, "John");
ObjectAssertExtensions.ShouldEqual(people.Last().FirstName, "Howard");
}
+
+ [Test]
+ public void Calls_instance_creation_method_using_row_as_parameter()
+ {
+ var table = new Table("FullName", "Sex", "IsRational");
+ table.AddRow("John Smith", "Male", "False");
+ table.AddRow("Howard Jones", "Male", "True");
+
+ var people = table.CreateSet(row => new Person { FirstName = row.GetString("FullName").Split(' ').First() });
+
+ var john = people.First();
+ var howard = people.Last();
+
+ ObjectAssertExtensions.ShouldEqual(john.FirstName, "John");
+ ObjectAssertExtensions.ShouldEqual(john.IsRational, false);
+ ObjectAssertExtensions.ShouldEqual(howard.FirstName, "Howard");
+ ObjectAssertExtensions.ShouldEqual(howard.IsRational, true);
+ }
}
}
\ No newline at end of file
diff --git a/Tests/RuntimeTests/AssistTests/TestInfrastructure/InstanceComparisonTestObjectWithFields.cs b/Tests/RuntimeTests/AssistTests/TestInfrastructure/InstanceComparisonTestObjectWithFields.cs
new file mode 100644
index 000000000..1abf33b35
--- /dev/null
+++ b/Tests/RuntimeTests/AssistTests/TestInfrastructure/InstanceComparisonTestObjectWithFields.cs
@@ -0,0 +1,13 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace TechTalk.SpecFlow.RuntimeTests.AssistTests.TestInfrastructure
+{
+ public class InstanceComparisonTestObjectWithFields
+ {
+ public string StringField;
+ public int IntField;
+ }
+}
diff --git a/Tests/RuntimeTests/AssistTests/TestInfrastructure/SetComparisonTestObject.cs b/Tests/RuntimeTests/AssistTests/TestInfrastructure/SetComparisonTestObject.cs
index 656ae9d8c..2fa528e76 100644
--- a/Tests/RuntimeTests/AssistTests/TestInfrastructure/SetComparisonTestObject.cs
+++ b/Tests/RuntimeTests/AssistTests/TestInfrastructure/SetComparisonTestObject.cs
@@ -12,4 +12,11 @@ class SetComparisonTestObject
public Guid GuidProperty { get; set; }
}
+
+ class SetComparisonTestObjectWithFields
+ {
+ public string StringField;
+ public int IntField;
+
+ }
}
\ No newline at end of file
diff --git a/Tests/RuntimeTests/AssistTests/ValueRetrieverTests/EnumValueRetrieverTests.cs b/Tests/RuntimeTests/AssistTests/ValueRetrieverTests/EnumValueRetrieverTests.cs
index 31f42c48e..6a49ad3e3 100644
--- a/Tests/RuntimeTests/AssistTests/ValueRetrieverTests/EnumValueRetrieverTests.cs
+++ b/Tests/RuntimeTests/AssistTests/ValueRetrieverTests/EnumValueRetrieverTests.cs
@@ -92,7 +92,7 @@ public void Throws_an_exception_when_the_value_is_empty()
}
[Test]
- public void Does_not_throw_an_exception_when_the_value_is_null_and_enum_type_is_not_nullable()
+ public void Does_not_throw_an_exception_when_the_value_is_null_and_enum_type_is_nullable()
{
var retriever = new EnumValueRetriever();
@@ -101,30 +101,35 @@ public void Does_not_throw_an_exception_when_the_value_is_null_and_enum_type_is_
{
retriever.GetValue(null, typeof (Sex?));
}
- catch (InvalidOperationException exception)
+ catch (InvalidOperationException)
{
- if (exception.Message == "No enum with value {null} found")
- exceptionThrown = true;
+ exceptionThrown = true;
}
exceptionThrown.ShouldBeFalse();
}
[Test]
- public void Does_not_throw_an_exception_when_the_value_is_empty_and_enum_type_is_not_nullable()
+ public void Does_not_throw_an_exception_when_the_value_is_empty_and_enum_type_is_nullable()
{
var retriever = new EnumValueRetriever();
var exceptionThrown = false;
try
{
- retriever.GetValue(string.Empty, typeof (Sex));
+ retriever.GetValue(string.Empty, typeof (Sex?));
}
- catch (InvalidOperationException exception)
+ catch (InvalidOperationException)
{
- if (exception.Message == "No enum with value {empty} found")
- exceptionThrown = true;
+ exceptionThrown = true;
}
- exceptionThrown.ShouldBeTrue();
+ exceptionThrown.ShouldBeFalse();
+ }
+
+ [Test]
+ public void Should_return_null_when_the_value_is_empty_and_enum_type_is_nullable()
+ {
+ var retriever = new EnumValueRetriever();
+ retriever.GetValue(string.Empty, typeof(Sex?)).ShouldBeNull();
}
[Test]
diff --git a/Tests/RuntimeTests/RuntimeTests.csproj b/Tests/RuntimeTests/RuntimeTests.csproj
index 5a6e23f06..7630d1ab2 100644
--- a/Tests/RuntimeTests/RuntimeTests.csproj
+++ b/Tests/RuntimeTests/RuntimeTests.csproj
@@ -80,6 +80,7 @@
+
@@ -168,25 +169,14 @@
+
-
- {453D8014-B6CD-4E86-80A8-D59F59092334}
- TechTalk.SpecFlow.Generator
-
-
- {7CCEF6D6-FC17-422E-9BED-EDD752B6496F}
- TechTalk.SpecFlow.Parser
-
{413EE28C-4F89-4C6F-BA1E-2CDEE4CD43B4}
TechTalk.SpecFlow
-
- {C0AF4A43-0C3B-47C7-86DE-79FB632B1453}
- TechTalk.SpecFlow.Utils
-
diff --git a/Tests/RuntimeTests/StepArgumentTypeConverterTest.cs b/Tests/RuntimeTests/StepArgumentTypeConverterTest.cs
index 8d1c6b75e..3aa587bd6 100644
--- a/Tests/RuntimeTests/StepArgumentTypeConverterTest.cs
+++ b/Tests/RuntimeTests/StepArgumentTypeConverterTest.cs
@@ -67,6 +67,13 @@ public void ShouldConvertStringToEnumerationType()
Assert.That(result, Is.EqualTo(TestEnumeration.Value1));
}
+ [Test]
+ public void ShouldConvertStringToEnumerationTypeWithSpaces()
+ {
+ var result = _stepArgumentTypeConverter.Convert("Value 1", typeof(TestEnumeration), _enUSCulture);
+ Assert.That(result, Is.EqualTo(TestEnumeration.Value1));
+ }
+
[Test]
public void ShouldConvertStringToEnumerationTypeWithDifferingCase()
{
diff --git a/Tests/RuntimeTests/StepExecutionTests.cs b/Tests/RuntimeTests/StepExecutionTests.cs
index 64fd9ccaf..c0c35f826 100644
--- a/Tests/RuntimeTests/StepExecutionTests.cs
+++ b/Tests/RuntimeTests/StepExecutionTests.cs
@@ -1,5 +1,7 @@
using System;
using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
using NUnit.Framework;
using Rhino.Mocks;
using TechTalk.SpecFlow.Infrastructure;
@@ -75,6 +77,13 @@ public virtual void DistinguishByTableParam2(Table table)
{
}
+
+
+ [Given("Returns a Task")]
+ public virtual Task ReturnsATask()
+ {
+ throw new NotSupportedException("should be mocked");
+ }
}
[Binding]
@@ -275,6 +284,54 @@ public void SholdRaiseBindingErrorIfWrongParamNumber()
MockRepository.VerifyAll();
}
+ [Test]
+ public void SholdCallBindingThatReturnsTask()
+ {
+ StepExecutionTestsBindings bindingInstance;
+ TestRunner testRunner = GetTestRunnerFor(out bindingInstance);
+
+ bool taskFinished = false;
+
+ bindingInstance.Expect(b => b.ReturnsATask()).Return(Task.Factory.StartNew(() =>
+ {
+ Thread.Sleep(800);
+ taskFinished = true;
+ }));
+
+ MockRepository.ReplayAll();
+
+ testRunner.Given("Returns a Task");
+ Assert.IsTrue(taskFinished);
+ Assert.AreEqual(TestStatus.OK, GetLastTestStatus());
+ MockRepository.VerifyAll();
+ }
+
+ [Test]
+ public void SholdCallBindingThatReturnsTaskAndReportError()
+ {
+ StepExecutionTestsBindings bindingInstance;
+ TestRunner testRunner = GetTestRunnerFor(out bindingInstance);
+
+ bool taskFinished = false;
+
+ bindingInstance.Expect(b => b.ReturnsATask()).Return(Task.Factory.StartNew(() =>
+ {
+ Thread.Sleep(800);
+ taskFinished = true;
+ throw new Exception("catch meee");
+ }));
+
+ MockRepository.ReplayAll();
+
+ testRunner.Given("Returns a Task");
+ Assert.IsTrue(taskFinished);
+ Assert.AreEqual(TestStatus.TestError, GetLastTestStatus());
+ Assert.AreEqual("catch meee", ContextManagerStub.ScenarioContext.TestError.Message);
+
+ MockRepository.VerifyAll();
+ }
+
+
}
}
diff --git a/Tests/RuntimeTests/StepExecutionTestsBase.cs b/Tests/RuntimeTests/StepExecutionTestsBase.cs
index 68f8dd1e6..90de3c7ec 100644
--- a/Tests/RuntimeTests/StepExecutionTestsBase.cs
+++ b/Tests/RuntimeTests/StepExecutionTestsBase.cs
@@ -10,7 +10,6 @@
using TechTalk.SpecFlow.Bindings.Reflection;
using TechTalk.SpecFlow.Infrastructure;
using TechTalk.SpecFlow.Tracing;
-using TechTalk.SpecFlow.Utils;
using MockRepository = Rhino.Mocks.MockRepository;
using TestStatus = TechTalk.SpecFlow.Infrastructure.TestStatus;
diff --git a/Tests/RuntimeTests/StepTransformationTests.cs b/Tests/RuntimeTests/StepTransformationTests.cs
index aa08878f0..5dfa18065 100644
--- a/Tests/RuntimeTests/StepTransformationTests.cs
+++ b/Tests/RuntimeTests/StepTransformationTests.cs
@@ -1,131 +1,168 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using System.Reflection;
-using Moq;
-using NUnit.Framework;
-using TechTalk.SpecFlow.Bindings;
-using TechTalk.SpecFlow.Bindings.Reflection;
-using TechTalk.SpecFlow.Configuration;
-using TechTalk.SpecFlow.ErrorHandling;
-using TechTalk.SpecFlow.Infrastructure;
-using TechTalk.SpecFlow.Tracing;
-
-namespace TechTalk.SpecFlow.RuntimeTests
-{
- public class User
- {
- public string Name { get; set; }
- }
-
- [Binding]
- public class UserCreator
- {
- [StepArgumentTransformation("user (w+)")]
- public User Create(string name)
- {
- return new User {Name = name};
- }
-
- [StepArgumentTransformation]
- public IEnumerable CreateUsers(Table table)
- {
- return table.Rows.Select(tableRow =>
- new User { Name = tableRow["Name"] });
- }
- }
-
- [TestFixture]
- public class StepTransformationTests
- {
- private readonly Mock bindingRegistryStub = new Mock();
- private readonly Mock contextManagerStub = new Mock();
- private readonly Mock methodBindingInvokerStub = new Mock();
- private readonly List stepTransformations = new List();
-
- [SetUp]
- public void SetUp()
- {
- // ScenarioContext is needed, because the [Binding]-instances live there
- var scenarioContext = new ScenarioContext(null, null, null);
- contextManagerStub.Setup(cm => cm.ScenarioContext).Returns(scenarioContext);
-
- bindingRegistryStub.Setup(br => br.GetStepTransformations()).Returns(stepTransformations);
- }
-
- private IStepArgumentTransformationBinding CreateStepTransformationBinding(string regexString, IBindingMethod transformMethod)
- {
- return new StepArgumentTransformationBinding(regexString, transformMethod);
- }
-
- private IStepArgumentTransformationBinding CreateStepTransformationBinding(string regexString, MethodInfo transformMethod)
- {
- return new StepArgumentTransformationBinding(regexString, new RuntimeBindingMethod(transformMethod));
- }
-
- [Test]
- public void UserConverterShouldConvertStringToUser()
- {
- UserCreator stepTransformationInstance = new UserCreator();
- var transformMethod = stepTransformationInstance.GetType().GetMethod("Create");
- var stepTransformationBinding = CreateStepTransformationBinding(@"user (\w+)", transformMethod);
-
- Assert.True(stepTransformationBinding.Regex.IsMatch("user xyz"));
-
- var invoker = new BindingInvoker(new RuntimeConfiguration(), new Mock().Object);
- TimeSpan duration;
- var result = invoker.InvokeBinding(stepTransformationBinding, contextManagerStub.Object, new object[] { "xyz" }, new Mock().Object, out duration);
- Assert.NotNull(result);
- Assert.That(result.GetType(), Is.EqualTo(typeof(User)));
- Assert.That(((User)result).Name, Is.EqualTo("xyz"));
- }
-
- [Test]
- public void StepArgumentTypeConverterShouldUseUserConverterForConversion()
- {
- UserCreator stepTransformationInstance = new UserCreator();
- var transformMethod = new RuntimeBindingMethod(stepTransformationInstance.GetType().GetMethod("Create"));
- var stepTransformationBinding = CreateStepTransformationBinding(@"user (\w+)", transformMethod);
- stepTransformations.Add(stepTransformationBinding);
- TimeSpan duration;
- var resultUser = new User();
- methodBindingInvokerStub.Setup(i => i.InvokeBinding(stepTransformationBinding, It.IsAny(), It.IsAny