如何在单元测试中比较包含NaN元素的Go切片?

huangapple go评论91阅读模式
英文:

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

问题

我需要在单元测试中比较两个切片,我认为assert包应该可以解决这个问题,但它不能处理NaN值:

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())
}

输出结果为:

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

我理解NaN的特性是它不等于自身,但另一方面,我从函数中得到了预期的结果。

我想知道如何解决这个问题-如何拥有简洁的单元测试断言和清晰的输出?

作为一种替代方案,我可以避免使用assert,并在两个切片的每个元素上调用math.IsNaN,但这在单元测试中看起来会显得冗长。

英文:

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.

答案1

得分: 1

github.com/google/go-cmp/cmp 包通常推荐用于更复杂的比较。cmpopts.EquateNaNs 可以用于轻松比较可能包含 NaN 的数据结构。

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)  // 通过。
    if !cmp.Equal(got, want, cmpopts.EquateNaNs()) {
        t.Errorf("calc: got = %v; want = %v", got, want)
    }

    got = calc(2)   // 失败,有差异。
    if diff := cmp.Diff(want, got, cmpopts.EquateNaNs()); diff != "" {
        t.Errorf("calc: diff (-want +got) = \n%s", diff)
    }
}
英文:

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

huangapple
  • 本文由 发表于 2023年1月17日 21:33:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/75147218.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定