Welcome to Shouldly’s documentation!¶
How asserting Should be
Attention
These docs are in progress! Get involved at Learn more about on GitHub, contributions welcome! First time contributors welcome, we are happy to help you get started.
This is the old Assert way:
Assert.That(contestant.Points, Is.EqualTo(1337));
For your troubles, you get this message, when it fails:
Expected 1337 but was 0
How it Should be:
contestant.Points.ShouldBe(1337);
Which is just syntax, so far, but check out the message when it fails:
contestant.Points should be 1337 but was 0
It might be easy to underestimate how useful this is. Another example, side by side:
Assert.That(map.IndexOfValue("boo"), Is.EqualTo(2)); // -> Expected 2 but was 1
map.IndexOfValue("boo").ShouldBe(2); // -> map.IndexOfValue("boo") should be 2 but was 1
Shouldly uses the variables within the ShouldBe statement to report on errors, which makes diagnosing easier.
Another example, if you compare two collections:
new[] { 1, 2, 3 }.ShouldBe(new[] { 1, 2, 4 });
and it fails because they’re different, it’ll show you the differences between the two collections:
should be
[1, 2, 4]
but was
[1, 2, 3]
difference
[1, 2, *3*]
Shouldly has plenty of different assertions, have a look under the assertions folder for all the options.
ShouldBe¶
Numeric¶
ShouldBe
numeric overloads accept tolerances and has overloads for float
, double
and decimal
types.
Exception
DateTime(Offset)¶
DateTime overloads are similar to the numeric overloads and support tolerances.
Exception
TimeSpan¶
TimeSpan also has tolerance overloads
Exception
Want to improve shouldy? We have an open issue at [#303](https://github.com/shouldly/shouldly/issues/303) to improve this error message!
Enumerables¶
Enumerable comparison is done on the elements in the enumerable, so you can compare an array to a list and have it pass.
Exception
Enumerables of Numerics¶
If you have enumerables of float
, decimal
or double
types then you can use the tolerance overloads, similar to the value extensions.
Exception
Bools¶
Exception
ShouldNotBe¶
ShouldNotBe
is the inverse of ShouldBe
.
Numeric¶
ShouldNotBe
also allows you to compare numeric values, regardless of their value type.
Integer¶
Exception
Long¶
Exception
DateTime(Offset)¶
ShouldNotBe
DateTime overloads are similar to the numeric overloads and also support tolerances.
Exception
ShouldMatchApproved¶
Based on the awesome ApprovalTest.Net, Shouldly has ShouldMatchApproved()
to do approval based testing. The main goal of Shouldly’s approval testing is for it to be simple, intuative and give great error messages.
Approved File does not exist¶
When you first run a ShouldMatchApproved
test, you will be presented with a diff viewer and a failing test.
Exception
Screenshot

Approved File does not match received¶
After you have approved the text, when it changes you get a different experience.
Exception
Screenshot

Options and customisation¶
While the defaults should work fine, often you need to customise things easily. ApprovalTests is highly configurable but the configuration is not always discoverable. Shouldly wants to make configuration simple and discoverable. This section covers the local customisations availble for a single ShouldMatchApproved call.
Defaults¶
The first thing to note is that by default Shouldly ignores line endings. This saves painful failures on the build server when git checks out the approved files with n rather than rn which the received file has. You can opt out of this behaviour for a single call, or globally. For global defaults see the Configuration section.
Usage¶
toVerify.ShouldMatchApproved(configurationBuilder => configurationBuilder.OPTION())
where OPTION can be one of the following methods.
DoNotIgnoreLineEndings¶
Tells shouldly to use a line ending sensitive comparison.
toVerify.ShouldMatchApproved(c => c.DoNotIgnoreLineEndings())
WithStringCompareOptions¶
Sets the string comparison options
var options = StringCompareShould.IgnoreCase | StringCompareShould.IgnoreLineEndings;
toVerify.ShouldMatchApproved(c => c.WithStringCompareOptions(options))
WithDescriminator¶
By default the approved and received files are named ${MethodName}.approved.txt
, WithDescriminator
allows you to descriminate multiple files, useful for data driven tests which can have multiple executions of a single method. For example
[Fact] void Simpsons() { toVerify.ShouldMatchApproved(c => c.WithDescriminator("Bart")) }
Will result in a approved file with the name Simpsons.Bart.approved.txt
NoDiff¶
Prevents the diff viewer from opening up. Doing this you can use Shouldly’s error messages to verify the changes then run the command in the exception message to approve the changes.
toVerify.ShouldMatchApproved(c => c.NoDiff())
WithFileExtension¶
Override the file exension of the approved/received files. The default is .txt.
toVerify.ShouldMatchApproved(c => c.WithFileExtension(".cs"))
SubFolder¶
Put the approved/received files into a sub-directory
toVerify.ShouldMatchApproved(c => c.SubFolder("Approvals"))
UseCallerLocation¶
By default shouldly will walk the stacktrace to find the first non-shouldly method (not including anonymous methods and compiler generated stuff like the async state machine) and use that method for the approval filename. I.e a test named MyTest
will result in a received filename of MyTest.received.txt
.
This setting tells shouldly to walk one more frame, this is really handy when you have created a utility function which calls ShouldMatchApproved
.
[Fact]
public void MyTest()
{
SomeUtilityMethod("Foo");
}
void SomeUtilityMethod(string toApprove)
{
toApprove.ShouldMatchApproved(c => c.UseCallerLocation());
}
// -> MyTest.received.txt - without UseCallerLocation() the file would be called SomeUtilityMethod.received.txt
LocateTestMethodUsingAttribute¶
If you want to locate your test method using an attribute that is easy too!
// XUnit
"testAttributes".ShouldMatchApproved(b => b.LocateTestMethodUsingAttribute<FactAttribute>());
// NUnit
"testAttributes".ShouldMatchApproved(b => b.LocateTestMethodUsingAttribute<TestAttribute>());
WithScrubber¶
Scrubbers allow you to remove dynamic content, such as the current date
toVerify.ShouldMatchApproved(c => c.WithScrubber(s => Regex.Replace(s, "\d{1,2}/\d{1,2}/\d{2,4}", "<date>"))
Will turn Today is 01/01/2016
into Today is <date>
in the received file.
Configuration¶
Because this feature is quite new shouldly doesn’t have many Diff tools or know all the places it shouldn’t open the diff tool. The global configuration of Shouldly is very easy to change and extend. If you do add a difftool or a should not open difftool strategy then please submit a pull request so everyone gets the benefits!
Changing default options¶
All of the instance based configuration can be changed globally through ShouldlyConfiguration.ShouldMatchApprovedDefaults
. For example to make the default behaviour be line ending sensitive you can just run this before any tests execute ShouldlyConfiguration.ShouldMatchApprovedDefaults.DoNotIgnoreLineEndings()
Adding a difftool¶
So Shouldly doesn’t support your favorite difftool yet. No worries, it’s easy to add your own.
var diffomatic3000 = new DiffTool(
"Diffomatic3000",
@"diffomatic3000\diffomatic3000.exe",
(received, approved, approvedExists) => $"\{received}\" \"{approved}\"")
ShouldlyConfiguration.DiffTools.RegisterDiffTool(diffomatic3000);
This will discover diffomatic3000.exe if it’s in your PATH or if it exists in any Program Files directory under diffomatic3000diffomatic3000.exe
If you do this, please submit a PR to add it to the KnownDiffTools
, you can also test how it works by running the Shouldly.TestsTestDiffTools project!
Adding a do not launch difftool strategy¶
We don’t really want to be opening difftools in nCrunch, or on the build server and a number of other scenarios. So ShouldlyConfiguration.DiffTools.KnownDoNotLaunchStrategies
allows you to add in scenarios which Shouldly doesn’t know about yet. Once again, please submit PR’s if you need to do this :)
Currently the only strategy is to check for environmental variables, but you can implement IShouldNotLaunchDiffTool
to implement any logic you want. Assuming it’s just an environmental variable:
ShouldlyConfiguration.DiffTools.AddDoNotLaunchStrategy(new DoNotLaunchWhenEnvVariableIsPresent("NCRUNCH"));
Setting Diff tool priority¶
Shouldly launches the first found difftool, if you want to give priority to another difftool you can do that.
ShouldlyConfiguration.DiffTools.SetDiffToolPriorities(
KnownDiffTools.Instance.BeyondCompare4,
KnownDiffTools.Instance.KDiff3);
The priority tools will be checked before falling back to the entire known difftool list.
ShouldBeTrue/False¶
ShouldBeTrue
and ShouldBeFalse
work on boolean values.
ShouldBeTrue¶
Exception
ShouldBeFalse¶
Exception
ShouldBeNull/NotBeNull¶
ShouldBeNull
and ShouldNotBeNull
allow you to check whether or not a type’s reference is null.
ShouldBeNull¶
Exception
ShouldNotBeNull¶
Exception
ShouldHaveFlag/NotHaveFlag¶
ShouldHaveFlag
allows you to assert whether an object is an enum and has a flag specified.
Conversely ShouldNotHaveFlag
allows you to assert the opposite; that an object is an enum but does not have a flag specified.
ShouldHaveFlag¶
Exception
ShouldNotHaveFlag¶
Exception
Example Classes¶
The classes used in these samples are:
using System;
namespace Simpsons
{
public abstract class Pet
{
public abstract string Name { get; set; }
public override string ToString()
{
return Name;
}
}
public class Cat : Pet
{
public override string Name { get; set; }
}
public class Dog : Pet
{
public override string Name { get; set; }
}
public class Person
{
public Person()
{
}
public Person(string name)
{
Name = name ?? throw new ArgumentNullException(nameof(name));
}
public string Name { get; set; }
public int Salary { get; set; }
public override string ToString()
{
return Name;
}
}
}
Contributing¶
Once you have cloned Shouldly to your local machine, the following instructions will walk you through installing the tools necessary to build and test the documentation.
Download python version 2.7.10 or higher.
If you are installing on Windows, add both the Python install directory and the Python scripts directory to your
PATH
environment variable. For example, if you install Python into thec:\python34
directory, you would addc:\python34;c:\python34\scripts
to yourPATH
environment variable.Install Sphinx by opening a command prompt and running the following Python command. (Note that this operation might take a few minutes to complete.):
pip install sphinx
By default, when you install Sphinx, it will install the ReadTheDocs custom theme automatically. If you need to update the installed version of this theme, you should run:
pip install -U sphinx_rtd_theme
Run the make.bat file using html argument to build the stand-alone version of the project in question:
make html
Once make completes, the generated docs will be in the
_build/html
directory. Simply open theindex.html
file in your browser to see the built docs for that project.
Style Guidelines¶
Please review the following style guides:
Configuration¶
Shouldly has a few configuration options:
DefaultFloatingPointTolerance¶
Allows specifying a floating point tolerance for all assertions
Default value: 0.0d
DefaultTaskTimeout¶
Should.Throw(Func<Task>)
blocks, the timeout is a safeguard for deadlocks.
Shouldly runs the lambda without a synchronisation context, but deadlocks are still possible. Use Should.ThrowAsync
to be safe then await the returned task to prevent possible deadlocks.
Default value: 10 seconds
CompareAsObjectTypes¶
Types which also are IEnumerable of themselves.
An example is Newtonsoft.Json.Linq.JToken
which looks like this class JToken : IEnumerable<JToken>
.
Default value: Newtonsoft.Json.Linq.JToken