Last active
December 12, 2015 06:48
-
-
Save adamjasinski/4731768 to your computer and use it in GitHub Desktop.
AutoFixture.xUnit - CompositeDataAttribute rewrite
- lazy enumeration
- shorter code
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Globalization; | |
using System.Linq; | |
using System.Reflection; | |
using Xunit.Extensions; | |
namespace Prototypes.AutoFixture.Xunit.Extensions | |
{ | |
public class CompositeDataAttribute : DataAttribute | |
{ | |
private readonly IEnumerable<DataAttribute> attributes; | |
/// <summary> | |
/// Initializes a new instance of the <see cref="CompositeDataAttribute"/> class. | |
/// </summary> | |
/// <param name="attributes">The attributes representing a data source for a data theory. | |
/// </param> | |
public CompositeDataAttribute( IEnumerable<DataAttribute> attributes ) | |
: this( attributes.ToArray() ) | |
{ | |
} | |
/// <summary> | |
/// Initializes a new instance of the <see cref="CompositeDataAttribute"/> class. | |
/// </summary> | |
/// <param name="attributes">The attributes representing a data source for a data theory. | |
/// </param> | |
public CompositeDataAttribute( params DataAttribute[] attributes ) | |
{ | |
if ( attributes == null ) | |
{ | |
throw new ArgumentNullException( "attributes" ); | |
} | |
this.attributes = attributes; | |
} | |
/// <summary> | |
/// Gets the attributes supplied through one of the constructors. | |
/// </summary> | |
public IEnumerable<DataAttribute> Attributes | |
{ | |
get { return this.attributes; } | |
} | |
/// <summary> | |
/// Returns the composition of data to be used to test the theory. Favors the data returned | |
/// by DataAttributes in ascending order. Data already returned is ignored on next | |
/// DataAttribute returned data. | |
/// </summary> | |
/// <param name="methodUnderTest">The method that is being tested.</param> | |
/// <param name="parameterTypes">The types of the parameters for the test method.</param> | |
/// <returns> | |
/// Returns the composition of the theory data. | |
/// </returns> | |
/// <remarks> | |
/// The number of test cases is set from the first DataAttribute theory length. | |
/// </remarks> | |
public override IEnumerable<object[]> GetData( MethodInfo methodUnderTest, Type[] parameterTypes ) | |
{ | |
int numberOfParameters = parameterTypes.Length; | |
IEnumerator<object[]>[] dataEnumerators = attributes.Select( x => x | |
.GetData( methodUnderTest, parameterTypes ) | |
.GetEnumerator() ) | |
.ToArray(); | |
while ( dataEnumerators.First().MoveNext() ) | |
{ | |
var foundData = new List<object>( dataEnumerators.First().Current ); | |
foreach ( var dataEnumerator in dataEnumerators.Skip( 1 ) ) | |
{ | |
foundData.AddRange( | |
FetchRowOrEmpty( dataEnumerator ) | |
.Skip( foundData.Count ) | |
.Take( numberOfParameters - foundData.Count ) ); | |
} | |
if ( foundData.Count < numberOfParameters ) | |
{ | |
throw new InvalidOperationException( | |
string.Format( | |
CultureInfo.CurrentCulture, | |
"Expected {0} parameters, got {1} parameters", | |
numberOfParameters, foundData.Count | |
) | |
); | |
} | |
yield return foundData.ToArray(); | |
} | |
} | |
static IEnumerable<object> FetchRowOrEmpty( IEnumerator<object[]> enumerator ) | |
{ | |
if ( enumerator.MoveNext() ) | |
return enumerator.Current; | |
return Enumerable.Empty<object>(); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment