Skip to content

refactor: modernize tests after updating aweXpect.Testably to v0.15.0#1020

Merged
vbreuss merged 6 commits into
mainfrom
topic/modernize-tests-after-awexpect.testably-update
May 20, 2026
Merged

refactor: modernize tests after updating aweXpect.Testably to v0.15.0#1020
vbreuss merged 6 commits into
mainfrom
topic/modernize-tests-after-awexpect.testably-update

Conversation

@vbreuss
Copy link
Copy Markdown
Member

@vbreuss vbreuss commented May 20, 2026

Adopt aweXpect.Testably 0.15.0 assertions in the test suite

Summary

  • Bumps aweXpect.Testably from 0.14.0 to 0.15.0.
  • Migrates eligible test sites to the new ITimerMock, IFileInfo/IDirectoryInfo, IDriveInfo, IFileVersionInfo, and IFileSystem expectations introduced in 0.15.0.

Net change: -31 lines across 11 files. The biggest win is TimerMockTests, where Timer.Executed().Within(...) replaces a SemaphoreSlim + Interlocked.Increment + Volatile.Read coordination pattern.

Commits (one per concern, easy to review or revert individually)

# Commit Files
1 chore(deps): bump aweXpect.Testably to 0.15.0 Directory.Packages.props
2 refactor(tests): use Timer.Executed().Within() in TimerMockTests TimerMockTests.cs
3 refactor(tests): use HasAttribute/DoesNotHaveAttribute on file system info 4 files under Tests/Testably.Abstractions.Tests/FileSystem/...
4 refactor(tests): use IDriveInfo expectations from aweXpect.Testably DriveInfoMockTests.cs, MockFileSystemTests.cs, DriveInfo/Tests.cs, DriveInfoFactory/Tests.cs
5 refactor(tests): use IFileVersionInfo expectations from aweXpect.Testably FileVersionInfoBuilderTests.cs
6 refactor(tests): use IFileSystem.HasDrive in MockFileSystemTests MockFileSystemTests.cs

Refactor patterns

Timer callbacks (the big one)

// before: semaphore + Interlocked + Volatile.Read + CancellationTokenSource(30s)
await That(Volatile.Read(ref callbackCount)).IsEqualTo(1);

// after
await That(timer).Executed().AtLeast(1.Times()).Within(10.Seconds());
await That(timer.ExecutionCount).IsEqualTo(1L);

File / directory attributes
await That(sut.Attributes).HasFlag(FileAttributes.ReadOnly);
// becomes
await That(sut).HasAttribute(FileAttributes.ReadOnly);

Drive properties
await That(drive.AvailableFreeSpace).IsEqualTo(size);
// becomes
await That(drive).HasAvailableFreeSpace(size);
Also: HasTotalSize, HasTotalFreeSpace, HasVolumeLabel, HasDriveFormat, HasDriveType, HasName, IsReady.

File version info
await That(result.CompanyName).IsEqualTo(companyName);
// becomes
await That(result).HasCompanyName(companyName);
Also: HasFileDescription, HasFileVersion, HasLanguage, HasOriginalFilename, HasProductName, HasProductVersion.

Drive presence on the file system
await That(drives).HasSingle()
    .Matching(d => string.Equals(d.Name, driveName, StringComparison.Ordinal));
// becomes
await That(sut).HasDrive(driveName);

Intentionally not refactored

  • InMemoryContainerTests - subject is IStorageContainer, not IFileInfo/IDirectoryInfo.
  • IsGreaterThan / IsNotEmpty / IsNotNull on drive properties - the new API only covers equality.
  • IFileVersionInfo booleans (IsDebug, IsPatched, IsPreRelease) parameterised by bool - the new IsDebug() / IsNotDebug() shape would force a conditional and lengthen the test.
  • IFileVersionInfo properties with no extension in 0.15.0 - Comments, InternalName, LegalCopyright, LegalTrademarks, PrivateBuild, SpecialBuild, IsPrivateBuild, IsSpecialBuild, FileMajor/Minor/Build/PrivatePart, ProductMajor/Minor/Build/PrivatePart.
  • WithDrive_ShouldHavePathSeparatorSuffix - the test asserts the exact ordinal name form (D:), but HasDrive normalises trailing slashes, so the new API can't express the check.
  • PeriodicTimerMockTests - uses IPeriodicTimerMock; the new Executed() extension targets ITimerMock only.

vbreuss added 6 commits May 20, 2026 18:08
Pulls in the new IFileInfo/IDirectoryInfo attribute, IDriveInfo,
IFileVersionInfo, and ITimerMock expectations introduced in 0.15.0.
Replaces SemaphoreSlim + Interlocked + Volatile.Read coordination in two
DisableAutoAdvance tests with the new ITimerMock.Executed() assertion
from aweXpect.Testably 0.15.0. Drops 25 lines of synchronisation
plumbing while preserving the exact-count verification via the
ExecutionCount property.

ShouldNotBeAffectedByTimeChange and DisableAutoAdvance_ShouldStart...
stay as-is - they need per-tick coordination or capture the callback
timestamp, which the new API does not expose.
… info

Replaces assertions of the form
  await That(sut.Attributes).HasFlag(FileAttributes.X)
with the typed extension
  await That(sut).HasAttribute(FileAttributes.X)
(and the negated variant) introduced for IFileInfo/IDirectoryInfo
in aweXpect.Testably 0.15.0. The subject becomes the file/directory
itself, yielding clearer failure messages.

InMemoryContainerTests is intentionally left alone - its subject is
IStorageContainer, which the new extensions do not target.
Replaces property-then-IsEqualTo patterns with the typed IDriveInfo
extensions introduced in 0.15.0:

- That(drive.AvailableFreeSpace).IsEqualTo(x) -> That(drive).HasAvailableFreeSpace(x)
- That(drive.TotalSize).IsEqualTo(x)          -> That(drive).HasTotalSize(x)
- That(drive.TotalFreeSpace).IsEqualTo(x)     -> That(drive).HasTotalFreeSpace(x)
- That(drive.VolumeLabel).IsEqualTo(x)        -> That(drive).HasVolumeLabel(x)
- That(drive.DriveFormat).IsEqualTo(x)        -> That(drive).HasDriveFormat(x)
- That(drive.DriveType).IsEqualTo(x)          -> That(drive).HasDriveType(x)
- That(drive.Name).IsEqualTo(x)               -> That(drive).HasName(x)
- That(drive.IsReady).IsTrue()                -> That(drive).IsReady()

Assertions that the new API does not cover (IsGreaterThan, IsNotEmpty,
IsNotNull, IsNotNullOrEmpty, IsEqualTo with a runtime bool) are left
unchanged.
…ably

Replaces property-then-IsEqualTo patterns with typed extensions added
to IFileVersionInfo in 0.15.0:

- HasCompanyName, HasFileDescription, HasFileVersion, HasLanguage,
  HasOriginalFilename, HasProductName, HasProductVersion

Properties without dedicated extensions (Comments, InternalName,
LegalCopyright, LegalTrademarks, PrivateBuild, SpecialBuild,
IsDebug/IsPatched/IsPreRelease/IsPrivateBuild/IsSpecialBuild,
FileMajor/Minor/Build/PrivatePart, ProductMajor/Minor/Build/PrivatePart)
keep the original IsEqualTo form.
Replaces

  await That(drives).HasSingle()
      .Matching(d => string.Equals(d.Name, driveName, StringComparison.Ordinal));

with

  await That(sut).HasDrive(driveName);

introduced for IFileSystem in 0.15.0. Drive names are unique within a
file system, so HasDrive's "at least one drive with this name" is
equivalent to the prior "exactly one matching" check. The accompanying
length assertion is kept to preserve the test's count semantics.

Tests intentionally targeting an exact ordinal name form (e.g.
WithDrive_ShouldHavePathSeparatorSuffix, which verifies the trailing
separator) are left alone since HasDrive normalizes trailing slashes.
@vbreuss vbreuss self-assigned this May 20, 2026
@vbreuss vbreuss added refactor A change or improvement without functional impact dependencies Update of dependencies labels May 20, 2026
@vbreuss vbreuss enabled auto-merge (squash) May 20, 2026 16:14
@sonarqubecloud
Copy link
Copy Markdown

@vbreuss vbreuss merged commit 5275522 into main May 20, 2026
13 checks passed
@vbreuss vbreuss deleted the topic/modernize-tests-after-awexpect.testably-update branch May 20, 2026 16:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Update of dependencies refactor A change or improvement without functional impact

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant