Permalink
Browse files

Now test collections can be specified on per test method basis.

  • Loading branch information...
pawelpabich committed May 28, 2014
1 parent 7737458 commit 7fa0f32a1f831f8aef55a8ff7ee6db0dfb88a8cd
@@ -16,6 +16,12 @@ public enum CollectionBehavior
/// By default, generates a collection per test class for any test classes that are not
/// decorated with <see cref="CollectionAttribute"/>.
/// </summary>
CollectionPerClass
CollectionPerClass,
/// <summary>
/// By default, generates a collection per test method for any test classes that are not
/// decorated with <see cref="CollectionAttribute"/>.
/// </summary>
CollectionPerMethod
}
}
@@ -16,10 +16,10 @@ public interface IXunitTestCollectionFactory
string DisplayName { get; }
/// <summary>
/// Gets the test collection for a given test class.
/// Gets the test collection for a given test method.
/// </summary>
/// <param name="testClass">The test class.</param>
/// <param name="testMethod">The test method.</param>
/// <returns>The test collection.</returns>
ITestCollection Get(ITypeInfo testClass);
ITestCollection Get(IMethodInfo testMethod);
}
}
@@ -154,9 +154,14 @@ static Type GetTestCollectionFactoryType(IAttributeInfo collectionBehaviorAttrib
if (ctorArgs.Count == 1)
{
if ((CollectionBehavior)ctorArgs[0] == CollectionBehavior.CollectionPerAssembly)
var collectionBehaviour = (CollectionBehavior) ctorArgs[0];
if (collectionBehaviour == CollectionBehavior.CollectionPerAssembly)
return typeof(CollectionPerAssemblyTestCollectionFactory);
if (collectionBehaviour == CollectionBehavior.CollectionPerMethod)
return typeof(CollectionPerMethodTestCollectionFactory);
return typeof(CollectionPerClassTestCollectionFactory);
}
@@ -49,11 +49,11 @@ ITestCollection CreateTestCollection(string name)
}
/// <inheritdoc/>
public ITestCollection Get(ITypeInfo testClass)
public ITestCollection Get(IMethodInfo testMethod)
{
var testClass = testMethod.Type;
var collectionAttribute = testClass.GetCustomAttributes(typeof(CollectionAttribute)).SingleOrDefault();
if (collectionAttribute == null)
return defaultCollection;
if (collectionAttribute == null) return defaultCollection;
var collectionName = (string)collectionAttribute.GetConstructorArguments().First();
return testCollections.GetOrAdd(collectionName, CreateTestCollection);
@@ -46,8 +46,9 @@ ITestCollection CreateCollection(string name)
}
/// <inheritdoc/>
public ITestCollection Get(ITypeInfo testClass)
public ITestCollection Get(IMethodInfo testMethod)
{
var testClass = testMethod.Type;
string collectionName;
var collectionAttribute = testClass.GetCustomAttributes(typeof(CollectionAttribute)).SingleOrDefault();
@@ -0,0 +1,62 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using Xunit.Abstractions;
namespace Xunit.Sdk
{
/// <summary>
/// Implementation of <see cref="IXunitTestCollectionFactory"/> which creates a new test
/// collection for each test method that isn't decorated with <see cref="CollectionAttribute"/>.
/// </summary>
public class CollectionPerMethodTestCollectionFactory : IXunitTestCollectionFactory
{
readonly Dictionary<string, ITypeInfo> collectionDefinitions;
readonly ConcurrentDictionary<string, ITestCollection> testCollections = new ConcurrentDictionary<string, ITestCollection>();
/// <summary>
/// Initializes a new instance of the <see cref="CollectionPerMethodTestCollectionFactory" /> class.
/// </summary>
/// <param name="assemblyInfo">The assembly.</param>
public CollectionPerMethodTestCollectionFactory(IAssemblyInfo assemblyInfo)
: this(assemblyInfo, MessageAggregator.Instance) { }
/// <summary>
/// Initializes a new instance of the <see cref="CollectionPerMethodTestCollectionFactory" /> class.
/// </summary>
/// <param name="assemblyInfo">The assembly info.</param>
/// <param name="messageAggregator">The message aggregator used to report <see cref="EnvironmentalWarning"/> messages.</param>
public CollectionPerMethodTestCollectionFactory(IAssemblyInfo assemblyInfo, IMessageAggregator messageAggregator)
{
collectionDefinitions = TestCollectionFactoryHelper.GetTestCollectionDefinitions(assemblyInfo, messageAggregator);
}
/// <inheritdoc/>
public string DisplayName
{
get { return "collection-per-method"; }
}
ITestCollection CreateCollection(string name)
{
ITypeInfo definitionType;
collectionDefinitions.TryGetValue(name, out definitionType);
return new XunitTestCollection { CollectionDefinition = definitionType, DisplayName = name };
}
/// <inheritdoc/>
public ITestCollection Get(IMethodInfo testMethod)
{
string collectionName;
var collectionAttribute = testMethod.GetCustomAttributes(typeof(CollectionAttribute)).SingleOrDefault();
if (collectionAttribute == null)
collectionName = "Test collection for " + testMethod.Type.Name + "." + testMethod.Name;
else
collectionName = (string)collectionAttribute.GetConstructorArguments().First();
return testCollections.GetOrAdd(collectionName, CreateCollection);
}
}
}
@@ -101,15 +101,18 @@ protected override async Task<RunSummary> RunTestCollectionsAsync(IMessageBus me
{
if (disableParallelization)
return await base.RunTestCollectionsAsync(messageBus, cancellationTokenSource);
var tasks = TestCases.Cast<IXunitTestCase>()
.GroupBy(tc => tc.TestCollection, TestCollectionComparer.Instance)
.Select(collectionGroup => Task.Factory.StartNew(() => RunTestCollectionAsync(messageBus, collectionGroup.Key, collectionGroup, cancellationTokenSource),
cancellationTokenSource.Token,
TaskCreationOptions.None,
scheduler))
.ToArray();
var testCollections = TestCases.Cast<IXunitTestCase>()
.GroupBy(tc => tc.TestCollection, TestCollectionComparer.Instance)
.ToArray();
Console.WriteLine("Queueing {0} test collections.", testCollections.Length);
var tasks = testCollections.Select(collectionGroup => Task.Factory.StartNew(() => RunTestCollectionAsync(messageBus, collectionGroup.Key, collectionGroup, cancellationTokenSource),
cancellationTokenSource.Token,
TaskCreationOptions.None,
scheduler))
.ToArray();
var summaries = await Task.WhenAll(tasks.Select(t => t.Unwrap()));
return new RunSummary()
@@ -93,11 +93,11 @@ protected virtual bool FindTestsForMethod(ITestCollection testCollection, ITypeI
/// <inheritdoc/>
protected override bool FindTestsForType(ITypeInfo type, bool includeSourceInformation, IMessageBus messageBus)
{
var testCollection = TestCollectionFactory.Get(type);
foreach (var method in type.GetMethods(includePrivateMethods: true))
if (!FindTestsForMethod(testCollection, type, method, includeSourceInformation, messageBus))
return false;
{
var testCollection = TestCollectionFactory.Get(method);
if (!FindTestsForMethod(testCollection, type, method, includeSourceInformation, messageBus))return false;
}
return true;
}
@@ -77,6 +77,7 @@
<Compile Include="Extensions\ReflectionAbstractionExtensions.cs" />
<Compile Include="Sdk\AsyncTestSyncContext.cs" />
<Compile Include="Sdk\DefaultTestCaseOrderer.cs" />
<Compile Include="Sdk\Frameworks\CollectionPerClassTestCollectionFactory.cs" />
<Compile Include="Sdk\Frameworks\Runners\TestAssemblyRunner.cs" />
<Compile Include="Sdk\Frameworks\Runners\TestClassRunner.cs" />
<Compile Include="Sdk\Frameworks\Runners\TestCollectionRunner.cs" />
@@ -96,7 +97,7 @@
<Compile Include="Sdk\EnvironmentalWarning.cs" />
<Compile Include="Sdk\ExceptionUtility.cs" />
<Compile Include="Sdk\MessageAggregator.cs" />
<Compile Include="Sdk\Frameworks\CollectionPerClassTestCollectionFactory.cs" />
<Compile Include="Sdk\Frameworks\CollectionPerMethodTestCollectionFactory.cs" />
<Compile Include="Sdk\Frameworks\LambdaTestCase.cs" />
<Compile Include="Sdk\Frameworks\TestCollectionFactoryHelper.cs" />
<Compile Include="Sdk\Frameworks\XunitTestCollection.cs" />
@@ -7,14 +7,14 @@ public class CollectionPerAssemblyTestCollectionFactoryTests
[Fact]
public void ReturnsDefaultTestCollectionForUndecoratedTestClass()
{
var type1 = Mocks.TypeInfo("type1");
var type2 = Mocks.TypeInfo("type2");
var method1 = Mocks.MethodInfo(type: Mocks.TypeInfo("type1"));
var method2 = Mocks.MethodInfo(type: Mocks.TypeInfo("type2"));
var assembly = Mocks.AssemblyInfo();
assembly.AssemblyPath.Returns(@"C:\Foo\bar.dll");
var factory = new CollectionPerAssemblyTestCollectionFactory(assembly);
var result1 = factory.Get(type1);
var result2 = factory.Get(type2);
var result1 = factory.Get(method1);
var result2 = factory.Get(method2);
Assert.Same(result1, result2);
Assert.Equal("Test collection for bar.dll", result1.DisplayName);
@@ -24,14 +24,14 @@ public void ReturnsDefaultTestCollectionForUndecoratedTestClass()
public void ClassesDecoratedWithSameCollectionNameAreInSameTestCollection()
{
var attr = Mocks.CollectionAttribute("My Collection");
var type1 = Mocks.TypeInfo("type1", attributes: new[] { attr });
var type2 = Mocks.TypeInfo("type2", attributes: new[] { attr });
var method1 = Mocks.MethodInfo(type: Mocks.TypeInfo("type1", attributes: new[] { attr }));
var method2 = Mocks.MethodInfo(type: Mocks.TypeInfo("type2", attributes: new[] { attr }));
var assembly = Mocks.AssemblyInfo();
assembly.AssemblyPath.Returns(@"C:\Foo\bar.dll");
var factory = new CollectionPerAssemblyTestCollectionFactory(assembly);
var result1 = factory.Get(type1);
var result2 = factory.Get(type2);
var result1 = factory.Get(method1);
var result2 = factory.Get(method2);
Assert.Same(result1, result2);
Assert.Equal("My Collection", result1.DisplayName);
@@ -40,14 +40,14 @@ public void ClassesDecoratedWithSameCollectionNameAreInSameTestCollection()
[Fact]
public void ClassesWithDifferentCollectionNamesHaveDifferentCollectionObjects()
{
var type1 = Mocks.TypeInfo("type1", attributes: new[] { Mocks.CollectionAttribute("Collection 1") });
var type2 = Mocks.TypeInfo("type2", attributes: new[] { Mocks.CollectionAttribute("Collection 2") });
var method1 = Mocks.MethodInfo(type: Mocks.TypeInfo("type1", attributes: new[] { Mocks.CollectionAttribute("Collection 1") }));
var method2 = Mocks.MethodInfo(type: Mocks.TypeInfo("type2", attributes: new[] { Mocks.CollectionAttribute("Collection 2") }));
var assembly = Mocks.AssemblyInfo();
assembly.AssemblyPath.Returns(@"C:\Foo\bar.dll");
var factory = new CollectionPerAssemblyTestCollectionFactory(assembly);
var result1 = factory.Get(type1);
var result2 = factory.Get(type2);
var result1 = factory.Get(method1);
var result2 = factory.Get(method2);
Assert.NotSame(result1, result2);
Assert.Equal("Collection 1", result1.DisplayName);
@@ -57,13 +57,13 @@ public void ClassesWithDifferentCollectionNamesHaveDifferentCollectionObjects()
[Fact]
public void UsingTestCollectionDefinitionSetsTypeInfo()
{
var testType = Mocks.TypeInfo("type", attributes: new[] { Mocks.CollectionAttribute("This is a test collection") });
var testMethod = Mocks.MethodInfo(type: Mocks.TypeInfo("type", attributes: new[] { Mocks.CollectionAttribute("This is a test collection") }));
var collectionDefinitionType = Mocks.TypeInfo("collectionDefinition", attributes: new[] { Mocks.CollectionDefinitionAttribute("This is a test collection") });
var assembly = Mocks.AssemblyInfo(new[] { collectionDefinitionType });
assembly.AssemblyPath.Returns(@"C:\Foo\bar.dll");
var factory = new CollectionPerAssemblyTestCollectionFactory(assembly);
var result = factory.Get(testType);
var result = factory.Get(testMethod);
Assert.Same(collectionDefinitionType, result.CollectionDefinition);
}
@@ -72,14 +72,14 @@ public void UsingTestCollectionDefinitionSetsTypeInfo()
public void MultiplyDeclaredCollectionsRaisesEnvironmentalWarning()
{
var broker = Substitute.For<IMessageAggregator>();
var testType = Mocks.TypeInfo("type", attributes: new[] { Mocks.CollectionAttribute("This is a test collection") });
var testMethod = Mocks.MethodInfo(type: Mocks.TypeInfo("type", attributes: new[] { Mocks.CollectionAttribute("This is a test collection") }));
var collectionDefinition1 = Mocks.TypeInfo("collectionDefinition1", attributes: new[] { Mocks.CollectionDefinitionAttribute("This is a test collection") });
var collectionDefinition2 = Mocks.TypeInfo("collectionDefinition2", attributes: new[] { Mocks.CollectionDefinitionAttribute("This is a test collection") });
var assembly = Mocks.AssemblyInfo(new[] { collectionDefinition1, collectionDefinition2 });
assembly.AssemblyPath.Returns(@"C:\Foo\bar.dll");
var factory = new CollectionPerAssemblyTestCollectionFactory(assembly, broker);
factory.Get(testType);
factory.Get(testMethod);
var captured = broker.Captured(b => b.Add<EnvironmentalWarning>(null));
var warning = captured.Arg<EnvironmentalWarning>();
Oops, something went wrong.

0 comments on commit 7fa0f32

Please sign in to comment.