Skip to content

Commit

Permalink
Merge pull request nunit#4618 from RenderMichael/tolerance
Browse files Browse the repository at this point in the history
Add support for DateTime comparison with TimeSpan tolerance
  • Loading branch information
OsirisTerje authored Feb 15, 2024
2 parents 68d9947 + 47bfede commit 56fa6f4
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 59 deletions.
5 changes: 5 additions & 0 deletions src/NUnitFramework/framework/Constraints/Tolerance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,11 @@ private Range LinearRange(object value)
return new Range(v - amount, v + amount);
}

if (Amount is TimeSpan interval && value is DateTime dateTime)
{
return new Range(dateTime - interval, dateTime + interval);
}

throw new InvalidOperationException("Cannot create range for a non-numeric value");
}

Expand Down
48 changes: 33 additions & 15 deletions src/NUnitFramework/tests/Constraints/GreaterThanConstraintTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt

using System;
using System.Collections.Generic;

using NUnit.Framework.Constraints;

namespace NUnit.Framework.Tests.Constraints
Expand Down Expand Up @@ -45,27 +48,42 @@ public void CanCompareIComparablesOfInt()
Assert.That(actual, Is.GreaterThan(expected));
}

[TestCase(6.0, 5.0, 0.05)]
[TestCase(5.05, 5.0, 0.05)] // upper range bound
[TestCase(5.0001, 5.0, 0.05)]
[TestCase(4.9999, 5.0, 0.05)]
[TestCase(4.9501, 5.0, 0.05)] // lower range bound + .01
[TestCase(210, 200, 5)]
[TestCase(205, 200, 5)] // upper range bound
[TestCase(202, 200, 5)]
[TestCase(198, 200, 5)]
[TestCase(196, 200, 5)] // lower range bound + 1
private static readonly DateTime ConstantDateTime = new(2024, 1, 1, 1, 1, 1);

private static IEnumerable<object[]> GetSimpleToleranceData()
{
yield return new object[] { 6.0, 5.0, 0.05 };
yield return new object[] { 5.05, 5.0, 0.05 }; // upper range bound
yield return new object[] { 5.0001, 5.0, 0.05 };
yield return new object[] { 4.9999, 5.0, 0.05 };
yield return new object[] { 4.9501, 5.0, 0.05 }; // lower range bound + .01
yield return new object[] { 210, 200, 5 };
yield return new object[] { 205, 200, 5 }; // upper range bound
yield return new object[] { 202, 200, 5 };
yield return new object[] { 198, 200, 5 };
yield return new object[] { 196, 200, 5 }; // lower range bound + 1
yield return new object[] { ConstantDateTime, ConstantDateTime.AddSeconds(1), TimeSpan.FromSeconds(2) };
}

[TestCaseSource(nameof(GetSimpleToleranceData))]
public void SimpleTolerance(object actual, object expected, object tolerance)
{
#pragma warning disable NUnit2042 // Comparison constraint on object
Assert.That(actual, Is.GreaterThan(expected).Within(tolerance));
#pragma warning restore NUnit2042 // Comparison constraint on object
}

[TestCase(4.95, 5.0, 0.05)] // lower range bound
[TestCase(4.9, 5.0, 0.05)]
[TestCase(195, 200, 5)] // lower range bound
[TestCase(190, 200, 5)]
private static IEnumerable<object[]> GetSimpleTolerance_FailureData()
{
yield return new object[] { 4.95, 5.0, 0.05 }; // lower range bound
yield return new object[] { 4.9, 5.0, 0.05 };
yield return new object[] { 195, 200, 5 }; // lower range bound
yield return new object[] { 190, 200, 5 };
yield return new object[] { ConstantDateTime, ConstantDateTime.AddSeconds(2), TimeSpan.FromSeconds(1) };
yield return new object[] { ConstantDateTime, ConstantDateTime.AddSeconds(2), TimeSpan.FromSeconds(2) };
}

[TestCaseSource(nameof(GetSimpleTolerance_FailureData))]
public void SimpleTolerance_Failure(object actual, object expected, object tolerance)
{
#pragma warning disable NUnit2042 // Comparison constraint on object
Expand All @@ -74,7 +92,7 @@ public void SimpleTolerance_Failure(object actual, object expected, object toler
"Assertion should have failed");
#pragma warning restore NUnit2042 // Comparison constraint on object

Assert.That(ex?.Message, Contains.Substring("Expected: greater than " + expected));
Assert.That(ex?.Message, Contains.Substring("Expected: greater than " + MsgUtils.FormatValue(expected)));
}

[TestCase(6.0, 5.0, 1)]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt

using System;
using System.Collections.Generic;

using NUnit.Framework.Constraints;

namespace NUnit.Framework.Tests.Constraints
Expand Down Expand Up @@ -45,27 +48,42 @@ public void CanCompareIComparablesOfInt()
Assert.That(actual, Is.GreaterThanOrEqualTo(expected));
}

[TestCase(6.0, 5.0, 0.05)]
[TestCase(5.05, 5.0, 0.05)] // upper range bound
[TestCase(5.0001, 5.0, 0.05)]
[TestCase(4.9999, 5.0, 0.05)]
[TestCase(4.9501, 5.0, 0.05)] // lower range bound + .01
[TestCase(4.95, 5.0, 0.05)] // lower range bound
[TestCase(210, 200, 5)]
[TestCase(205, 200, 5)] // upper range bound
[TestCase(202, 200, 5)]
[TestCase(198, 200, 5)]
[TestCase(196, 200, 5)] // lower range bound + 1
[TestCase(195, 200, 5)] // lower range bound
private static readonly DateTime ConstantDateTime = new(2024, 1, 1, 1, 1, 1);

private static IEnumerable<object[]> GetSimpleToleranceData()
{
yield return new object[] { 6.0, 5.0, 0.05 };
yield return new object[] { 5.05, 5.0, 0.05 }; // upper range bound
yield return new object[] { 5.0001, 5.0, 0.05 };
yield return new object[] { 4.9999, 5.0, 0.05 };
yield return new object[] { 4.9501, 5.0, 0.05 }; // lower range bound + .01
yield return new object[] { 4.95, 5.0, 0.05 }; // lower range bound
yield return new object[] { 210, 200, 5 };
yield return new object[] { 205, 200, 5 }; // upper range bound
yield return new object[] { 202, 200, 5 };
yield return new object[] { 198, 200, 5 };
yield return new object[] { 196, 200, 5 }; // lower range bound + 1
yield return new object[] { 195, 200, 5 }; // lower range bound
yield return new object[] { ConstantDateTime, ConstantDateTime.AddSeconds(1), TimeSpan.FromSeconds(2) };
yield return new object[] { ConstantDateTime, ConstantDateTime.AddSeconds(2), TimeSpan.FromSeconds(2) };
}

[TestCaseSource(nameof(GetSimpleToleranceData))]
public void SimpleTolerance(object actual, object expected, object tolerance)
{
#pragma warning disable NUnit2042 // Comparison constraint on object
Assert.That(actual, Is.GreaterThanOrEqualTo(expected).Within(tolerance));
#pragma warning restore NUnit2042 // Comparison constraint on object
}

[TestCase(4.9, 5.0, 0.05)]
[TestCase(190, 200, 5)]
private static IEnumerable<object[]> GetSimpleTolerance_FailureData()
{
yield return new object[] { 4.9, 5.0, 0.05 };
yield return new object[] { 190, 200, 5 };
yield return new object[] { ConstantDateTime, ConstantDateTime.AddSeconds(2), TimeSpan.FromSeconds(1) };
}

[TestCaseSource(nameof(GetSimpleTolerance_FailureData))]
public void SimpleTolerance_Failure(object actual, object expected, object tolerance)
{
#pragma warning disable NUnit2042 // Comparison constraint on object
Expand All @@ -74,7 +92,7 @@ public void SimpleTolerance_Failure(object actual, object expected, object toler
"Assertion should have failed");
#pragma warning restore NUnit2042 // Comparison constraint on object

Assert.That(ex?.Message, Contains.Substring("Expected: greater than or equal to " + expected));
Assert.That(ex?.Message, Contains.Substring("Expected: greater than or equal to " + MsgUtils.FormatValue(expected)));
}

[TestCase(6.0, 5.0, 1)]
Expand Down
46 changes: 32 additions & 14 deletions src/NUnitFramework/tests/Constraints/LessThanConstraintTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt

using System;
using System.Collections.Generic;

using NUnit.Framework.Constraints;

namespace NUnit.Framework.Tests.Constraints
Expand Down Expand Up @@ -45,27 +48,42 @@ public void CanCompareIComparablesOfInt()
Assert.That(actual, Is.LessThan(expected));
}

[TestCase(4.0, 5.0, 0.05)]
[TestCase(4.95, 5.0, 0.05)] // lower range bound
[TestCase(4.9501, 5.0, 0.05)] // lower range bound + .01
[TestCase(4.9999, 5.0, 0.05)]
[TestCase(5.0001, 5.0, 0.05)]
[TestCase(190, 200, 5)]
[TestCase(195, 200, 5)] // lower range bound
[TestCase(196, 200, 5)] // lower range bound + 1
[TestCase(198, 200, 5)]
[TestCase(202, 200, 5)]
private static readonly DateTime ConstantDateTime = new(2024, 1, 1, 1, 1, 1);

private static IEnumerable<object[]> GetSimpleToleranceData()
{
yield return new object[] { 4.0, 5.0, 0.05 };
yield return new object[] { 4.95, 5.0, 0.05 }; // lower range bound
yield return new object[] { 4.9501, 5.0, 0.05 }; // lower range bound + .01
yield return new object[] { 4.9999, 5.0, 0.05 };
yield return new object[] { 5.0001, 5.0, 0.05 };
yield return new object[] { 190, 200, 5 };
yield return new object[] { 195, 200, 5 }; // lower range bound
yield return new object[] { 196, 200, 5 }; // lower range bound + 1
yield return new object[] { 198, 200, 5 };
yield return new object[] { 202, 200, 5 };
yield return new object[] { ConstantDateTime, ConstantDateTime.AddSeconds(-1), TimeSpan.FromSeconds(2) };
}

[TestCaseSource(nameof(GetSimpleToleranceData))]
public void SimpleTolerance(object actual, object expected, object tolerance)
{
#pragma warning disable NUnit2042 // Comparison constraint on object
Assert.That(actual, Is.LessThan(expected).Within(tolerance));
#pragma warning restore NUnit2042 // Comparison constraint on object
}

[TestCase(5.05, 5.0, 0.05)] // upper range bound
[TestCase(6.0, 5.0, 0.05)]
[TestCase(205, 200, 5)] // upper range bound
[TestCase(210, 200, 5)]
private static IEnumerable<object[]> GetSimpleTolerance_FailureData()
{
yield return new object[] { 5.05, 5.0, 0.05 }; // upper range bound
yield return new object[] { 6.0, 5.0, 0.05 };
yield return new object[] { 205, 200, 5 }; // upper range bound
yield return new object[] { 210, 200, 5 };
yield return new object[] { ConstantDateTime, ConstantDateTime.AddSeconds(-2), TimeSpan.FromSeconds(2) };
yield return new object[] { ConstantDateTime, ConstantDateTime.AddSeconds(-2), TimeSpan.FromSeconds(1) };
}

[TestCaseSource(nameof(GetSimpleTolerance_FailureData))]
public void SimpleTolerance_Failure(object actual, object expected, object tolerance)
{
#pragma warning disable NUnit2042 // Comparison constraint on object
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt

using System;
using System.Collections.Generic;

using NUnit.Framework.Constraints;

namespace NUnit.Framework.Tests.Constraints
Expand Down Expand Up @@ -45,27 +48,42 @@ public void CanCompareIComparablesOfInt()
Assert.That(actual, Is.LessThanOrEqualTo(expected));
}

[TestCase(4.0, 5.0, 0.05)]
[TestCase(4.95, 5.0, 0.05)] // lower range bound
[TestCase(4.9501, 5.0, 0.05)] // lower range bound + .01
[TestCase(4.9999, 5.0, 0.05)]
[TestCase(5.0001, 5.0, 0.05)]
[TestCase(5.05, 5.0, 0.05)] // upper range bound
[TestCase(190, 200, 5)]
[TestCase(195, 200, 5)] // lower range bound
[TestCase(196, 200, 5)] // lower range bound + 1
[TestCase(198, 200, 5)]
[TestCase(202, 200, 5)]
[TestCase(205, 200, 5)] // upper range bound
private static readonly DateTime ConstantDateTime = new(2024, 1, 1, 1, 1, 1);

private static IEnumerable<object[]> GetSimpleToleranceData()
{
yield return new object[] { 4.0, 5.0, 0.05 };
yield return new object[] { 4.95, 5.0, 0.05 }; // lower range bound
yield return new object[] { 4.9501, 5.0, 0.05 }; // lower range bound + .01
yield return new object[] { 4.9999, 5.0, 0.05 };
yield return new object[] { 5.0001, 5.0, 0.05 };
yield return new object[] { 5.05, 5.0, 0.05 }; // upper range bound
yield return new object[] { 190, 200, 5 };
yield return new object[] { 195, 200, 5 }; // lower range bound
yield return new object[] { 196, 200, 5 }; // lower range bound + 1
yield return new object[] { 198, 200, 5 };
yield return new object[] { 202, 200, 5 };
yield return new object[] { 205, 200, 5 }; // upper range bound
yield return new object[] { ConstantDateTime, ConstantDateTime.AddSeconds(-1), TimeSpan.FromSeconds(2) };
yield return new object[] { ConstantDateTime, ConstantDateTime.AddSeconds(-2), TimeSpan.FromSeconds(2) };
}

[TestCaseSource(nameof(GetSimpleToleranceData))]
public void SimpleTolerance(object actual, object expected, object tolerance)
{
#pragma warning disable NUnit2042 // Comparison constraint on object
Assert.That(actual, Is.LessThanOrEqualTo(expected).Within(tolerance));
#pragma warning restore NUnit2042 // Comparison constraint on object
}

[TestCase(6.0, 5.0, 0.05)]
[TestCase(210, 200, 5)]
private static IEnumerable<object[]> GetSimpleTolerance_FailureData()
{
yield return new object[] { 6.0, 5.0, 0.05 };
yield return new object[] { 210, 200, 5 };
yield return new object[] { ConstantDateTime, ConstantDateTime.AddSeconds(-2), TimeSpan.FromSeconds(1) };
}

[TestCaseSource(nameof(GetSimpleTolerance_FailureData))]
public void SimpleTolerance_Failure(object actual, object expected, object tolerance)
{
#pragma warning disable NUnit2042 // Comparison constraint on object
Expand All @@ -74,7 +92,7 @@ public void SimpleTolerance_Failure(object actual, object expected, object toler
"Assertion should have failed");
#pragma warning restore NUnit2042 // Comparison constraint on object

Assert.That(ex?.Message, Contains.Substring("Expected: less than or equal to " + expected));
Assert.That(ex?.Message, Contains.Substring("Expected: less than or equal to " + MsgUtils.FormatValue(expected)));
}

[TestCase(4.0, 5.0, 1)]
Expand Down

0 comments on commit 56fa6f4

Please sign in to comment.