如何使用NUnit的EqualTo()。在()约束中使用自定义数据类型?

时间:2015-07-31 18:02:36

标签: c# floating-point nunit assertions

我喜欢NUnit的基于约束的API。我经常使用这样的浮点比较:

double d = foo.SomeComputedProperty;

Assert.That(d, Is.EqualTo(42.0).Within(0.001));

非常易读!

但是,如果我有一个自定义类,其相等性取决于浮点比较:

class Coord
{
  Coord(double radius, double radians)
  {
    this.Radius = radius;
    this.Radians = radians;
  }

  double Radius { get; }
  double Radians { get; }

  public override bool Equals(Object obj)
  {
    Coord c = obj as Coord;
    if (obj == null || c == null) return false;

    return c.Radians == this.Radians && c.Radius == this.Radius;
  }
}

我想写这样的测试:

Coord reference = new Coord(1.0, 3.14);

// test another Coord for near-equality to a reference Coord:
Assert.That(testCoord, Is.EqualTo(reference).Within(0.001));

是否可以像这样使用NUnit?

2 个答案:

答案 0 :(得分:0)

以下内容适用于NUnit 3

使用TRUE类作为简单示例,我可以编写测试

System.Numerics.Complex

具有此比较功能:

Assert.That(z1, Is.EqualTo(z2).Using<Complex>(NearlyEqual));

这为您提供了juharr的评论中提到的比较器,并实现了您所要求的基础知识。它不允许我对公差进行参数设置,但是已经很接近了。

为了完成要求,我想将测试写为

internal static bool NearlyEqual(Complex z1, Complex z2)
{
    return Math.Abs(z1.Real - z2.Real) < 1e-10 &&
           Math.Abs(z1.Imaginary - z2.Imaginary) < 1e-10;
}

但是,正如问题中指出的那样,这并不容易。它需要一种新的约束扩展方法

Assert.That(z1, Is.EqualTo(z2).Within(new Complex(1e-10, 1e-10)));

,然后按照以下方式编写自定义约束:

public static class ComplexTestExtensions
{
    public static ComplexEqualConstraint WithinZ(this EqualConstraint constraint, Complex tolerance)
    {
        return new ComplexEqualConstraint(constraint) { Tolerance = tolerance };
    }
}

答案 1 :(得分:0)

基于 ClickRick 的回答:

如果您需要与 NUnit 2.6(例如 Unity 的测试框架基于)一起使用的东西:

public static class ColorTestExtensions
{
    public static EqualConstraint WithinManhattanDistance(this EqualConstraint constraint, float tolerance)
    {
        return new ColorEqualConstraint((Color) constraint.Arguments[0]).Within(tolerance);
    }

    private class ColorEqualConstraint : EqualConstraint
    {
        public ColorEqualConstraint(Color expected) : base(expected) {}

        public override ConstraintResult ApplyTo(object actual)
        {
            if (!(actual is Color c1)) return new ConstraintResult(this, actual, false);

            var c2 = (Color) Arguments[0];
            var tolerance = (float) Tolerance.Value;
            var success = ColorExtensions.ManhattanDistance(c1, c2) < tolerance;
            return new ConstraintResult(this, actual, success);
        }
    }
}

这让你可以写:

Color color = GetPixel(0,0);
Assert.That(color, Is.EqualTo(Color.red).WithinManhattanDistance(0.1f);