NUnit 3.7.1
Setup:
Running fixtures in parallel (Parallelizable(ParallelScope.Fixtures) set in AssemblyInfo.cs) in at least 2 threads (LevelOfParallelism(2) set in AssemblyInfo.cs).
Multiple fixtures with tests and OneTimeTearDown's for each of them exist.
Problem:
All [OneTimeTearDown] methods are executed in bulk when first available thread finishes.
Example:
Tests:
using System.Threading;
using NLog;
using NUnit.Framework;
namespace Skanska.Korab2.UITests.Infrastructure.Tests
{
class Common
{
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
public static void LogMe(string message)
{
Logger.Log(LogLevel.Info, $"{message} from {Thread.CurrentThread.Name}");
}
}
class Class1Fast
{
[Test]
public void Test1()
{
Common.LogMe(nameof(Test1));
}
[Test]
public void Test11()
{
Common.LogMe(nameof(Test11));
}
[OneTimeTearDown]
public void Test1TearDown()
{
Common.LogMe(nameof(Test1TearDown));
}
}
class Class2Slow
{
[Test]
public void Test2()
{
Thread.Sleep(1000);
Common.LogMe(nameof(Test2));
}
[Test]
public void Test22()
{
Thread.Sleep(1000);
Common.LogMe(nameof(Test22));
}
[OneTimeTearDown]
public void Test2TearDown()
{
Common.LogMe(nameof(Test2TearDown));
}
}
class Class3Slow
{
[Test]
public void Test3()
{
Thread.Sleep(1000);
Common.LogMe(nameof(Test3));
}
[Test]
public void Test33()
{
Thread.Sleep(1000);
Common.LogMe(nameof(Test33));
}
[OneTimeTearDown]
public void Test3TearDown()
{
Common.LogMe(nameof(Test3TearDown));
}
}
class Class4
{
[Test]
public void Test4()
{
Common.LogMe(nameof(Test4));
}
[Test]
public void Test44()
{
Common.LogMe(nameof(Test44));
}
[OneTimeTearDown]
public void Test4TearDown()
{
Common.LogMe(nameof(Test4TearDown));
}
}
class Class5
{
[Test]
public void Test5()
{
Common.LogMe(nameof(Test5));
}
[Test]
public void Test55()
{
Common.LogMe(nameof(Test55));
}
[OneTimeTearDown]
public void Test5TearDown()
{
Common.LogMe(nameof(Test5TearDown));
}
}
class Class6
{
[Test]
public void Test6()
{
Common.LogMe(nameof(Test6));
}
[Test]
public void Test66()
{
Common.LogMe(nameof(Test66));
}
[OneTimeTearDown]
public void Test6TearDown()
{
Common.LogMe(nameof(Test6TearDown));
}
}
class Class7
{
[Test]
public void Test7()
{
Common.LogMe(nameof(Test7));
}
[Test]
public void Test77()
{
Common.LogMe(nameof(Test77));
}
[OneTimeTearDown]
public void Test7TearDown()
{
Common.LogMe(nameof(Test7TearDown));
}
}
class Class8Slow
{
[Test]
public void Test8()
{
Thread.Sleep(1000);
Common.LogMe(nameof(Test8));
}
[Test]
public void Test88()
{
Thread.Sleep(1000);
Common.LogMe(nameof(Test88));
}
[OneTimeTearDown]
public void Test8TearDown()
{
Common.LogMe(nameof(Test8TearDown));
}
}
}
AssemblyInfo.cs
[assembly: Parallelizable(ParallelScope.Fixtures)]
[assembly: LevelOfParallelism(2)]
Result:
2017-07-28 18:09:03.0068|INFO| Test1 from Worker#2
2017-07-28 18:09:03.0338|INFO| Test11 from Worker#2
2017-07-28 18:09:03.8560|INFO| Test2 from Worker#1
2017-07-28 18:09:04.0419|INFO| Test3 from Worker#2
2017-07-28 18:09:04.8612|INFO| Test22 from Worker#1
2017-07-28 18:09:04.8732|INFO| Test4 from Worker#1
2017-07-28 18:09:04.8732|INFO| Test44 from Worker#1
2017-07-28 18:09:04.8862|INFO| Test5 from Worker#1
2017-07-28 18:09:04.8862|INFO| Test55 from Worker#1
2017-07-28 18:09:04.8982|INFO| Test6 from Worker#1
2017-07-28 18:09:04.8982|INFO| Test66 from Worker#1
2017-07-28 18:09:04.9132|INFO| Test7 from Worker#1
2017-07-28 18:09:04.9132|INFO| Test77 from Worker#1
2017-07-28 18:09:05.0482|INFO| Test33 from Worker#2
2017-07-28 18:09:05.0522|INFO| Test1TearDown from Worker#2
2017-07-28 18:09:05.0522|INFO| Test2TearDown from Worker#2
2017-07-28 18:09:05.0677|INFO| Test4TearDown from Worker#2
2017-07-28 18:09:05.0677|INFO| Test5TearDown from Worker#2
2017-07-28 18:09:05.0677|INFO| Test6TearDown from Worker#2
2017-07-28 18:09:05.0677|INFO| Test7TearDown from Worker#2
2017-07-28 18:09:05.0677|INFO| Test3TearDown from Worker#2
2017-07-28 18:09:05.9266|INFO| Test8 from Worker#1
2017-07-28 18:09:06.9321|INFO| Test88 from Worker#1
2017-07-28 18:09:06.9321|INFO| Test8TearDown from Worker#1
Expected result:
Test1TearDown is run before Worker#2 has started tests from other fixtures.
Previous versions:
Logs from NUnit 3.6.1:
2017-07-28 18:18:19.3493|INFO| Test1 from Worker#2
2017-07-28 18:18:19.3913|INFO| Test11 from Worker#2
2017-07-28 18:18:19.4018|INFO| Test1TearDown from Worker#2
2017-07-28 18:18:19.9824|INFO| Test2 from Worker#1
2017-07-28 18:18:20.4252|INFO| Test3 from Worker#2
2017-07-28 18:18:20.9884|INFO| Test22 from Worker#1
2017-07-28 18:18:20.9914|INFO| Test2TearDown from Worker#1
2017-07-28 18:18:20.9914|INFO| Test4 from Worker#1
2017-07-28 18:18:20.9914|INFO| Test44 from Worker#1
2017-07-28 18:18:21.0085|INFO| Test4TearDown from Worker#1
2017-07-28 18:18:21.0085|INFO| Test5 from Worker#1
2017-07-28 18:18:21.0224|INFO| Test55 from Worker#1
2017-07-28 18:18:21.0224|INFO| Test5TearDown from Worker#1
2017-07-28 18:18:21.0224|INFO| Test6 from Worker#1
2017-07-28 18:18:21.0424|INFO| Test66 from Worker#1
2017-07-28 18:18:21.0424|INFO| Test6TearDown from Worker#1
2017-07-28 18:18:21.0574|INFO| Test7 from Worker#1
2017-07-28 18:18:21.0574|INFO| Test77 from Worker#1
2017-07-28 18:18:21.0724|INFO| Test7TearDown from Worker#1
2017-07-28 18:18:21.4422|INFO| Test33 from Worker#2
2017-07-28 18:18:21.4452|INFO| Test3TearDown from Worker#2
2017-07-28 18:18:22.0818|INFO| Test8 from Worker#1
2017-07-28 18:18:23.0879|INFO| Test88 from Worker#1
2017-07-28 18:18:23.0879|INFO| Test8TearDown from Worker#1
NUnit 3.7.1
Setup:
Running fixtures in parallel (
Parallelizable(ParallelScope.Fixtures)set inAssemblyInfo.cs) in at least 2 threads (LevelOfParallelism(2)set inAssemblyInfo.cs).Multiple fixtures with tests and OneTimeTearDown's for each of them exist.
Problem:
All
[OneTimeTearDown]methods are executed in bulk when first available thread finishes.Example:
Tests:
AssemblyInfo.cs
Result:
Expected result:
Test1TearDownis run before Worker#2 has started tests from other fixtures.Previous versions:
Logs from NUnit 3.6.1: