约束与自定义数据类型一起使用

约束与自定义数据类型一起使用

本文介绍了如何将NUnit的EqualTo().Within()约束与自定义数据类型一起使用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I love NUnit's constraint-based API. I often use floating point comparison like this:

double d = foo.SomeComputedProperty;

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

非常可读!

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

However, if I have a custom class whose equality depends on floating point comparison:

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?

推荐答案

以下内容适用于NUnit 3

使用System.Numerics.Complex类作为简单示例,我可以编写测试

Using the System.Numerics.Complex class as a simple example, I can write a test

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

具有此比较功能:

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;
}

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

This gives you the Comparer that was mentioned in juharr's comment, and achieves the basics of what you asked. It doesn't let me parameterise the tolerance, but it's close.

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

In order to complete the requirement, I would instead want to write the test as

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

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

but, as noted in the question, it's not as easy. It requires a new constraint extension method

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

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

and then write the custom constraint along these lines:

public class ComplexEqualConstraint
    : EqualConstraint
{
    public ComplexEqualConstraint(EqualConstraint that)
        : base(that)
    {
    }

    public override ConstraintResult ApplyTo<TActual>(TActual actual)
    {
        bool success = false;
        if (actual is Complex z1)
        {
            Complex z2 = (Complex)this.Arguments[0];
            success = Math.Abs(z1.Real - z1.Real) < Tolerance.Real &&
                      Math.Abs(z1.Imaginary - z2.Imaginary) < Tolerance.Imaginary;
        }
        return new ConstraintResult(this, actual, success);
    }

    public new Complex Tolerance
    {
        get;
        set;
    } = Complex.Zero;
}

这篇关于如何将NUnit的EqualTo().Within()约束与自定义数据类型一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-14 10:34