diff --git a/.gitattributes b/.gitattributes index 2b79349044..f6e90d41d3 100644 --- a/.gitattributes +++ b/.gitattributes @@ -9,7 +9,10 @@ src/Verify/EmptyFiles/* binary *.verified.txt text eol=lf working-tree-encoding=UTF-8 *.verified.xml text eol=lf working-tree-encoding=UTF-8 +*.verified.md text eol=lf working-tree-encoding=UTF-8 *.verified.json text eol=lf working-tree-encoding=UTF-8 +*.verified.props text eol=lf working-tree-encoding=UTF-8 +*.verified.nuspec text eol=lf working-tree-encoding=UTF-8 src/.editorconfig text eol=lf working-tree-encoding=UTF-8 *.sln.DotSettings text eol=lf working-tree-encoding=UTF-8 diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 50eb5f98ed..2af506abeb 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -12,7 +12,7 @@ General questions may be better placed [StackOveflow](https://stackoverflow.com/ Where relevant, ensure you are using the current stable versions on your development stack. For example: - * Visual Studio + * Visual Studio or Rider * [.NET SDK or .NET Core SDK](https://www.microsoft.com/net/download) * Any related NuGet packages @@ -30,7 +30,8 @@ Add any other context about the problem here. #### Minimal Repro -Ensure you have replicated the bug in a minimal solution with the fewest moving parts. Often this will help point to the true cause of the problem. Upload this repro as part of the issue, preferably a public GitHub repository or a downloadable zip. The repro will allow the maintainers of this project to smoke test the any fix. +Ensure you have replicated the bug in a minimal solution with the fewest moving parts. Often this will help point to the true cause of the problem. Upload this repro as part of the issue, as a public GitHub repository or a downloadable zip. The repro will allow the maintainers of this project to smoke test the any fix. + #### Submit a PR that fixes the bug diff --git a/.gitignore b/.gitignore index 2d17ea5e54..98fd6dec40 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,5 @@ src/Verify.Tests/Tests.TextNegative.verified.tmp src/Verify.Tests/NewLineTests.StringWithDifferingNewline.verified.txt src/Verify.MSTest.Tests/Tests.AutoVerifyHasAttachment.verified.txt src/Verify.NUnit.Tests/Tests.AutoVerifyHasAttachment.verified.txt +src/Verify.TUnit.Tests/Tests.AutoVerifyHasAttachment.verified.txt +/src/Benchmarks/BenchmarkDotNet.Artifacts diff --git a/docs/anonymous-types.md b/docs/anonymous-types.md index e22572c894..d5e84c2a5f 100644 --- a/docs/anonymous-types.md +++ b/docs/anonymous-types.md @@ -37,7 +37,7 @@ public Task Anon() }); } ``` -snippet source | anchor +snippet source | anchor @@ -68,7 +68,7 @@ public Task Anon() }); } ``` -snippet source | anchor +snippet source | anchor @@ -98,7 +98,7 @@ public Task Anon() }); } ``` -snippet source | anchor +snippet source | anchor @@ -129,7 +129,7 @@ public Task Anon() }); } ``` -snippet source | anchor +snippet source | anchor diff --git a/docs/compared-to-assertion.md b/docs/compared-to-assertion.md index f4223fbff8..22e36f73af 100644 --- a/docs/compared-to-assertion.md +++ b/docs/compared-to-assertion.md @@ -81,7 +81,7 @@ public void TraditionalTest() Assert.Equal("USA", person.Address.Country); } ``` -snippet source | anchor +snippet source | anchor @@ -97,7 +97,7 @@ public Task SnapshotTest() return Verify(person); } ``` -snippet source | anchor +snippet source | anchor Produces a snapshot file `SnapshotTest.verified.txt`: @@ -121,4 +121,22 @@ Produces a snapshot file `SnapshotTest.verified.txt`: } ``` snippet source | anchor + +```txt +{ + GivenNames: John, + FamilyName: Smith, + Spouse: Jill, + Address: { + Street: 4 Puddle Lane, + Country: USA + }, + Children: [ + Sam, + Mary + ], + Id: Guid_1 +} +``` +snippet source | anchor diff --git a/docs/dates.md b/docs/dates.md index d2acea8255..214f111a36 100644 --- a/docs/dates.md +++ b/docs/dates.md @@ -7,7 +7,6 @@ To change this file edit the source file and then run MarkdownSnippets. # Dates - By default dates and times (`DateTime`, `DateTimeOffset`, `DateOnly`, and `TimeOnly`) are sanitized during verification. This is done by finding each date and taking a counter based that that specific date. That counter is then used replace the date values. This allows for repeatable tests when date values are changing. @@ -30,7 +29,7 @@ var target = new DateTimeTarget await Verify(target); ``` -snippet source | anchor +snippet source | anchor Results in the following: @@ -71,7 +70,7 @@ settings.DontScrubDateTimes(); return Verify(target, settings); ``` -snippet source | anchor +snippet source | anchor @@ -88,7 +87,7 @@ var target = new return Verify(target) .DontScrubDateTimes(); ``` -snippet source | anchor +snippet source | anchor @@ -101,13 +100,13 @@ return Verify(target) public static void ModuleInitializer() => VerifierSettings.DontScrubDateTimes(); ``` -snippet source | anchor +snippet source | anchor ## DisableDateCounting -If many calls are made to the the current date/time in quick succession, the date counting behavior (`DateTime_x`) can result in inconsistent results. To revert to the simpler scrubbing convention (`{Scrubbed}`) use DisableDateCounting. +If many calls are made to the current date/time in quick succession, the date counting behavior (`DateTime_x`) can result in inconsistent results. To revert to the simpler scrubbing convention (`{Scrubbed}`) use DisableDateCounting. ### Instance @@ -125,7 +124,7 @@ settings.DisableDateCounting(); return Verify(target, settings); ``` -snippet source | anchor +snippet source | anchor @@ -142,7 +141,7 @@ var target = new return Verify(target) .DisableDateCounting(); ``` -snippet source | anchor +snippet source | anchor @@ -155,7 +154,7 @@ return Verify(target) public static void ModuleInitializer() => VerifierSettings.DisableDateCounting(); ``` -snippet source | anchor +snippet source | anchor @@ -202,7 +201,7 @@ public Task ScrubInlineDateTimesInstance() settings); } ``` -snippet source | anchor +snippet source | anchor @@ -216,7 +215,7 @@ public Task ScrubInlineDateTimesFluent() => Verify("content 2020-10-20 content") .ScrubInlineDateTimes("yyyy-MM-dd"); ``` -snippet source | anchor +snippet source | anchor @@ -232,7 +231,7 @@ public static class ModuleInitializer VerifierSettings.ScrubInlineDateTimes("yyyy-MM-dd"); } ``` -snippet source | anchor +snippet source | anchor @@ -253,7 +252,7 @@ settings.AddNamedDateTime(new(2030, 1, 2), "instanceNamedDateTime"); settings.AddNamedDateTimeOffset(new DateTime(2030, 1, 2), "instanceNamedTimeOffset"); await Verify(target, settings); ``` -snippet source | anchor +snippet source | anchor @@ -268,7 +267,7 @@ await Verify(target) .AddNamedDateTime(new(2030, 1, 2), "instanceNamedDateTime") .AddNamedDateTimeOffset(new DateTime(2030, 1, 2), "instanceNamedTimeOffset"); ``` -snippet source | anchor +snippet source | anchor @@ -286,5 +285,138 @@ public static void NamedDatesAndTimesGlobal() VerifierSettings.AddNamedDateTimeOffset(new(new(2030, 1, 1)), "namedDateTimeOffset"); } ``` -snippet source | anchor +snippet source | anchor + + + +## Custom Comparers + +The following comparers can be overridden + + +### DateTime + +Default Comparer: + + + +```cs +class DateTimeComparer : IEqualityComparer +{ + public bool Equals(DateTime x, DateTime y) => + x == y && + x.Kind == y.Kind; + + public int GetHashCode(DateTime obj) => + obj.GetHashCode() + (int) obj.Kind; +} +``` +snippet source | anchor + + +Custom Comparer: + + + +```cs +[ModuleInitializer] +public static void UseCustomDateTimeComparer() => + Counter.UseDateTimeComparer(new CustomDateTimeComparer()); + +public class CustomDateTimeComparer : + IEqualityComparer +{ + public bool Equals(DateTime x, DateTime y) => + new DateTime(x.Year, x.Month, x.Day) == + new DateTime(y.Year, y.Month, y.Day); + + public int GetHashCode(DateTime date) => + new DateTime(date.Year, date.Month, date.Day).GetHashCode(); +} +``` +snippet source | anchor + + + +### DateTimeOffset + +Default Comparer: + + + +```cs +class DateTimeOffsetComparer : + IEqualityComparer +{ + public bool Equals(DateTimeOffset x, DateTimeOffset y) => + x == y && x.Offset == y.Offset; + + public int GetHashCode(DateTimeOffset obj) => + obj.GetHashCode() + (int) obj.Offset.TotalMinutes; +} +``` +snippet source | anchor + + +Custom Comparer: + + + +```cs +[ModuleInitializer] +public static void UseCustomDateTimeOffsetComparer() => + Counter.UseDateTimeOffsetComparer(new CustomDateTimeOffsetComparer()); + +public class CustomDateTimeOffsetComparer : + IEqualityComparer +{ + public bool Equals(DateTimeOffset x, DateTimeOffset y) => + new DateTimeOffset(new(x.Year, x.Month, x.Day)) == + new DateTimeOffset(new(y.Year, y.Month, y.Day)); + + public int GetHashCode(DateTimeOffset date) + { + var dateTime = new DateTime(date.Year, date.Month, date.Day); + return new DateTimeOffset(dateTime) + .GetHashCode(); + } +} +``` +snippet source | anchor + + + +### TimeOnly + +Default Comparer: + + + +```cs +EqualityComparer