.above .below .least .most .within .closeTo 数值比较全览
六个比较断言
| 写法 | 语义 | 参数 | ||
|---|---|---|---|---|
.above(n) | 大于 n(>n) | 数值或日期 | ||
.below(n) | 小于 n(<n) | 数值或日期 | ||
.least(n) | 大于等于 n(≥n) | 数值或日期 | ||
.most(n) | 小于等于 n(≤n) | 数值或日期 | ||
.within(min, max) | 区间包含([min, max]) | 数值或日期 | ||
.closeTo(expected, delta) | 近似相等 \ | actual - expected\ | ≤ delta | 数值 |
大于 / 小于:above / below
expect(42).to.be.above(40); // ✅ 42 > 40
expect(42).to.be.above(42); // ❌ 42 不大于 42
expect(42).to.be.below(50); // ✅ 42 < 50
expect(42).to.be.below(42); // ❌ 42 不小于 42
大于等于 / 小于等于:least / most
expect(42).to.be.at.least(42); // ✅ 42 ≥ 42
expect(42).to.be.at.least(40); // ✅ 42 ≥ 40
expect(42).to.be.at.most(42); // ✅ 42 ≤ 42
expect(42).to.be.at.most(50); // ✅ 42 ≤ 50
注意 .least 前面习惯加 .at:expect(x).to.be.at.least(n)。.at 是一个语言链,只是让句子通顺。不加也可以:expect(x).to.be.least(n)。
区间包含:within
expect(42).to.be.within(40, 50); // ✅ 42 ∈ [40, 50]
expect(42).to.be.within(42, 42); // ✅ 边界值也通过
expect(42).to.be.within(50, 40); // ⚠️ min > max 时 Chai 会交换它们,仍然通过
.within 的区间是闭区间——两个边界值都包含在内。
近似相等:closeTo
解决浮点精度问题的利器:
// 经典浮点问题
expect(0.1 + 0.2).to.equal(0.3);
// AssertionError: expected 0.30000000000000004 to equal 0.3
// 用 closeTo 指定允许误差
expect(0.1 + 0.2).to.be.closeTo(0.3, 0.0001); // ✅
delta 参数表示允许的绝对误差:|actual - expected| ≤ delta。
expect(3.14159).to.be.closeTo(3.14, 0.01); // ✅ |3.14159 - 3.14| = 0.00159 ≤ 0.01
expect(3.14159).to.be.closeTo(3.14, 0.001); // ❌ 0.00159 > 0.001
日期也能比较
.above / .below / .least / .most / .within 都支持 Date 对象:
const today = new Date();
const tomorrow = new Date(today.getTime() + 86400000);
expect(tomorrow).to.be.above(today);
expect(today).to.be.at.most(tomorrow);
expect(new Date('2024-01-01')).to.be.within(
new Date('2023-12-31'),
new Date('2024-01-02')
);
Chai 内部调用 .getTime() 比较时间戳,所以也可以直接比较时间戳数值:
expect(tomorrow.getTime()).to.be.above(today.getTime());
assert 风格对应
assert.isAbove(42, 40);
assert.isBelow(42, 50);
assert.isAtLeast(42, 42);
assert.isAtMost(42, 42);
assert.isWithin(42, 40, 50);
assert.isCloseTo(0.1 + 0.2, 0.3, 0.0001);
assert 风格的 .isWithin 参数顺序不同:assert.isWithin(value, min, max)——第一个是实际值,后面是区间。而 expect 风格是 expect(value).to.be.within(min, max)——实际值在 expect 里。
常见陷阱
.within 边界交换
如果你写了 expect(x).to.be.within(50, 40)(min > max),Chai 会自动交换成 (40, 50),不会报错。这在边界是变量时可能掩盖 bug——最好保证 min ≤ max。
浮点精度没处理
测试中涉及乘除运算时,随时可能遇到精度问题。养成习惯:涉及小数运算的比较,先用 .closeTo 而不是 .equal。
日期比较的时区问题
比较日期时确保两端使用同一时区的 Date 对象。如果一端用 UTC 一端用本地时区,可能出现意外结果。