Skip to content

Commit b2dd745

Browse files
vbreussvbtig
andauthored
fix: exclude tests on real file system in DEBUG mode (#222)
Tests on the real file system sometimes fail on the local developer environment. To simplify development, exclude the tests on the real file system in `DEBUG` mode, unless the variable `"ENABLE_REALFILESYSTEMTESTS_IN_DEBUG"` is set! Also add a prefix to the created temporary directory on the real file system, to simplify association between tests and temporary directories... Co-authored-by: Valentin Breuß <[email protected]>
1 parent f2d344f commit b2dd745

File tree

6 files changed

+60
-22
lines changed

6 files changed

+60
-22
lines changed

Source/Testably.Abstractions.Testing/FileSystemInitializer/DirectoryCleaner.cs

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,22 @@
11
using System;
2+
using System.Diagnostics.CodeAnalysis;
23
using System.IO;
34
using System.Threading;
45
using Testably.Abstractions.Testing.Helpers;
56

67
namespace Testably.Abstractions.Testing.FileSystemInitializer;
78

9+
[ExcludeFromCodeCoverage]
810
internal sealed class DirectoryCleaner : IDirectoryCleaner
911
{
1012
private readonly IFileSystem _fileSystem;
1113
private readonly Action<string>? _logger;
1214

13-
public DirectoryCleaner(IFileSystem fileSystem, Action<string>? logger)
15+
public DirectoryCleaner(IFileSystem fileSystem, string? prefix, Action<string>? logger)
1416
{
1517
_fileSystem = fileSystem;
1618
_logger = logger;
17-
BasePath = InitializeBasePath();
19+
BasePath = InitializeBasePath(prefix ?? "");
1820
}
1921

2022
#region IDirectoryCleaner Members
@@ -30,7 +32,10 @@ public void Dispose()
3032
{
3133
// It is important to reset the current directory, as otherwise deleting the BasePath
3234
// results in a IOException, because the process cannot access the file.
33-
_fileSystem.Directory.SetCurrentDirectory(_fileSystem.Path.GetTempPath());
35+
if (_fileSystem.Directory.GetCurrentDirectory() == BasePath)
36+
{
37+
_fileSystem.Directory.SetCurrentDirectory(_fileSystem.Path.GetTempPath());
38+
}
3439

3540
_logger?.Invoke($"Cleaning up '{BasePath}'...");
3641
for (int i = 10; i >= 0; i--)
@@ -109,24 +114,51 @@ private void ForceDeleteDirectory(string path, bool recursive = true)
109114
_fileSystem.Directory.Delete(path);
110115
}
111116

112-
private string InitializeBasePath()
117+
private string InitializeBasePath(string prefix)
113118
{
114119
string basePath;
115120

116121
do
117122
{
118123
string localBasePath = _fileSystem.Path.Combine(
119124
_fileSystem.Path.GetTempPath(),
120-
_fileSystem.Path.GetFileNameWithoutExtension(_fileSystem.Path
121-
.GetRandomFileName()));
125+
prefix + _fileSystem.Path.GetFileNameWithoutExtension(
126+
_fileSystem.Path.GetRandomFileName()));
122127
Execute.OnMac(() => localBasePath = "/private" + localBasePath);
123128
basePath = localBasePath;
124129
} while (_fileSystem.Directory.Exists(basePath));
125130

126-
_fileSystem.Directory.CreateDirectory(basePath);
131+
for (int i = 0; i <= 2; i++)
132+
{
133+
try
134+
{
135+
_fileSystem.Directory.CreateDirectory(basePath);
136+
break;
137+
}
138+
catch (Exception)
139+
{
140+
// Give a transient condition like antivirus/indexing a chance to go away
141+
Thread.Sleep(10);
142+
}
143+
}
144+
145+
if (!_fileSystem.Directory.Exists(basePath))
146+
{
147+
throw new TestingException($"Could not create current directory '{basePath}' for tests");
148+
}
127149

128150
_logger?.Invoke($"Use '{basePath}' as current directory.");
129151
_fileSystem.Directory.SetCurrentDirectory(basePath);
152+
for (int i = 0; i <= 10 && _fileSystem.Directory.GetCurrentDirectory() != basePath; i++)
153+
{
154+
Thread.Sleep(5);
155+
}
156+
157+
if (_fileSystem.Directory.GetCurrentDirectory() != basePath)
158+
{
159+
throw new TestingException($"Could not set current directory to '{basePath}' for tests");
160+
}
161+
130162
return basePath;
131163
}
132164
}

Source/Testably.Abstractions.Testing/FileSystemInitializerExtensions.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,18 @@ public static IFileSystemInitializer<TFileSystem> InitializeIn<TFileSystem>(
3434
/// <see cref="IDirectory.GetCurrentDirectory()" /> and all relative paths will use this directory.
3535
/// </summary>
3636
/// <param name="fileSystem">The file system.</param>
37+
/// <param name="prefix">
38+
/// A prefix to use for the temporary directory.<br />
39+
/// This simplifies matching directories to tests.
40+
/// </param>
3741
/// <param name="logger">(optional) A callback to log the cleanup process.</param>
3842
/// <returns>
3943
/// A <see cref="IDirectoryCleaner" /> that will
4044
/// force delete all content in the temporary directory on dispose.
4145
/// </returns>
4246
public static IDirectoryCleaner SetCurrentDirectoryToEmptyTemporaryDirectory(
43-
this IFileSystem fileSystem, Action<string>? logger = null)
47+
this IFileSystem fileSystem, string? prefix = null, Action<string>? logger = null)
4448
{
45-
return new DirectoryCleaner(fileSystem, logger);
49+
return new DirectoryCleaner(fileSystem, prefix, logger);
4650
}
4751
}

Tests/Helpers/Testably.Abstractions.Tests.SourceGenerator/ClassGenerators/FileSystemClassGenerator.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public void Dispose()
5656
}}
5757
}}
5858
59-
#if !DEBUG || !DISABLE_TESTS_REALFILESYSTEM
59+
#if !DEBUG || ENABLE_REALFILESYSTEMTESTS_IN_DEBUG
6060
6161
namespace {@class.Namespace}.{@class.Name}
6262
{{
@@ -73,7 +73,7 @@ public RealFileSystemTests(ITestOutputHelper testOutputHelper)
7373
: base(new RealFileSystem(), new RealTimeSystem())
7474
{{
7575
_directoryCleaner = FileSystem
76-
.SetCurrentDirectoryToEmptyTemporaryDirectory(testOutputHelper.WriteLine);
76+
.SetCurrentDirectoryToEmptyTemporaryDirectory($""{@class.Namespace}{{FileSystem.Path.DirectorySeparatorChar}}{@class.Name}-"", testOutputHelper.WriteLine);
7777
}}
7878
7979
/// <inheritdoc cref=""IDisposable.Dispose()"" />

Tests/Testably.Abstractions.Testing.Tests/FileSystemInitializer/DirectoryCleanerTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public void Dispose_PermanentFailure_ShouldNotThrowException(
2121
MockFileSystem sut = new();
2222
List<string> receivedLogs = new();
2323
IDirectoryCleaner directoryCleaner =
24-
sut.SetCurrentDirectoryToEmptyTemporaryDirectory(m => receivedLogs.Add(m));
24+
sut.SetCurrentDirectoryToEmptyTemporaryDirectory(logger: m => receivedLogs.Add(m));
2525
string currentDirectory = sut.Directory.GetCurrentDirectory();
2626
int exceptionCount = 0;
2727
sut.Intercept.Event(_ =>
@@ -57,7 +57,7 @@ public void Dispose_ShouldForceDeleteCurrentDirectory()
5757
MockFileSystem sut = new();
5858
List<string> receivedLogs = new();
5959
IDirectoryCleaner directoryCleaner =
60-
sut.SetCurrentDirectoryToEmptyTemporaryDirectory(m => receivedLogs.Add(m));
60+
sut.SetCurrentDirectoryToEmptyTemporaryDirectory(logger: m => receivedLogs.Add(m));
6161
string currentDirectory = sut.Directory.GetCurrentDirectory();
6262

6363
directoryCleaner.Dispose();
@@ -105,7 +105,7 @@ public void InitializeBasePath_ShouldCreateDirectoryAndLogBasePath()
105105
List<string> receivedLogs = new();
106106

107107
using IDirectoryCleaner directoryCleaner =
108-
sut.SetCurrentDirectoryToEmptyTemporaryDirectory(t => receivedLogs.Add(t));
108+
sut.SetCurrentDirectoryToEmptyTemporaryDirectory(logger: t => receivedLogs.Add(t));
109109

110110
string currentDirectory = sut.Directory.GetCurrentDirectory();
111111
sut.Directory.Exists(currentDirectory).Should().BeTrue();

Tests/Testably.Abstractions.Tests/FileSystem/Directory/CreateDirectoryTests.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -208,11 +208,12 @@ public void CreateDirectory_ShouldCreateDirectoryInBasePath()
208208
result.FullName.Should().StartWith(BasePath);
209209
}
210210

211-
[SkippableTheory]
212-
[AutoData]
213-
public void CreateDirectory_ShouldCreateParentDirectories(
214-
string directoryLevel1, string directoryLevel2, string directoryLevel3)
211+
[SkippableFact]
212+
public void CreateDirectory_ShouldCreateParentDirectories()
215213
{
214+
string directoryLevel1 = "lvl1";
215+
string directoryLevel2 = "lvl2";
216+
string directoryLevel3 = "lvl3";
216217
string path =
217218
FileSystem.Path.Combine(directoryLevel1, directoryLevel2, directoryLevel3);
218219

Tests/Testably.Abstractions.Tests/FileSystem/DirectoryInfo/CreateTests.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,12 @@ public void Create_ShouldCreateInBasePath()
3434
result.FullName.Should().StartWith(BasePath);
3535
}
3636

37-
[SkippableTheory]
38-
[AutoData]
39-
public void Create_ShouldCreateParentDirectories(
40-
string directoryLevel1, string directoryLevel2, string directoryLevel3)
37+
[SkippableFact]
38+
public void Create_ShouldCreateParentDirectories()
4139
{
40+
string directoryLevel1 = "lvl1";
41+
string directoryLevel2 = "lvl2";
42+
string directoryLevel3 = "lvl3";
4243
string path =
4344
FileSystem.Path.Combine(directoryLevel1, directoryLevel2, directoryLevel3);
4445

0 commit comments

Comments
 (0)