Permalink
Browse files

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

  • Loading branch information...
1 parent 7737458 commit 7fa0f32a1f831f8aef55a8ff7ee6db0dfb88a8cd @pawelpabich committed May 28, 2014
@@ -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 void OnAssemblyStarting()
{
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.