Home > OS >  How to compare Go slices with NaN elements in unit tests?
How to compare Go slices with NaN elements in unit tests?

Time:01-24

I need to compare 2 slices in unit tests and I thought assert package should solve this but it doesn't work with NaNs:

import (
    "github.com/stretchr/testify/assert"
)

func CallMe() []float64 {
    return []float64{math.NaN()}
}

func TestCallMe(t *testing.T) {
    assert.Equal(t, []float64{math.NaN()}, CallMe())
}

The output is:

            Error:          Not equal: 
                            expected: []float64{NaN}
                            actual  : []float64{NaN}
                            
                            Diff:
            Test:           TestCallMe

I understand that it's a property of NaN to be not equal to itself but on the other hand I receive the expected result from the function.

I wonder how to solve that - to have a concise unit test assertion and a clear output?

As an alternative I can avoid using assert and call math.IsNaN on every element of both slices but that will look extra verbose in unit tests.

CodePudding user response:

The github.com/google/go-cmp/cmp package is typically recommended for more complex comparisons. cmpopts.EquateNaNs can be used to easily compare data structures which may contain NaNs.

package calc_test

import (
    "math"
    "testing"

    "github.com/google/go-cmp/cmp"
    "github.com/google/go-cmp/cmp/cmpopts"
)

func calc(n float64) []float64 {
    return []float64{n, math.NaN()}
}

func TestCalc(t *testing.T) {
    want := []float64{1, math.NaN()}

    got := calc(1)  // PASS.
    if !cmp.Equal(got, want, cmpopts.EquateNaNs()) {
        t.Errorf("calc: got = %v; want = %v", got, want)
    }

    got = calc(2)   // FAIL with differences.
    if diff := cmp.Diff(want, got, cmpopts.EquateNaNs()); diff != "" {
        t.Errorf("calc: diff (-want  got) = \n%s", diff)
    }
}
  • Related