Giter Site home page Giter Site logo

pinkuburu / verify Goto Github PK

View Code? Open in Web Editor NEW

This project forked from verifytests/verify

0.0 0.0 0.0 5.58 MB

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

License: MIT License

C# 99.72% F# 0.28% HTML 0.01%

verify's Introduction

Verify

Discussions Build 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.

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 ImplicitUsings. Ensure the following is set to have 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 = new()
            {
                "Sam",
                "Mary"
            },
            Address = new()
            {
                Street = "4 Puddle Lane",
                Country = "USA"
            }
        };
}

snippet source | anchor

xUnit

Support for xUnit

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

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

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 LR
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 LR
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 = new()
            {
                "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.

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 StreamMember()
{
    var stream = new MemoryStream(Encoding.UTF8.GetBytes("value"));
    return Verify(new
    {
        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

Received

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

eg. add the following to .gitignore

*.received.*

If using UseSplitModeForUniqueDirectory also include:

*.received/

Verified

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

All text extensions of *.verified.* and have eol set to lf.

eg add the following to .gitattributes

*.verified.txt text eol=lf
*.verified.xml text eol=lf
*.verified.json text eol=lf

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:

[UsesVerify]
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 Verifier.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.

Media

Extensions

More Documentation

Icon

Helmet designed by Leonidas Ikonomou from The Noun Project.

verify's People

Contributors

simoncropp avatar actions-user avatar dependabot-preview[bot] avatar 0xced avatar coenm avatar gbiellem avatar dependabot[bot] avatar andrewlock avatar atifaziz avatar bmueller84 avatar bchavez avatar distantcam avatar baronfel avatar chrissie1 avatar danielcweber avatar daviddesloovere avatar dparvin avatar dlemstra avatar erwan-joly avatar githubpang avatar heskandari avatar jankrivanek avatar jordanmarr avatar uniquelau avatar wilversings avatar mkaring avatar elnigno avatar patriksvensson avatar senal avatar stevedunn avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.