凹语言如何做单元测试?

在凹语言中,以 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. 小结

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

相关推荐
liulilittle4 天前
UNIX/macOS路由表查询原理与实现
服务器·开发语言·c++·macos·unix·编程语言
liulilittle4 天前
HTTP简易客户端实现
开发语言·网络·c++·网络协议·http·编程语言
liulilittle5 天前
Unix/Linux 平台通过 IP 地址获取接口名的 C++ 实现
linux·开发语言·c++·tcp/ip·unix·编程语言
hqyjzsb5 天前
2025职场进阶:B端产品经理必备的计算机专业技能精要
大数据·开发语言·人工智能·产品经理·编程语言·caie
科技树支点5 天前
无GC的Java创新设计思路:作用域引用式自动内存管理
java·python·go·web·编程语言·编译器
大熊猫侯佩9 天前
韦爵爷闯荡 Swift 6 江湖:单例秘籍新解(上)
swift·编程语言·apple
一支鱼9 天前
前端使用次数最多的工具封装
前端·typescript·编程语言
Jooolin10 天前
【C++】C++11都有什么新特性?
c++·ai编程·编程语言
秋难降12 天前
深入解析快速排序:原理、波动根源与优化之道
算法·排序算法·编程语言
咕白m62514 天前
Java 开发:用 Spire.PDF 高效压缩 PDF 文件
java·编程语言