Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,40 @@ protected string[] InheritedArrayInput2

public class ExpressionExtensionsTests : BaseClass
{
private class ContainerType
{
public int Target { get; set; }

public string Target2 { get; set; }

public ContainerType SubContainer { get; set; }

public override string ToString()
{
return Target2;
}
}

class ClassUnderTest
{
public void MethodWithoutArguments()
{

}

public void MethodWithInputs(int input1, string input2)
{

}

public void MethodWithArrayInputs(int[] input1, string[] input2)
{


}

public void MethodWithInputs(ContainerType subContainer)
{

}
}

Expand Down Expand Up @@ -89,18 +108,22 @@ string GetInput2(string someInput)
return someInput + " Input 2";
}

ContainerType container = new ContainerType();

[Test]
public void NoArguments()
{
var arguments = GetArguments(x => x.MethodWithoutArguments(), new ClassUnderTest());
Assert.That(arguments.Length, Is.EqualTo(0));
}

void AssertReturnedArguments(object[] arguments, object expectedArg1, object expectedArg2)
void AssertReturnedArguments(object[] arguments, params object[] expectedArgs)
{
Assert.That(arguments.Length, Is.EqualTo(2));
Assert.That(arguments[0], Is.EqualTo(expectedArg1));
Assert.That(arguments[1], Is.EqualTo(expectedArg2));
Assert.That(arguments.Length, Is.EqualTo(expectedArgs.Length));
for (int i = 0; i < expectedArgs.Length; i++)
{
Assert.That(arguments[i], Is.EqualTo(expectedArgs[i]));
}
}

[Test]
Expand Down Expand Up @@ -132,14 +155,14 @@ public void InputArgumentsProvidedUsingProperty()
var arguments = GetArguments(x => x.MethodWithInputs(Input1, Input2), new ClassUnderTest());
AssertReturnedArguments(arguments, Input1, Input2);
}

[Test]
public void InputArgumentsProvidedUsingInheritedFields()
{
var arguments = GetArguments(x => x.MethodWithInputs(InheritedInput1, InheritedInput2), new ClassUnderTest());
AssertReturnedArguments(arguments, InheritedInput1, InheritedInput2);
}

[Test]
public void InputArgumentsProvidedUsingMethodCallDoesNotThrow()
{
Expand All @@ -150,14 +173,14 @@ public void InputArgumentsProvidedUsingMethodCallDoesNotThrow()
public void ArrayInputsArgumentsProvidedInline()
{
var arguments = GetArguments(x => x.MethodWithArrayInputs(new[] { 1, 2 }, new[] { "3", "4" }), new ClassUnderTest());
AssertReturnedArguments(arguments, new[] {1, 2}, new[] {"3", "4"});
AssertReturnedArguments(arguments, new[] { 1, 2 }, new[] { "3", "4" });
}

[Test]
public void ArrayInputArgumentsProvidedUsingVariables()
{
var input1 = new[] {1, 2};
var input2 = new[] {"3", "4"};
var input1 = new[] { 1, 2 };
var input2 = new[] { "3", "4" };
var arguments = GetArguments(x => x.MethodWithArrayInputs(input1, input2), new ClassUnderTest());
AssertReturnedArguments(arguments, input1, input2);
}
Expand All @@ -176,6 +199,33 @@ public void ArrayInputArgumentsProvidedUsingProperty()
AssertReturnedArguments(arguments, ArrayInput1, ArrayInput2);
}

[Test]
public void ComplexArgument()
{
container.Target = 1;
container.SubContainer = new ContainerType { Target2 = "Foo" };

var arguments = GetArguments(x => x.MethodWithInputs(container.Target, container.SubContainer.Target2), new ClassUnderTest());
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This blew up before. Much nicer now :)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. Man I had to read the code again to understand how these tests worked!! Thanks for adding the tests.

AssertReturnedArguments(arguments, 1, "Foo");
}

[Test]
public void ComplexArgument2()
{
container.SubContainer = new ContainerType { Target2 = "Foo" };

var arguments = GetArguments(x => x.MethodWithInputs(container.SubContainer), new ClassUnderTest());
AssertReturnedArguments(arguments, container.SubContainer);
}

[Test]
public void ComplexArgumentWhenContainerIsNull()
{
ContainerType nullContainer = null;
var arguments = GetArguments(x => x.MethodWithInputs(nullContainer.SubContainer), new ClassUnderTest());
AssertReturnedArguments(arguments, new object[] { null });
}

[Test]
public void ArrayInputArgumentsProvidedUsingInheritedProperty()
{
Expand Down
22 changes: 20 additions & 2 deletions TestStack.BDDfy.Tests/Scanner/FluentScanner/FluentWithExamples.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using ApprovalTests;
using System.Runtime.CompilerServices;
using ApprovalTests;
using NUnit.Framework;
using Shouldly;
using TestStack.BDDfy.Reporters;
Expand Down Expand Up @@ -31,6 +32,22 @@ public void FluentCanBeUsedWithExamples()
Approvals.Verify(textReporter.ToString());
}

[Test]
[MethodImpl(MethodImplOptions.NoInlining)]
public void ExampleTypeMismatch()
{
var ex = Should.Throw<UnassignableExampleException>(
() => this.Given(() => WrongType.ShouldBe(1), "Given i use an example")
.WithExamples(new ExampleTable("Wrong type")
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard to diagnose before. Was an invalid cast exception

{
new object(),
new object[] { null }
})
.BDDfy());

ex.Message.ShouldBe("System.Object cannot be assigned to Int32 (Column: 'Wrong type', Row: 1)");
}

private void AndIUseA(string multiWordHeading)
{
multiWordHeading.ShouldBeOneOf("", "val2");
Expand All @@ -44,7 +61,7 @@ private void GivenADifferentMethodWith(string prop2)

private void GivenADifferentMethodWithRandomArg(int foo)
{

}

private void ThenAllIsGood()
Expand All @@ -63,6 +80,7 @@ private void GivenMethodTaking__ExampleInt__(int exampleInt)
exampleInt.ShouldBeInRange(1, 2);
}

public int WrongType { get; set; }
public int Prop1 { get; set; }
private string _prop2 = null;
private string multiWordHeading = null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using NUnit.Framework;
using Shouldly;

namespace TestStack.BDDfy.Tests.Scanner.StepScanners.Examples
{
public class ExampleValueTests
{
[Test]
public void CanFormatAsStringTests()
{
new ExampleValue("Header", null, () => 0).GetValueAsString().ShouldBe("'null'");
new ExampleValue("Header", 1, () => 0).GetValueAsString().ShouldBe("1");
new ExampleValue("Header", new Object(), () => 0).GetValueAsString().ShouldBe("System.Object");
new ExampleValue("Header", new[] {1, 2}, () => 0).GetValueAsString().ShouldBe("1, 2");
}
}
}
1 change: 1 addition & 0 deletions TestStack.BDDfy.Tests/TestStack.BDDfy.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@
<Compile Include="Scanner\FluentScanner\InlineAssertions.cs" />
<Compile Include="Scanner\ReflectiveScanner\ReflectiveWithExamples.cs" />
<Compile Include="Scanner\StepScanners\Examples\ExampleTableTests.cs" />
<Compile Include="Scanner\StepScanners\Examples\ExampleValueTests.cs" />
<Compile Include="Scanner\WhenStepScannerFactoryAsyncMethods.cs" />
<Compile Include="Configuration\CustomProcessor.cs" />
<Compile Include="Configuration\BatchProcessorsTests.cs" />
Expand Down
2 changes: 1 addition & 1 deletion TestStack.BDDfy/Reporters/Html/ClassicReportBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ private void AddExampleRow(Scenario scenario, Result scenarioResult)
{
AddLine(string.Format("<td><Span class='{0}' style='margin-right:4px;' /></td>", scenario.Result));
foreach (var exampleValue in scenario.Example.Values)
AddLine(string.Format("<td>{0}</td>", HttpUtility.HtmlEncode(exampleValue.GetValue(typeof(string)))));
AddLine(string.Format("<td>{0}</td>", HttpUtility.HtmlEncode(exampleValue.GetValueAsString())));

if (scenarioResult != Result.Failed)
return;
Expand Down
2 changes: 1 addition & 1 deletion TestStack.BDDfy/Reporters/Html/MetroReportBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,7 @@ private void AddExampleRow(Scenario scenario, Result scenarioResult)
{
AddLine(string.Format("<td><Span class='{0}' style='margin-right:4px;' /></td>", scenario.Result));
foreach (var exampleValue in scenario.Example.Values)
AddLine(string.Format("<td>{0}</td>", HttpUtility.HtmlEncode(exampleValue.GetValue(typeof(string)))));
AddLine(string.Format("<td>{0}</td>", HttpUtility.HtmlEncode(exampleValue.GetValueAsString())));

if (scenarioResult != Result.Failed)
return;
Expand Down
2 changes: 1 addition & 1 deletion TestStack.BDDfy/Reporters/TextReporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ private void WriteExamples(Scenario exampleScenario, IEnumerable<Scenario> scena
? null
: string.Format("Step: {0} failed with exception: {1}", failingStep.Title, CreateExceptionMessage(failingStep));

addRow(scenario.Example.Values.Select(e => (string)e.GetValue(typeof(string))), scenario.Result.ToString(), error);
addRow(scenario.Example.Values.Select(e => e.GetValueAsString()), scenario.Result.ToString(), error);
}

foreach (var row in rows)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System;
using System.Linq;

namespace TestStack.BDDfy
{
internal static class ArgumentCleaningExtensions
{
internal static object[] FlattenArrays(this object[] inputs)
{
return inputs.Select(FlattenArray).ToArray();
}

public static object FlattenArray(this object input)
{
var inputArray = input as Array;
if (inputArray != null)
{
var temp = (from object arrElement in inputArray select GetSafeString(arrElement)).ToArray();
return string.Join(", ", temp);
}

if (input == null) return "'null'";

return input;
}

static string GetSafeString(object input)
{
if (input == null)
return "'null'";

return input.ToString();
}
}
}
21 changes: 18 additions & 3 deletions TestStack.BDDfy/Scanners/StepScanners/Examples/ExampleValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public object GetValue(Type targetType)
var stringValue = _underlyingValue as string;
if (_underlyingValue == null)
{
if (targetType.IsValueType && !(targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof (Nullable<>)))
if (targetType.IsValueType && !(targetType.IsGenericType && targetType.GetGenericTypeDefinition() == typeof(Nullable<>)))
{
var valueAsString = string.IsNullOrEmpty(stringValue) ? "<null>" : string.Format("\"{0}\"", _underlyingValue);
throw new ArgumentException(string.Format("Cannot convert {0} to {1} (Column: '{2}', Row: {3})", valueAsString, targetType.Name, Header, Row));
Expand All @@ -49,10 +49,20 @@ public object GetValue(Type targetType)
if (targetType.IsEnum && _underlyingValue is string)
return Enum.Parse(targetType, (string)_underlyingValue);

if (targetType == typeof (DateTime))
if (targetType == typeof(DateTime))
return DateTime.Parse(stringValue);

return Convert.ChangeType(_underlyingValue, targetType);
try
{
return Convert.ChangeType(_underlyingValue, targetType);
}
catch (InvalidCastException ex)
{
throw new UnassignableExampleException(string.Format(
"{0} cannot be assigned to {1} (Column: '{2}', Row: {3})",
_underlyingValue == null ? "<null>" : _underlyingValue.ToString(),
targetType.Name, Header, Row), ex, this);
}
}

public bool ValueHasBeenUsed { get; private set; }
Expand All @@ -61,5 +71,10 @@ public override string ToString()
{
return string.Join("{0}: {1}", Header, _underlyingValue);
}

public string GetValueAsString()
{
return _underlyingValue.FlattenArray().ToString();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using System;
using System.Runtime.Serialization;

namespace TestStack.BDDfy
{
[Serializable]
public class UnassignableExampleException : Exception
{
public UnassignableExampleException(string message, Exception inner, ExampleValue exampleValue) : base(message, inner)
{
ExampleValue = exampleValue;
}

protected UnassignableExampleException(
SerializationInfo info,
StreamingContext context) : base(info, context)
{
}

public ExampleValue ExampleValue { get; private set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,6 @@ private static IEnumerable<object> ExtractConvertibleTypeArrayConstants(NewArray

private static IEnumerable<object> ExtractArguments<T>(ConstantExpression constantExpression, T value)
{

var expression = constantExpression.Value as Expression;
if (expression != null)
{
Expand Down Expand Up @@ -220,7 +219,26 @@ private static IEnumerable<object> ExtractConstant(MemberExpression memberExpres

private static IEnumerable<object> ExtractPropertyValue<T>(MemberExpression expression, PropertyInfo member, T value)
{
return new[] { member.GetValue(value, null) };
var memberExpression = expression.Expression as MemberExpression;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good addition.

if (memberExpression != null)
{
var extractArguments = ExtractArguments(memberExpression, value);
try
{
return new[]
{
member.GetValue(extractArguments.Single(), null)
};
}
catch (TargetException)
{
return new object[] {null};
}
}
return new[]
{
member.GetValue(value, null)
};
}
}
}
}
Loading