凹语言如何做单元测试?

在凹语言中,以 test_xxx.waxxx_test.wa 形式命名的文件对应测试代码,测试代码可以单文件执行也可以放在工程文件中执行。

1. 斐波那契数列

斐波那契数数列对应一个兔子繁殖的题目,对应的数学定义为:F(0)=1, F(1)=1, F(n)=F(n-1)+F(n-2)。对应的数列为:1、1、2、3、5、8、13、21、34......。我们现在以凹语言构造这个程序。

创建 fib.wa 文件(不是测试文件),构造一个凹语言斐波那契数列的例子:

wa 复制代码
func main {
    for i := range 10 {
        println(Fibonacci(i))
    }
}

// 1, 1, 2, 3, 5, ...
func Fibonacci(i: int) => int {
    if i >= 2 {
        return Fibonacci(i-1) + Fibonacci(i-2)
    }
    return 1
}

执行结果如下:

arduino 复制代码
$ wa run fib.wa
1
1
2
3
5
8
13
21
34
55

2. 测试斐波那契数列

为了方便演示,我们可以构造等价的 test_fib.wa 测试文件:

wa 复制代码
func Example {
    for i := range 10 {
        println(Fibonacci(i))
    }

    // Output:
    // 1
    // 1
    // 2
    // 3
    // 5
    // 8
    // 13
    // 21
    // 34
    // 55
}

// 1, 1, 2, 3, 5, ...
func Fibonacci(i: int) => int {
    if i >= 2 {
        return Fibonacci(i-1) + Fibonacci(i-2)
    }
    return 1
}

其中Example对应main函数,其中// Output:标注的是期望的结果。然后通过wa test命令以测试的方式运行:

shell 复制代码
$ wa test test_fib.wa
ok   __main__ 97ms

表明测试通过。

3. 构造一个失败的测试

斐波那契数列的输入参数默认都是非负整数,因此如果出现输入负数等无效输入我们希望返回0。构造测试例子:

wa 复制代码
func ExampleFibonacci_invalid {
    println(Fibonacci(-1))

    // Output:
    // 0
}

重新执行测试:

ini 复制代码
$ wa test test_fib.wa
---- __main__.ExampleFibonacci_invalid
    expect = "0", got = "1"
FAIL __main__ 90ms

测试失败。这时候如果通过-run=Example参数只运行Example函数依然是成功的:

ini 复制代码
$ wa test -run=Example test_fib.wa
ok   __main__ 107ms

4. 修复失败的测试

改进函数对负数的输出检查:

wa 复制代码
func Fibonacci(i: int) => int {
    if i < 0 {
        return 0
    }
    if i >= 2 {
        return Fibonacci(i-1) + Fibonacci(i-2)
    }
    return 1
}

重新运行测试:

shell 复制代码
$ wa test test_fib.wa
ok   __main__ 125ms

现在成功了。

5. TestXXX测试函数

之前都是通过Example开头的示例测试,通过验证输出的结果来判断测试代码是否正常。这种ExampleXXX示例测试很像传统的集成测试,每个测试函数类型独立运行的main函数,并且两次运行之间没有上下文的干扰。

除了测试打印输出,还可以在TestXXX测试函数中通过assert函数进行测试。assert函数是测试环境的内置函数,函数签名如下:

wa 复制代码
func assert(ok: bool)
func assert(ok: bool, errMessage: string)

第一个参数是必选的测试条件,如果为false则测试失败。第二个是可选的测试失败时输出的信息。

先构造一个失败的测试:

wa 复制代码
func TestFibonacci {
    assert(Fibonacci(-1) == 1, "expect 0")
}

运行的结果如下:

lua 复制代码
$ wa test test_fib.wa
    assert failed: expect 0 (test_fib.wa:45:8)
    module "unittest://test_fib.wa" closed with exit_code(1)
exit status 1

失败的信息中包含了失败的原因和对应的位置。修正后的测试函数如下:

wa 复制代码
func TestFibonacci {
    // assert(Fibonacci(-1) == 1, "expect 0")

    assert(Fibonacci(0) == 1)
    assert(Fibonacci(1) == 1)
    assert(Fibonacci(2) == 2)
    assert(Fibonacci(3) == 3)
    assert(Fibonacci(4) == 5)
}

6. 异常的测试

之前我们将负数的输出返回了0,现在我们希望在输入错误是抛出异常,代码如下:

wa 复制代码
func FibonacciV2(i: int) => int {
    if i < 0 {
        panic("invalid")
    }
    return Fibonacci(i)
}

要测试异常,必须通过Example示例测试:

wa 复制代码
func ExampleFibonacciV2 {
    FibonacciV2(-1)

    // Output(panic):
    // invalid
}

通过// Output(panic):表注期望输出的异常输出信息。如果有异常并且匹配输出结果则测试通过。

7. 工程中的测试

对于完整的凹语言工程(含有wa.mod文件),可以将函数的实现和测试代码分别存放便于管理。

8. 小结

凹语言测试框架麻雀虽小五脏俱全,提供了单元测试、集成测试、异常测试,并且支持执行指定的测试函数。

相关推荐
数据智能老司机2 小时前
精通ROS 2机器人编程——ROS 2入门
机器人·ai编程·编程语言
大虫小呓5 小时前
Python So Easy 大虫小呓三部曲 - 进阶篇
python·编程语言
JohnYan2 天前
一句话编程语言
编程语言
数据智能老司机3 天前
使用 Python 进行并行与高性能编程——构建多线程程序
python·性能优化·编程语言
dudly3 天前
Python 列表内存存储本质:存储差异原因与优化建议
开发语言·数据结构·python·编程语言·内存分析
猪哥帅过吴彦祖4 天前
什么是内存对齐?
编程语言
数据智能老司机4 天前
使用 Python 进行并行与高性能编程——并行编程导论
python·性能优化·编程语言
ansurfen6 天前
自制编程语言 Hulo —— 模块系统跳票,但Batch和Powershell对接、解释器初步
go·编程语言