Table of Contents

Class SnapshotFileResolver

Namespace
SnapshotAssertions
Assembly
SnapshotAssertions.dll

Path resolution for snapshot files. Computes the expected file path given a directory and either an explicit name or a (test class, test method) pair, plus the matching .actual.txt sibling path.

public static class SnapshotFileResolver
Inheritance
SnapshotFileResolver
Inherited Members

Remarks

All paths returned are absolute. The resolver does not touch the filesystem; the caller is responsible for ensuring the directory exists when writing the actual file.

Fields

ActualExtension

The file extension used for transient actual content written on mismatch or no-baseline.

public const string ActualExtension = ".actual.txt"

Field Value

string

DefaultSnapshotsFolder

The default subdirectory (relative to the test binary's directory) where snapshot files are read from and written to.

public const string DefaultSnapshotsFolder = "Snapshots"

Field Value

string

ExpectedExtension

The file extension used for committed expected baselines.

public const string ExpectedExtension = ".expected.txt"

Field Value

string

Methods

GetDefaultSnapshotsDirectory(string)

Returns the default snapshots directory, derived as {baseDirectory}/{DefaultSnapshotsFolder}.

public static string GetDefaultSnapshotsDirectory(string baseDirectory)

Parameters

baseDirectory string

The directory the snapshots folder lives under (typically the test binary's AppContext.BaseDirectory).

Returns

string

The absolute path to the default snapshots directory.

Exceptions

ArgumentNullException

baseDirectory is null.

ResolveByFile(string)

Resolves the expected and actual file paths from an explicit absolute or relative file path to the expected file. The path is normalized to absolute form against the current working directory if relative.

public static SnapshotPaths ResolveByFile(string expectedFilePath)

Parameters

expectedFilePath string

The path to the expected file (absolute or relative).

Returns

SnapshotPaths

The expected and actual paths. The actual path is the expected path with the ExpectedExtension suffix replaced by ActualExtension; if the path does not end in the expected extension, ActualExtension is appended to the expected path's stem.

Exceptions

ArgumentNullException

expectedFilePath is null.

ResolveByName(string, string)

Resolves the expected and actual file paths for a snapshot identified by an explicit name, located under snapshotsDirectory.

public static SnapshotPaths ResolveByName(string snapshotsDirectory, string snapshotName)

Parameters

snapshotsDirectory string

The absolute path to the directory containing snapshot files.

snapshotName string

The base name (without extension). Must be a valid file-name component on the host platform; path separators are rejected.

Returns

SnapshotPaths

The expected and actual paths.

Exceptions

ArgumentNullException

A required argument is null.

ArgumentException

snapshotsDirectory is empty or whitespace, or snapshotName contains a path separator or is empty / whitespace.

ResolveByTest(string, string, string, IReadOnlyList<object?>?)

Resolves the expected and actual file paths for a snapshot identified by a (test class, test method) pair, optionally augmented with a hash of the test method's arguments for parameterized tests. The base name is constructed as {testClassName}.{testMethodName} when testMethodArguments is null or empty, or {testClassName}.{testMethodName}.{argsHash} otherwise.

public static SnapshotPaths ResolveByTest(string snapshotsDirectory, string testClassName, string testMethodName, IReadOnlyList<object?>? testMethodArguments = null)

Parameters

snapshotsDirectory string

The absolute path to the directory containing snapshot files.

testClassName string

The simple test class name (no namespace).

testMethodName string

The test method name.

testMethodArguments IReadOnlyList<object>

The arguments passed to the parameterized test invocation, or null for non-parameterized tests. Each argument is stringified, the results joined with "|", and hashed with SHA-256; the first 8 hex characters of the hash are appended to the base name. Stringification routes by type so the key stays stable and culture-independent: a string is taken verbatim, an IFormattable (numbers, DateTime, TimeSpan, etc.) is formatted with InvariantCulture, an IEnumerable is expanded element-by-element as [item1,item2,...] (recursively, so nested collections expand too), and any other type falls back to ToString(object, IFormatProvider). The hash is stable across runs and machines for the same argument values, so each parameterized variant gets its own distinct snapshot file; changing a collection argument's elements changes the hash, and therefore the snapshot file.

Returns

SnapshotPaths

The expected and actual paths.

Exceptions

ArgumentNullException

A required argument is null.

ArgumentException

testClassName or testMethodName is empty or contains invalid file-name characters.

TryResolveSourceSnapshotsDirectory(string)

Resolves the source-tree snapshots directory: the committable Snapshots/ folder that lives next to the test project file, rather than the runtime copy under bin/. Used by accept-mode so that an accepted baseline is written where it is committed and read from, not into the build output where it is discarded on the next clean.

public static string? TryResolveSourceSnapshotsDirectory(string startDirectory)

Parameters

startDirectory string

The directory to start the upward search from (typically the test binary's AppContext.BaseDirectory).

Returns

string

The absolute path to the source-tree snapshots directory, or null if no ancestor project directory could be located.

Remarks

The read path resolves baselines from {AppContext.BaseDirectory}/Snapshots: the build copies Snapshots/**/*.expected.txt from the project directory into bin/ via the package's include glob. The accept write target is resolved by walking up from startDirectory (typically BaseDirectory) to the nearest ancestor that contains a *.csproj file, then appending DefaultSnapshotsFolder. That ancestor is the directory the build's include glob is relative to, so the accept write lands in the exact folder the next build copies back into bin/.

When no ancestor project file can be found (for example, a single-file publish where the source tree is not present), the method returns null: the caller falls back to the runtime directory so accept-mode still produces a file, even if it is not in the source tree.

Exceptions

ArgumentNullException

startDirectory is null.