# 测试 Deft 内置测试框架:`defsuite` 对测试分组,`deftest` 定义单个用例, `assert/` 命名空间检查结果。`deft test` 命令运行匹配 `test_*.dft` 的 `.dft` 文件或显式指定的文件。 ## 你好,测试
defsuite "arithmetic" {
    deftest "addition" {
        [assert/eq (1 + 2) 3]
    }

    deftest "multiplication" {
        [assert/eq (2 * 3) 6]
    }
}
使用以下命令运行: ``` deft test test_math.dft ```` ## 断言 每个断言都是 `assert/` 命名空间下独立的标准库函数 —— 没有类型关键字, 只有以斜杠分隔的名称:
[assert/eq $a $b]                 # equality
[assert/ne $a $b]                 # inequality
[assert/truthy $x]                # truthy
[assert/falsy $x]                 # falsy
[assert/gt $a $b]                 # greater than
[assert/gte $a $b]                # greater than or equal
[assert/lt $a $b]                 # less than
[assert/lte $a $b]                # less than or equal
[assert/nil? $x]                  # nil check
[assert/not-nil? $x]              # not-nil check
[assert/empty? $xs]               # empty collection
[assert/not-empty? $xs]           # non-empty collection
[assert/contains? $xs $v]         # collection contains value
[assert/type $x "number"]         # type check
[assert/length $xs $n]            # length check
对于本身以 `?` 结尾的谓词,直接使用对应的 `assert/` 形式:
[assert/nil? $result]
[assert/truthy [empty? $xs]]
### 自定义断言消息 可选最后一个参数是失败消息:
[assert/eq $status 200 "expected HTTP 200"]
## 测试发现 不带参数的 `deft test` 会在当前目录下查找 `test/test_*.dft`。显式传入 路径可运行子集: ``` deft test # all tests under ./test/ deft test test_sqlite.dft # one file deft test test/test_sqlite.dft test/test_refs.dft # several ```` ## 编写优秀的测试 ### 对被测系统使用类型标注
def add {|a^number b^number| ($a + $b) }

defsuite "add" {
    deftest "positive" { [assert/eq [add 1 2] 3] }
    deftest "negative" { [assert/eq [add -1 -2] -3] }
    deftest "zero"     { [assert/eq [add 0 0] 0] }
}
### 验证结果,而不只是成功
defsuite "json/parse" {
    deftest "valid" {
        set r [json/parse "{\"a\":1}"]
        [assert/eq $r~a 1]
    }

    deftest "invalid" {
        set r [json/parse "not json"]
        [assert/truthy [err? $r]]
    }
}
### 测试抛出异常的代码 将调用包裹在 `try` 中,并断言 catch 分支已执行:
defsuite "divide" {
    deftest "by zero throws" {
        set caught false
        try {
            [divide 1 0]
        } catch _e {
            set caught true
        }
        [assert/truthy $caught]
    }
}
### 高阶函数测试
defsuite "map" {
    deftest "applies f" {
        set result @{ 1 2 3 } |> map { $it * 2 } |> collect
        [assert/eq $result @{ 2 4 6 }]
    }

    deftest "lazy on infinite" {
        set result [range 0 1000] |> filter even? |> take 3 |> collect
        [assert/eq $result @{ 0 2 4 }]
    }
}
### 管道测试
defsuite "pipeline" {
    deftest "chain" {
        set result @{ 1 2 3 4 }
            |> map { $it * $it }
            |> filter { $it > 4 }
            |> collect
        [assert/eq $result @{ 9 16 }]
    }
}
### 用户自定义类型测试
deftype Point %{ :x %{:type :number} :y %{:type :number} }

defsuite "Point" {
    deftest "construction" {
        set p %Point{ :x 3 :y 4 }
        [assert/eq $p~x 3]
        [assert/eq $p~y 4]
    }
}
### 函数值测试 函数是一等公民;断言其返回值:
defsuite "factorial" {
    def factorial {|n|
        if ($n <= 1) { 1 } { ($n * [factorial ($n - 1)]) }
    }

    deftest "base case" { [assert/eq [factorial 0] 1] }
    deftest "recursive" { [assert/eq [factorial 5] 120] }
}
## 基准测试 `defbench` 声明一个基准测试用例。使用 `deft test --bench` 运行:
defsuite "fib perf" {
    defbench "fib 20" {
        [fib 20]
    }
}
运行器会报告每次迭代的墙钟时间。用它来发现热路径中的性能退化。 ## 最佳实践 1. 每个测试套件聚焦一个概念。 按测试所针对的函数或类型分组,而不是 按输出形态分组。 2. 测试名称应像规格说明。 用 `"add positive numbers"`,而不是 `"test1"`。 3. 不要在测试之间共享可变状态。 每个 `deftest` 都应构造自己的 夹具(fixture)。 4. 优先使用纯断言,而非 `echo` 检查。 断言可由机器检查;打印输出 则不能。 5. 测试失败模式,而不仅是正常路径。 将调用包裹在 `try` 中,以验证 错误行为。 ## CI 集成 典型的 GitHub Actions 步骤: ```yaml - name: Run tests run: | zig build deft -Doptimize=ReleaseFast ./zig-out/bin/deft test ```` 对于 FFI 测试: ```yaml - name: Build with FFI run: zig build deft -Dffi=true -Doptimize=ReleaseFast - name: Run FFI tests run: ./zig-out/bin/deft test test/test_ffi.dft ```` ## 快速参考 | 形式 | 用途 | |---|---| | `defsuite "name" { ... }` | 对测试分组 | | `deftest "name" { ... }` | 单个用例 | | `defbench "name" { ... }` | 基准测试用例 | | `[assert/eq actual expected]` | 断言 | | `deft test [files...]` | 运行测试 | | `deft test --bench` | 运行基准测试 |