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

为何test.check测试自定义index-of时使用小于设定的输入?

问题分析与解决

为什么会出现短输入的失败案例?

test.check 在发现失败案例后,会自动**缩小(shrink)**输入,找到能触发失败的最小可能值。你看到的"0bU"或"240"并不是直接生成的短输入,而是从你设定的100+字符的原始失败输入中缩减而来的最小复现案例,这是test.check的核心特性之一,帮助快速定位问题根源。

代码中的两个关键问题

1. 属性测试的绑定语法错误

你的prop/for-all绑定存在两处问题:

[ s1 (gen-alphanumeric 100 200) begin gen/nat 80 ]
  • gen/nat不接受参数,你想限制begin范围的写法无效;
  • begin可能生成超出s1有效范围的值:当begin +10 > (count s1)时,subs会返回短于10字符的字符串(甚至空字符串),导致索引对比出现不一致。

正确做法是使用依赖生成器,确保begin的取值始终满足begin +10 ≤ (count s1):

(defspec indexof-functionality-test   
  (prop/for-all [s1 (gen-alphanumeric 100 200)
                 begin (gen/bind (gen/return s1) 
                                 (fn [s] (gen/choose 0 (- (count s) 10))))]
    (let [end (+ begin 10)
          s2 (subs s1 begin end)]
      (= (str/index-of s1 s2) (cp-str/indexof s1 s2)))))

2. 自定义indexof函数与标准库行为不一致

当搜索字符串为空时,str/index-of返回0,但你的函数返回nil,这会直接导致测试失败。修正空字符串的处理逻辑:

(defn indexof
  "given two strings, returns the index where sb begins in sa. Nil if not found"
  ([sa sb]
   (indexof sa sb 0))
  ([sa sb i]
   (let [sa-len (count sa)
         sb-len (count sb)]
     (cond
       (zero? sb-len) 0  ; 匹配str/index-of的空字符串行为
       (>= i sa-len) nil
       (> (+ i sb-len) sa-len) nil
       (= (subs sa i (+ i sb-len)) sb) i
       :else (indexof sa sb (inc i))))))

为什么不同电脑上结果不同?

test.check 使用随机种子生成测试用例。失败的那次运行使用了特定种子1676231835751,刚好生成了触发问题的begin值;而另一台电脑的测试用例没有命中这个场景。你可以在另一台电脑上用该种子复现失败:

(prop/run-tests indexof-functionality-test :seed 1676231835751)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 13:05:17