Display a readable diff between two objects
$ dotnet add package DEdge.DiffractDiffract is a .NET library that displays a readable diff between two objects. It is particularly useful for unit testing complex objects. Diffract is maintained by folks at D-EDGE.Here is an example:```csharp using DEdge.Diffract;
record User(string Name, int Age, string[] Pets);
var expected = new User("Emma", 42, new[] { "Oscar", "Fluffy", "Tibbles" }); var actual = new User("Andy", 42, new[] { "Oscar", "Sparky" });
Differ.Assert(expected, actual);
```The above throws an AssertionFailedException with the following message: Value differs by 2 fields:
Name Expect = "Emma"
Actual = "Andy"
Pets collection differs:
Pets.Count Expect = 3
Actual = 2
Pets[1] Expect = "Fluffy"
Actual = "Sparky"Diffract can drill down many composite types:* POCOs;
IEnumerable<T>);IDictionary<K, V>, IReadOnlyDictionary<K, V>);string and int in the above example) are treated as leaves that can be tested for equality.## Example outputsPOCO or record with multiple field differences:```csharp
record User(string Name, int Age, bool IsActive);var expected = new User("Emma", 42, true);
var actual = new User("Andy", 35, true);Value differs by 2 fields:
Name Expect = "Emma"
Actual = "Andy"
Age Expect = 42
Actual = 35
F# union where the case is different:fsharp
type Contact =
| Email of address: string
| Phone of number: string
let expected = Email "user@example.com"
let actual = Phone "555-123-456"Value differs by union case:
Expect is Email
Actual is Phone
F# union where the case is the same and the value is different:fsharp
type Contact =
| Email of address: string
| Phone of number: string
let expected = Email "user@example.com"
let actual = Email "someone@example.com"Value differs by union case Email fields:
address Expect = "user@example.com"
Actual = "someone@example.com"
Enumerables show the counts if they differ, followed by the diffs per item:csharp
var expected = new string[] { "first", "second" };
var actual = new string[] { "first", "2nd", "third" };Value collection differs:
Count Expect = 2
Actual = 3
[1] Expect = "second"
Actual = "2nd"
Dictionaries show the keys missing on either side, followed by the diffs per item that exists in both:csharp
var expected = new Dictionary<string, int>
{
{ "first", 1 },
{ "second", 2 },
{ "third", 3 },
};
var actual = new Dictionary<string, int>
{
{ "first", 1 },
{ "third", 2 },
{ "fourth", 4 },
};Value dictionary differs:
["second"] Actual is missing
["fourth"] Expect is missing
["third"] Expect = 3
Actual = 2
## APIDiffract lives in the namespace `DEdge.Diffract`. Its main API is the class `Differ`, which provides the following methods:csharp
void Assert(T expected, T actual, IDiffer differ = null, PrintParams param = null)
Computes the diff between two objects and, if it is not empty, throws an `AssertionFailedException` with the diff as message.csharp
string ToString(T expected, T actual, IDiffer differ = null, PrintParams param = null)
Prints the diff between two objects to a string.csharp
void Write(T expected, T actual, TextWriter writer = null, IDiffer differ = null, PrintParams param = null)
Prints the diff between two objects to the given TextWriter (or to standard output if not provided).csharp
FSharpOption Diff(T expected, T actual, IDiffer differ = null)
```Computes the diff between two objects. Returns None if the objects are found to be equal.