Skip to content

Commit

Permalink
Add strategies for NUnit 3 test names to support fixed test name
Browse files Browse the repository at this point in the history
Provide strategies to allow the test name to not change between
discovery and execution. That is needed by some test runners to work
correctly (e.g. VS adapter, NCrunch)
  • Loading branch information
frblondin authored and zvirja committed Oct 3, 2017
1 parent 06ca10b commit d1cc8b5
Show file tree
Hide file tree
Showing 12 changed files with 461 additions and 41 deletions.
Expand Up @@ -62,8 +62,12 @@
<Compile Include="NoAutoPropertiesAttributeTest.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Scenario.cs" />
<Compile Include="TestNameStrategiesFixture.cs" />
<Compile Include="TestNameStrategiesTest.cs" />
<Compile Include="ThrowingStubFixture.cs" />
<Compile Include="TypeWithCustomizationAttributes.cs" />
<Compile Include="FixedNameTestMethodBuilderTest.cs" />
<Compile Include="VolatileNameTestMethodBuilderTest.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AutoFixture.NUnit3\AutoFixture.NUnit3.csproj">
Expand Down
22 changes: 22 additions & 0 deletions Src/AutoFixture.NUnit3.UnitTest/FixedNameTestMethodBuilderTest.cs
@@ -0,0 +1,22 @@
using NUnit.Framework;
using NUnit.Framework.Internal;
using System;

namespace Ploeh.AutoFixture.NUnit3.UnitTest
{
public class FixedNameTestMethodBuilderTest
{
[Test]
public void FixedNameTestMethodBuilderIsResilientToFactoryException()
{
// Fixture setup
var dummyMethod = new MethodWrapper(typeof(TestNameStrategiesFixture), nameof(TestNameStrategiesFixture.FixedNameDecoratedMethod));
var sut = new FixedNameTestMethodBuilder();
// Exercise system
var testMethod = sut.Build(dummyMethod, null, () => throw new Exception(), 0);
// Verify outcome
Assert.That(testMethod.Name, Is.EqualTo(nameof(TestNameStrategiesFixture.FixedNameDecoratedMethod)));
// Teardown
}
}
}
2 changes: 1 addition & 1 deletion Src/AutoFixture.NUnit3.UnitTest/Scenario.cs
Expand Up @@ -378,7 +378,7 @@ public void InlineAutoDataCanBeUsedWithFrozen(int p1, int p2, [Frozen]string p3,

[Theory, AutoData]
public void NoAutoPropertiesAttributeLeavesPropertiesUnset(
[NoAutoProperties]PropertyHolder<object> ph1,
[NoAutoProperties]PropertyHolder<object> ph1,
[NoAutoProperties]PropertyHolder<string> ph2,
[NoAutoProperties]PropertyHolder<int> ph3
)
Expand Down
68 changes: 68 additions & 0 deletions Src/AutoFixture.NUnit3.UnitTest/TestNameStrategiesFixture.cs
@@ -0,0 +1,68 @@
namespace Ploeh.AutoFixture.NUnit3.UnitTest
{
public class TestNameStrategiesFixture
{
private static IFixture CreateFixtureWithInjectedValues()
{
var result = new Fixture();
// Make so that fixed values will be returned
result.Inject(42);
result.Inject("foo");
return result;
}

public class AutoDataFixedNameAttribute : AutoDataAttribute
{
public AutoDataFixedNameAttribute()
{
TestMethodBuilder = new FixedNameTestMethodBuilder();
}
}

public class AutoDataVolatileNameAttribute : AutoDataAttribute
{
public AutoDataVolatileNameAttribute() : base(CreateFixtureWithInjectedValues())
{
TestMethodBuilder = new VolatileNameTestMethodBuilder();
}
}

public class InlineAutoDataFixedNameAttribute : InlineAutoDataAttribute
{
public InlineAutoDataFixedNameAttribute(params object[] arguments)
: base(arguments)
{
TestMethodBuilder = new FixedNameTestMethodBuilder();
}
}

public class InlineAutoDataVolatileNameAttribute : InlineAutoDataAttribute
{
public InlineAutoDataVolatileNameAttribute(params object[] arguments)
: base(CreateFixtureWithInjectedValues(), arguments)
{
TestMethodBuilder = new VolatileNameTestMethodBuilder();
}
}

[AutoDataFixedName]
public void FixedNameDecoratedMethod(int expectedNumber, MyClass sut)
{
}

[AutoDataVolatileName]
public void VolatileNameDecoratedMethod(int expectedNumber, string value)
{
}

[InlineAutoDataFixedName("alpha", "beta")]
public void InlineFixedNameDecoratedMethod(string p1, string p2, string p3)
{
}

[InlineAutoDataVolatileNameAttribute("alpha", "beta")]
public void InlineVolatileNameDecoratedMethod(string p1, string p2, string p3)
{
}
}
}
139 changes: 139 additions & 0 deletions Src/AutoFixture.NUnit3.UnitTest/TestNameStrategiesTest.cs
@@ -0,0 +1,139 @@
using NUnit.Framework;
using NUnit.Framework.Internal;
using System;
using System.Linq;
using static Ploeh.AutoFixture.NUnit3.UnitTest.TestNameStrategiesFixture;

namespace Ploeh.AutoFixture.NUnit3.UnitTest
{
public class TestNameStrategiesTest
{
[Test]
public void AutoDataAttributeUsesRealValueByDefault()
{
// Fixture setup
// Exercise system
var sut = new AutoDataAttribute();
// Verify outcome
Assert.That(sut.TestMethodBuilder,
Is.TypeOf<VolatileNameTestMethodBuilder>());
// Teardown
}

[Test]
public void InlineAutoDataAttributeUsesRealValueByDefault()
{
// Fixture setup
// Exercise system
var sut = new InlineAutoDataAttribute();
// Verify outcome
Assert.That(sut.TestMethodBuilder,
Is.TypeOf<VolatileNameTestMethodBuilder>());
// Teardown
}

[Test]
public void AutoDataUsesFixedValuesForTestName()
{
// Fixture setup
// Exercise system
var testMethod = GetTestMethod<AutoDataFixedNameAttribute>(nameof(TestNameStrategiesFixture.FixedNameDecoratedMethod));
// Verify outcome
Assert.That(testMethod.Name,
Is.EqualTo(@"FixedNameDecoratedMethod(auto<Int32>,auto<MyClass>)"));
// Teardown
}

[Test]
public void AutoDataFixedNameUsesFixedValuesForTestFullName()
{
// Fixture setup
// Exercise system
var testMethod = GetTestMethod<AutoDataFixedNameAttribute>(nameof(TestNameStrategiesFixture.FixedNameDecoratedMethod));
// Verify outcome
Assert.That(testMethod.FullName,
Is.EqualTo(@"Ploeh.AutoFixture.NUnit3.UnitTest.TestNameStrategiesFixture.FixedNameDecoratedMethod(auto<Int32>,auto<MyClass>)"));
// Teardown
}

[Test]
public void AutoDataVolatileNameUsesRealValuesForTestName()
{
// Fixture setup
// Exercise system
var testMethod = GetTestMethod<AutoDataVolatileNameAttribute>(nameof(TestNameStrategiesFixture.VolatileNameDecoratedMethod));
// Verify outcome
Assert.That(testMethod.Name,
Is.EqualTo(@"VolatileNameDecoratedMethod(42,""foo"")"));
// Teardown
}

[Test]
public void AutoDataVolatileNameUsesRealValuesForTestFullName()
{
// Fixture setup
// Exercise system
var testMethod = GetTestMethod<AutoDataVolatileNameAttribute>(nameof(TestNameStrategiesFixture.VolatileNameDecoratedMethod));
// Verify outcome
Assert.That(testMethod.FullName,
Is.EqualTo(@"Ploeh.AutoFixture.NUnit3.UnitTest.TestNameStrategiesFixture.VolatileNameDecoratedMethod(42,""foo"")"));
// Teardown
}

[Test]
public void InlineAutoDataUsesFixedValuesForTestName()
{
// Fixture setup
// Exercise system
var testMethod = GetTestMethod<InlineAutoDataFixedNameAttribute>(nameof(TestNameStrategiesFixture.InlineFixedNameDecoratedMethod));
// Verify outcome
Assert.That(testMethod.Name,
Is.EqualTo(@"InlineFixedNameDecoratedMethod(""alpha"",""beta"",auto<String>)"));
// Teardown
}

[Test]
public void InlineAutoDataFixedNameUsesFixedValuesForTestFullName()
{
// Fixture setup
// Exercise system
var testMethod = GetTestMethod<InlineAutoDataFixedNameAttribute>(nameof(TestNameStrategiesFixture.InlineFixedNameDecoratedMethod));
// Verify outcome
Assert.That(testMethod.FullName,
Is.EqualTo(@"Ploeh.AutoFixture.NUnit3.UnitTest.TestNameStrategiesFixture.InlineFixedNameDecoratedMethod(""alpha"",""beta"",auto<String>)"));
// Teardown
}

[Test]
public void InlineAutoDataVolatileNameUsesRealValuesForTestName()
{
// Fixture setup
// Exercise system
var testMethod = GetTestMethod<InlineAutoDataVolatileNameAttribute>(nameof(TestNameStrategiesFixture.InlineVolatileNameDecoratedMethod));
// Verify outcome
Assert.That(testMethod.Name,
Is.EqualTo(@"InlineVolatileNameDecoratedMethod(""alpha"",""beta"",""foo"")"));
// Teardown
}

[Test]
public void InlineAutoDataVolatileNameUsesRealValuesForFullName()
{
// Fixture setup
// Exercise system
var testMethod = GetTestMethod<InlineAutoDataVolatileNameAttribute>(nameof(TestNameStrategiesFixture.InlineVolatileNameDecoratedMethod));
// Verify outcome
Assert.That(testMethod.FullName,
Is.EqualTo(@"Ploeh.AutoFixture.NUnit3.UnitTest.TestNameStrategiesFixture.InlineVolatileNameDecoratedMethod(""alpha"",""beta"",""foo"")"));
// Teardown
}

private static TestMethod GetTestMethod<TAttribute>(string testName) where TAttribute : Attribute, NUnit.Framework.Interfaces.ITestBuilder
{
var method = new MethodWrapper(typeof(TestNameStrategiesFixture), testName);
var inlineAttribute = (TAttribute)Attribute.GetCustomAttribute(method.MethodInfo, typeof(TAttribute));
var testMethod = inlineAttribute.BuildFrom(method, null).Single();
return testMethod;
}
}
}
@@ -0,0 +1,22 @@
using NUnit.Framework;
using NUnit.Framework.Internal;
using System;

namespace Ploeh.AutoFixture.NUnit3.UnitTest
{
public class VolatileNameTestMethodBuilderTest
{
[Test]
public void VolatileNameTestMethodBuilderIsResilientToFactoryException()
{
// Fixture setup
var anyMethod = new MethodWrapper(typeof(TestNameStrategiesFixture), nameof(TestNameStrategiesFixture.VolatileNameDecoratedMethod));
var sut = new VolatileNameTestMethodBuilder();
// Exercise system
var testMethod = sut.Build(anyMethod, null, () => throw new Exception(), 0);
// Verify outcome
Assert.That(testMethod.Name, Is.EqualTo(nameof(TestNameStrategiesFixture.VolatileNameDecoratedMethod)));
// Teardown
}
}
}
37 changes: 16 additions & 21 deletions Src/AutoFixture.NUnit3/AutoDataAttribute.cs
Expand Up @@ -5,19 +5,31 @@
using NUnit.Framework.Internal;
using NUnit.Framework.Internal.Builders;
using Ploeh.AutoFixture.Kernel;
using System.Diagnostics.CodeAnalysis;

namespace Ploeh.AutoFixture.NUnit3
{
/// <summary>
/// This attribute uses AutoFixture to generate values for unit test parameters.
/// This implementation is based on TestCaseAttribute of NUnit3
/// </summary>
[SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes",
Justification = "This attribute is the root of a potential attribute hierarchy.")]
[AttributeUsage(AttributeTargets.Method)]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1813:AvoidUnsealedAttributes", Justification = "This attribute is the root of a potential attribute hierarchy.")]
public class AutoDataAttribute : Attribute, ITestBuilder
{
private readonly IFixture _fixture;

private ITestMethodBuilder _testMethodBuilder = new VolatileNameTestMethodBuilder();
/// <summary>
/// Gets or sets the current <see cref="ITestMethodBuilder"/> strategy.
/// </summary>
public ITestMethodBuilder TestMethodBuilder
{
get => _testMethodBuilder;
set => _testMethodBuilder = value ?? throw new ArgumentNullException(nameof(value));
}

/// <summary>
/// Construct a <see cref="AutoDataAttribute"/>
/// </summary>
Expand Down Expand Up @@ -49,31 +61,14 @@ protected AutoDataAttribute(IFixture fixture)
/// <returns>One or more TestMethods</returns>
public IEnumerable<TestMethod> BuildFrom(IMethodInfo method, Test suite)
{
var test = new NUnitTestCaseBuilder().BuildTestMethod(method, suite, this.GetParametersForMethod(method));
var test = this.TestMethodBuilder.Build(method, suite, () => GetParameterValues(method).ToArray(), 0);

yield return test;
}

[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "This method is always expected to return an instance of the TestCaseParameters class.")]
private TestCaseParameters GetParametersForMethod(IMethodInfo method)
{
try
{
var parameters = method.GetParameters();

var parameterValues = this.GetParameterValues(parameters);

return new TestCaseParameters(parameterValues.ToArray());
}
catch (Exception ex)
{
return new TestCaseParameters(ex);
}
}

private IEnumerable<object> GetParameterValues(IEnumerable<IParameterInfo> parameters)
private IEnumerable<object> GetParameterValues(IMethodInfo method)
{
return parameters.Select(Resolve);
return method.GetParameters().Select(Resolve);
}

private object Resolve(IParameterInfo parameterInfo)
Expand Down
3 changes: 3 additions & 0 deletions Src/AutoFixture.NUnit3/AutoFixture.NUnit3.csproj
Expand Up @@ -71,6 +71,7 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="FixedNameTestMethodBuilder.cs" />
<Compile Include="InlineAutoDataAttribute.cs" />
<Compile Include="AutoDataAttribute.cs" />
<Compile Include="CustomizeAttribute.cs" />
Expand All @@ -84,6 +85,8 @@
<Compile Include="ModestAttribute.cs" />
<Compile Include="NoAutoPropertiesAttribute.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="VolatileNameTestMethodBuilder.cs" />
<Compile Include="ITestMethodBuilder.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AutoFixture\AutoFixture.csproj">
Expand Down

0 comments on commit d1cc8b5

Please sign in to comment.