【Unity】Unity Test Runner(Test Framework)でEqualityComparerをつかって誤差を考慮して浮動小数点をテストする

Unity Test RunnerでEqualityComparerをつかって浮動小数点をテストする方法をまとめました。

Unity 2019.3.5
Test Framework 1.1.11

基本的な使い方

Unity Test Runnerの基本的な使い方については以下の記事にまとめています。

light11.hatenadiary.com

インストール、セットアップから簡単なテストを書くまでの流れはこちらを参考にしてください。

浮動小数点をテスト?

たとえば以下のように書くと、浮動小数valueexpectedに等しいことをテストできます。

using NUnit.Framework;
using UnityEngine.TestTools.Utils;

public class ExampleEditorTest
{
    [Test]
    public void Test01()
    {
        var value = 1.0f;
        var expected = 1.0f;

        Assert.That(value, Is.EqualTo(expected));
    }
}

この例ではvalueexpectedが等しいのでテストは成功します。
ただしテストが成功するのは二つの値が完全に一致するときだけです。
実際には浮動小数点の計算には誤差が生じます。

light11.hatenadiary.com

そのため、浮動小数点の同一性をテストする際には誤差を考慮する必要があるケースがほとんどです。
この記事では誤差を適切に扱いながら浮動小数点をテストする方法をまとめます。

FloatEqualityComparer

さて、浮動小数点の値について誤差を考慮したテストを行うには以下のようにFloatEqualityComparerクラスを使います。

using NUnit.Framework;
using UnityEngine.TestTools.Utils;

public class ExampleEditorTest
{
    [Test]
    public void Test01()
    {
        var value = 0.00001f;
        var expected = 0f;
        var comparer = FloatEqualityComparer.Instance;

        Assert.That(value, Is.EqualTo(expected).Using(comparer));
    }
}

FloatEqualityComparer.Instanceを使った場合、0.0001までの値が誤差として許容されます。
すなわち上のテストは成功します。

もし誤差の範囲を明示的に指定したい場合にはFloatEqualityComparerのコンストラクタ引数で設定します。

var comparer = new FloatEqualityComparer(0.000001f);

VectorEqualityComparer

Vector3型の同一性テストは以下のようにVector3EqualityComparerを使用することで行います。

using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools.Utils;

public class ExampleEditorTest
{
    [Test]
    public void Test01()
    {
        var value = new Vector3(0.00001f, 0.00001f, 0.00001f);
        var expected = new Vector3(0f, 0f, 0f);
        var comparer = Vector3EqualityComparer.Instance;
        
        Assert.That(value, Is.EqualTo(expected).Using(comparer));
    }
}

上の例はVector3に含まれる3つのfloat値の差がすべて0.0001以内に収まっていた場合のみ成功します。
またFloatEqualityComparerと同様に誤差の範囲を指定することもできます。

var comparer = new Vector3EqualityComparer(0.001f);

なおVector2型用のVector2EqualityComparerVector4型用のVector4EqualityComparerも存在します。

ColorEqualityComparer

Color型の同一性は以下のようにColorEqualityComparerを使ってテストできます。

using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools.Utils;

public class ExampleEditorTest
{
    [Test]
    public void Test01()
    {
        var value = new Color(0f, 0f, 0f, 1.0f);
        var expected = new Color(0.001f, 0.001f, 0.001f, 0.9f);
        var comparer = ColorEqualityComparer.Instance;
        
        Assert.That(value, Is.EqualTo(expected).Using(comparer));
    }
}

上の例はColorに含まれる3つのRGBA値の差がすべて0.01以内に収まっていた場合のみ成功します。
また例のごとく誤差の範囲を指定することもできます。

 var comparer = new ColorEqualityComparer(0.1f);

QuaternionEqualityComparer

Quaternion型の同一性テストは以下のようにQuaternionEqualityComparerを使用することで行います。

using NUnit.Framework;
using UnityEngine;
using UnityEngine.TestTools.Utils;

public class ExampleEditorTest
{
    [Test]
    public void Test01()
    {
        var value = new Quaternion(10f, 0f, 0f, 0f);
        var expected = new Quaternion(1f, 10f, 0f, 0f);
        var comparer = QuaternionEqualityComparer.Instance;

        Assert.That(value, Is.EqualTo(expected).Using(comparer));
    }
}

QuaternionEqualityComparerは、二つの値をQuaternion.Dot()して求めたfloat値を用いて比較します。
上記の例ではこのfloat値が0.00001よりも小さければテストが成功します。

また、例のごとく誤差の範囲を指定することもできます。

 var comparer = new QuaternionEqualityComparer(0.1f);

関連

light11.hatenadiary.com

参考

docs.unity3d.com