• Stars
    star
    1,983
  • Rank 23,367 (Top 0.5 %)
  • Language
    C#
  • License
    MIT License
  • Created about 5 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Verify is a snapshot tool that simplifies the assertion of complex data models and documents.

Verify

Discussions Build status NuGet Status NuGet Status NuGet Status NuGet Status NuGet Status NuGet Status

Verify is a snapshot tool that simplifies the assertion of complex data models and documents.

Verify is called on the test result during the assertion phase. It serializes that result and stores it in a file that matches the test name. On the next test execution, the result is again serialized and compared to the existing file. The test will fail if the two snapshots do not match: either the change is unexpected, or the reference snapshot needs to be updated to the new result.

See Milestones for release notes.

Sponsors

A HUGE Thank-You to AWS for sponsoring this project in September 2023 as part of the AWS Open Source Software Fund.

Thanks to DataDog for the generous monthly sponsorship.

Get customized instructions for the specific combination of Operating System, IDE, Test Framework, and Build Server.

Start wizard.

NuGet packages

Snapshot management

Accepting or declining a snapshot file is part of the core workflow of Verify. There are several ways to do this and the approach(s) selected is a personal preference.

Usage

ImplicitUsings

All examples use Implicit Usings. Ensure <ImplicitUsings> is set to enable to ensure examples compile correctly.

<ImplicitUsings>enable</ImplicitUsings>

If ImplicitUsings are not enabled, substitute usages of Verify() with Verifier.Verify().

Class being tested

Given a class to be tested:

public static class ClassBeingTested
{
    public static Person FindPerson() =>
        new()
        {
            Id = new("ebced679-45d3-4653-8791-3d969c4a986c"),
            Title = Title.Mr,
            GivenNames = "John",
            FamilyName = "Smith",
            Spouse = "Jill",
            Children =
            [
                "Sam",
                "Mary"
            ],
            Address = new()
            {
                Street = "4 Puddle Lane",
                Country = "USA"
            }
        };
}

snippet source | anchor

NUnit

Support for NUnit

[TestFixture]
public class Sample
{
    [Test]
    public Task Test()
    {
        var person = ClassBeingTested.FindPerson();
        return Verify(person);
    }
}

snippet source | anchor

xUnit

Support for xUnit

public class Sample
{
    [Fact]
    public Task Test()
    {
        var person = ClassBeingTested.FindPerson();
        return Verify(person);
    }
}

snippet source | anchor

Fixie

Support for Fixie

public class Sample
{
    public Task Test()
    {
        var person = ClassBeingTested.FindPerson();
        return Verify(person);
    }
}

snippet source | anchor

Expecto

Support for Expecto

open Expecto
open VerifyTests
open VerifyExpecto

[<Tests>]
let tests =
    testTask "findPerson" {
        let person = ClassBeingTested.FindPerson()
        do! Verifier.Verify("findPerson", person)
    }

snippet source | anchor

Caveats

Due to the nature of the Expecto implementation, the following APIs in Verify are not supported.

  • settings.UseParameters()
  • settings.UseTextForParameters()

MSTest

Support for MSTest

[TestClass]
public class Sample :
    VerifyBase
{
    [TestMethod]
    public Task Test()
    {
        var person = ClassBeingTested.FindPerson();
        return Verify(person);
    }
}

snippet source | anchor

Initial Verification

No existing .verified. file.

graph TD
run(Run test and<br/>create Received file)
failTest(Fail Test<br/>and show Diff)
closeDiff(Close Diff)
run-->failTest
shouldAccept{Accept ?}
failTest-->shouldAccept
accept(Move Received<br/>to Verified)
shouldAccept-- Yes -->accept
discard(Discard<br/>Received)
shouldAccept-- No -->discard
accept-->closeDiff
discard-->closeDiff

When the test is initially run will fail. If a Diff Tool is detected it will display the diff.

InitialDiff

To verify the result:

Verified result

This will result in the Sample.Test.verified.txt being created:

{
  GivenNames: John,
  FamilyName: Smith,
  Spouse: Jill,
  Address: {
    Street: 4 Puddle Lane,
    Country: USA
  },
  Children: [
    Sam,
    Mary
  ],
  Id: Guid_1
}

snippet source | anchor

Subsequent Verification

Existing .verified. file.

graph TD
run(Run test and<br/>create Received file)
closeDiff(Close Diff)
failTest(Fail Test<br/>and show Diff)
run-->isSame
shouldAccept{Accept ?}
failTest-->shouldAccept
accept(Move Received<br/>to Verified)
shouldAccept-- Yes -->accept
discard(Discard<br/>Received)
shouldAccept-- No -->discard

isSame{Compare<br/>Verified +<br/>Received}
passTest(Pass Test and<br/>discard Received)
isSame-- Same --> passTest
isSame-- Different --> failTest
accept-->closeDiff
discard-->closeDiff

If the implementation of ClassBeingTested changes:

public static class ClassBeingTested
{
    public static Person FindPerson() =>
        new()
        {
            Id = new("ebced679-45d3-4653-8791-3d969c4a986c"),
            Title = Title.Mr,
            // Middle name added
            GivenNames = "John James",
            FamilyName = "Smith",
            Spouse = "Jill",
            Children =
            [
                "Sam",
                "Mary"
            ],
            Address = new()
            {
                // Address changed
                Street = "64 Barnett Street",
                Country = "USA"
            }
        };
}

snippet source | anchor

And the test is re run it will fail.

The Diff Tool will display the diff:

SecondDiff

The same approach can be used to verify the results and the change to Sample.Test.verified.txt is committed to source control along with the change to ClassBeingTested.

Async

Verify() has overloads that accept Task<T>, ValueTask<T>, and IAsyncEnumerable<T>. These are awaited before verification.

There is also an overload that accepts Func<Task<T>>, which works well with async lambda expressions:

await Verify(
    async () => new
    {
        Foo = await repo.GetFoo(id),
        Bars = await repo.GetBars(id)
    });

snippet source | anchor

VerifyJson

VerifyJson performs the following actions

  • Convert to JToken (if necessary).
  • Apply ignore member by name for keys.
  • PrettyPrint the resulting text.

[Fact]
public Task VerifyJsonString()
{
    var json = "{'key': {'msg': 'No action taken'}}";
    return VerifyJson(json);
}

[Fact]
public Task VerifyJsonStream()
{
    var json = "{'key': {'msg': 'No action taken'}}";
    var stream = new MemoryStream(Encoding.UTF8.GetBytes(json));
    return VerifyJson(stream);
}

[Fact]
public Task VerifyJsonJToken()
{
    var json = "{'key': {'msg': 'No action taken'}}";
    var target = JToken.Parse(json);
    return Verify(target);
}

snippet source | anchor

Results in:

{
  key: {
    msg: No action taken
  }
}

snippet source | anchor

Source control: Received and Verified files

Includes/Excludes

  • All *.received.* files should be excluded from source control.

eg. add the following to .gitignore

*.received.*

If using UseSplitModeForUniqueDirectory also include:

*.received/

All *.verified.* files should be committed to source control.

Text file settings

Text variants of verified and received have the following characteristics:

This manifests in several ways:

Source control settings

All text extensions of *.verified.* should have:

  • eol set to lf
  • working-tree-encoding set to UTF-8

eg add the following to .gitattributes

*.verified.txt text eol=lf working-tree-encoding=UTF-8
*.verified.xml text eol=lf working-tree-encoding=UTF-8
*.verified.json text eol=lf working-tree-encoding=UTF-8

EditorConfig settings

If modifying text verified/received files in an editor, it is desirable for the editor to respect the above conventions. For EditorConfig enabled the following can be used:

# Verify settings
[*.{received,verified}.{txt,xml,json}]
charset = "utf-8-bom"
end_of_line = lf
indent_size = unset
indent_style = unset
insert_final_newline = false
tab_width = unset
trim_trailing_whitespace = false

Note that the above are suggested for subset of text extension. Add others as required based on the text file types being verified.

Static settings

Most settings are available at the both global level and at the instance level.

When modifying settings at the both global level it should be done using a Module Initializer:

public class StaticSettings
{
    [Fact]
    public Task Test() =>
        Verify("String to verify");
}

public static class StaticSettingsUsage
{
    [ModuleInitializer]
    public static void Initialize() =>
        VerifierSettings.AddScrubber(_ => _.Replace("String to verify", "new value"));
}

snippet source | anchor

VerifyResult

In some scenarios it can be helpful to get access to the resulting *.verified.* files after a successful run. For example to do an explicit check for contains or not-contains in the resulting text. To allow this all Verify methods return a VerifyResult.

var result = await Verify(
    new
    {
        Property = "Value To Check"
    });
Assert.Contains("Value To Check", result.Text);

snippet source | anchor

If using Verifier.Throws, the resulting Exception will also be accessible

var result = await Throws(MethodThatThrows);
Assert.NotNull(result.Exception);

snippet source | anchor

CurrentFile

Utility for finding paths based on the current file.

using IOPath = System.IO.Path;

namespace VerifyTests;

public static class CurrentFile
{
    public static string Path([CallerFilePath] string file = "") =>
        file;

    public static string Directory([CallerFilePath] string file = "") =>
        IOPath.GetDirectoryName(file)!;

    public static string Relative(string relative, [CallerFilePath] string file = "")
    {
        var directory = IOPath.GetDirectoryName(file)!;
        return IOPath.Combine(directory, relative);
    }
}

snippet source | anchor

Versioning

Verify follows Semantic Versioning. The same applies for extensions to Verify. Small changes in the resulting snapshot files may be deployed in a minor version. As such nuget updates to Verify.* should be done as follows:

  • Updates all Verify.*packages in isolation
  • Re-run all tests.
  • If there are changes, ensure they look correct given the release notes. If the changes do not look correct, raise an issue.
  • Accept those changes.

Snapshot changes do not trigger a major version change to avoid causing Diamond dependency issues for downstream extensions.

Unit testing inside virtualized environment

Unit tests referencing Verify (including unit tests within this repository as well as any other code referencing Verify) can be run and debugged on a local virtualized environment supported by Visual Studio Remote Testing. Initial configurations have been added for WSL and net 7.0 linux docker via testenvironments.json (for third party code, the file needs to be copied or recreated next to the .sln solution file for solution to leverage the functionality).

Upon opening the Tests Explorer the advanced environments are available in the GUI:

TestExplorerEnvironments

This readme will not discuss definitive list of details for proper setup of the environments instead refer the following information sources and warn about particular gotchas:

Media

Extensions

More Documentation

Icon

Helmet designed by Leonidas Ikonomou from The Noun Project.

More Repositories

1

DiffEngine

Manages launching and cleanup of diff tools
C#
138
star
2

Verify.EntityFramework

Extends Verify to allow verification of EntityFramework bits.
C#
47
star
3

Verify.SourceGenerators

Extends Verify to allow verification of C# Source Generators.
C#
37
star
4

EmptyFiles

A collection of minimal binary files.
C#
30
star
5

Verify.Terminal

A dotnet tool for managing Verify snapshots.
C#
30
star
6

Verify.Blazor

Support for rendering a Blazor Component to a verified file via bunit or raw Blazor rendering.
C#
26
star
7

Verify.Xaml

Extends Verify to allow verification of Xaml UIs
C#
19
star
8

Verify.Avalonia

Extends Verify to allow verification of Avalonia UIs
C#
19
star
9

Verify.HeadlessBrowsers

Extends Verify to allow verification of Web UIs using Selenium, Playwright, or Puppeteer
C#
17
star
10

Verify.Http

Extends Verify to allow verification of web bits.
C#
17
star
11

Verify.SqlServer

Extends Verify to allow verification of SqlServer bits.
C#
13
star
12

Verify.Moq

Adds Verify support for verifying Moq types.
C#
12
star
13

Verify.Go

Verify.Go is a snapshot tool for Go language that simplifies the assertion of complex data models and documents.
Go
11
star
14

Verify.QuestPDF

C#
9
star
15

Verify.MassTransit

Adds Verify support for MassTransit test helpers.
C#
9
star
16

Verify.DocNet

Extends Verify to allow verification of documents via DocNet.
C#
9
star
17

Verify.Wolverine

Adds Verify support for verifying Wolverine via a custom test context.
C#
8
star
18

Verify.ImageSharp

Extends Verify to allow verification of documents via ImageSharp.
C#
8
star
19

Verify.ZeroLog

Extends Verify to allow verification of ZeroLog bits.
C#
6
star
20

Verify.PdfPig

Extends Verify to allow verification of documents via PdfPig
C#
6
star
21

Verify.AngleSharp

Extends Verify to allow comparison of html files via AngleSharp.
C#
6
star
22

Verify.DiffPlex

Extends Verify to allow comparison of text via DiffPlex.
C#
6
star
23

Verify.ICSharpCode.Decompiler

Extends Verify to allow verification of assemblies via ICSharpCode.Decompiler
C#
6
star
24

Verify.Aspose

Extends Verify to allow verification of documents via Aspose.
C#
5
star
25

Verify.ImageHash

C#
5
star
26

Verify.ImageMagick

Extends Verify to allow verification of documents via ImageMagick.NET.
C#
5
star
27

Verify.WinForms

Extends Verify to allow verification of WinForms UIs.
C#
5
star
28

Verify.NServiceBus

Adds Verify (https://github.com/VerifyTests/Verify) support to verify NServiceBus Test Contexts
C#
4
star
29

Verify.Phash

Extends Verify to allow comparison of documents via Phash.
C#
4
star
30

Verify.MicrosoftLogging

C#
4
star
31

Verify.Xamarin

Extends Verify to allow verification of Xamarin UIs.
C#
4
star
32

Verify.ImageSharp.Compare

Extends Verify to allow comparison of images via ImageSharp.Compare.
C#
4
star
33

Verify.Sample

C#
3
star
34

Verify.Quibble

Extends Verify to allow comparison of text via Quibble.
C#
3
star
35

Verify.Syncfusion

Extends Verify to allow verification of documents via Syncfusion File Formats.
C#
3
star
36

Verify.RavenDB

Extends Verify to allow verification of RavenDB bits.
C#
3
star
37

Verify.NodaTime

Adds Verify support for scrubbing NodaTime values.
C#
3
star
38

Verify.Cosmos

C#
2
star
39

Verify.FakeItEasy

Adds Verify support for verifying FakeItEasy types.
C#
2
star
40

Verify.AspNetCore

C#
2
star
41

Verify.Brighter

Adds Verify support for verifying Brighter.
C#
2
star
42

Verify.NewtonsoftJson

C#
1
star
43

Verify.CommunityToolkit.Mvvm

Extends Verify to allow verification of CommunityToolkit.Mvvm.
C#
1
star
44

BlazorVerifyExperiments

HTML
1
star
45

Verify.GrapeCity

Extends Verify to allow verification of documents via GrapeCity Documents.
C#
1
star
46

Discussions

GitHub Discussions for VerifyTests
1
star
47

Verify.SystemJson

Adds Verify support for converting System.Text.Json types
C#
1
star