consistency 教程

本页面向贡献者:介绍如何运行跨包一致性测试,以及在向 immut 和 mutable 同时添加某个运算时如何添加测试。其中的道理见 consistency 设计。

快速上手

在仓库根目录下:

moon test -p consistency

所有测试都在默认目标上运行;该包没有目标专用代码。

日常任务

添加一致性测试

在两个包中构造相同的输入,应用该运算,再比较共同的观察结果。这类测试的形式如下,就像它出现在 src/consistency/core_wbtest.mbt 中那样:

///|
test "anti_trace stays aligned" {
  let imm = @immut.Matrix::from_2d_array([[1, 2], [3, 4]])
  let mut_m = @mutable.Matrix::from_2d_array([[1, 2], [3, 4]])
  inspect(
    imm.anti_trace().unwrap(),
    content=mut_m.anti_trace().unwrap().to_string(),
  )
}

以性质的形式添加定律

使用 quick_check_fn 配合由小整数组成的元组,返回一个 Bool,在两个包中比较定律两边。使用整数可以保持比较精确。

同样的思路也适用于你自己的代码。下面这个随手册一起编译的检查,在一个乘积上比较两个包:

///|
test "products agree across packages" {
  let rows = [[1, -2], [3, 4]]
  let i = @immut.Matrix::from_2d_array(rows)
  let m = @mutable.Matrix::from_2d_array(rows)
  debug_inspect((i * i).to_array() == (m * m).to_array(), content="true")
}

进一步了解

当某个运算在两个包之间有意不同时,请添加一个说明该差异的测试,并在两个 API 页面中注明。

常见陷阱

  • 用 == 比较 Double 结果。 各内核的求和顺序不同;一致性测试请保持使用整数。
  • 跨元素类型比较 to_string。 当打印形式可能只在格式上不同时,请使用 to_array。

后续步骤