Last active
June 25, 2018 16:49
-
-
Save domartynov/6cbb7829d874aa47a4b1aaf716a96e4c to your computer and use it in GitHub Desktop.
Reusable test dir per test logic added via [TestDir.Use] for xunit
This file contains hidden or 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.IO; | |
using System.Reflection; | |
using System.Threading; | |
using FluentAssertions; | |
using Xunit; | |
using Xunit.Sdk; | |
namespace ExcelReporting.Tests.Common | |
{ | |
public class TestDir | |
{ | |
private static readonly Dictionary<string, int> TempDirs = new Dictionary<string, int>(); | |
private readonly bool _autoMakeDir; | |
private string _path; | |
public MethodInfo TestMethod { get; private set; } | |
public DateTime Now { get; private set; } | |
public TestDir(MethodInfo testMethod, bool autoMakeDir) | |
{ | |
TestMethod = testMethod; | |
_autoMakeDir = autoMakeDir; | |
} | |
public static string Path(string subdir = null) | |
{ | |
var testDir = UseAttribute.TestDirSlot.Value ?? throw new InvalidOperationException("Not found current test marked TestDir.Use"); | |
return testDir.PathInternal(subdir); | |
} | |
private string PathInternal(string subdir = null) | |
{ | |
var path = subdir != null ? System.IO.Path.Combine(GetPath(), subdir) : GetPath(); | |
return _autoMakeDir ? MkDirs(path) : path; | |
} | |
private string GetPath() | |
{ | |
if (_path != null) return _path; | |
lock (TempDirs) | |
{ | |
Now = DateTime.Now; | |
var path = $"_temp\\{Now:yyyyMMdd_HHmmss}_{TestMethod.ReflectedType?.Name ?? ""}_{TestMethod.Name}\\"; | |
if (TempDirs.TryGetValue(path, out var cnt)) | |
{ | |
TempDirs[path] = cnt + 1; | |
return _path = $"{path}_{cnt}"; | |
} | |
TempDirs[path] = 1; | |
return _path = path; | |
} | |
} | |
public static string MkDirs(string path) | |
{ | |
var folder = System.IO.Path.GetDirectoryName(path); | |
if (folder != null && !Directory.Exists(folder)) Directory.CreateDirectory(folder); | |
return path; | |
} | |
public class UseAttribute : BeforeAfterTestAttribute | |
{ | |
internal static readonly AsyncLocal<TestDir> TestDirSlot = new AsyncLocal<TestDir>(); | |
private readonly bool _autoMakeDir; | |
public UseAttribute(bool autoMakeDir = false) => _autoMakeDir = autoMakeDir; | |
public override void Before(MethodInfo methodUnderTest) => TestDirSlot.Value = new TestDir(methodUnderTest, _autoMakeDir); | |
public override void After(MethodInfo methodUnderTest) => TestDirSlot.Value = null; | |
} | |
} | |
public class TestDirTests | |
{ | |
[Fact] | |
public void ThrowWhenOutOfContext() | |
{ | |
Action a = () => TestDir.Path(); | |
a.ShouldThrow<InvalidOperationException>(); | |
} | |
[Fact, TestDir.Use] | |
public void TestMethodFoo() => | |
TestDir.Path().Should().Contain(nameof(TestMethodFoo)).And.Contain(GetType().Name); | |
} | |
public class TestDirTwoTests : TestDirTests | |
{ | |
[Fact, TestDir.Use(true)] | |
public void TestAutoCreate() => Directory.Exists(TestDir.Path()).Should().BeTrue(); | |
} | |
[TestDir.Use] | |
public class TestDirOnTestClass | |
{ | |
[Fact] | |
public void TestMethod1Foo() => | |
TestDir.Path().Should().Contain(nameof(TestMethod1Foo)).And.Contain(GetType().Name); | |
[Fact] | |
public void TestMethod2Foo() => | |
TestDir.Path().Should().Contain(nameof(TestMethod2Foo)).And.Contain(GetType().Name); | |
} | |
public class Foo | |
{ | |
public string Dir { get; } | |
public Foo(string dir) => Dir = dir; | |
} | |
[TestDir.Use] | |
public class TestSharedComponentOnTestDir | |
{ | |
// have to use Lazy because xunit calls BeforeAfterTestAttribute.Before after ctor :(, see https://github.com/xunit/xunit/issues/581 | |
private readonly Lazy<Foo> _fooLazy = new Lazy<Foo>(() => new Foo(TestDir.Path())); | |
protected Foo Foo => _fooLazy.Value; | |
[Fact] | |
public void TestFoo() => Foo.Dir.Should().Contain("TestFoo"); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment