You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

解决Go单元测试中含NaN的切片断言问题

在使用testify/assert包断言包含NaN的float64切片时,由于NaN不等于自身的特性,会出现预期和实际值看起来一致但断言失败的情况:

import (
    "math"
    "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

解决方案:自定义复用的断言函数

不用放弃testify的简洁性,你可以封装一个专门处理float64切片(含NaN)的断言函数,既避免冗长的逐元素检查,又保留清晰的错误输出:

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

// assertFloat64SliceEqual 断言两个float64切片相等,处理NaN的特殊情况
func assertFloat64SliceEqual(t assert.TestingT, expected, actual []float64, msgAndArgs ...interface{}) bool {
    // 先检查长度是否一致,不一致直接用原Equal输出差异
    if len(expected) != len(actual) {
        return assert.Equal(t, expected, actual, msgAndArgs...)
    }
    // 逐元素检查,NaN和NaN视为相等
    for i := range expected {
        expVal := expected[i]
        actVal := actual[i]
        if math.IsNaN(expVal) && math.IsNaN(actVal) {
            continue
        }
        if expVal != actVal {
            // 元素不相等时,用原Equal输出完整切片差异
            return assert.Equal(t, expected, actual, msgAndArgs...)
        }
    }
    return true
}

func TestCallMe(t *testing.T) {
    // 测试代码依然简洁
    assertFloat64SliceEqual(t, []float64{math.NaN()}, CallMe())
}

优势说明

  • 测试代码保持一行的简洁性,无需在测试函数中写循环逻辑
  • 当断言失败时,依然会输出testify风格的清晰差异对比,便于定位问题
  • 自定义函数可在所有需要检查含NaN的float64切片的测试中复用,减少重复代码

内容的提问来源于stack exchange,提问作者egor10_4

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 10:10:33