Skip to content

Commit 161d2b9

Browse files
committed
zz
1 parent c8fc00b commit 161d2b9

File tree

2 files changed

+232
-0
lines changed

2 files changed

+232
-0
lines changed

docs/smalltalk/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ title: 碎碎念
88

99
#
1010

11+
- 2025-07-30: [凹语言测试框架](st0084.md)
1112
- 2025-07-20: [凹语言开源3周年](st0083.md)
1213
- 2025-07-16: [凹语言控制LCD1602液晶显示屏](st0082.md)
1314
- 2025-06-18: [凹语言亮相第三届软件创新发展大会](st0081.md)

docs/smalltalk/st0084.md

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
# 凹语言测试框架
2+
3+
- 时间:2025-07-30
4+
- 撰稿:凹语言开发组
5+
- 转载请注明原文链接:[https://wa-lang.org/smalltalk/st0084.html](https://wa-lang.org/smalltalk/st0084.html)
6+
7+
---
8+
9+
在凹语言中,以 `test_xxx.wa``xxx_test.wa` 形式名面的文件对应测试代码,测试代码可以单文件执行也可以放在工程文件中执行。
10+
11+
## 1. 斐波那契数列
12+
13+
斐波那契数数列对应一个兔子繁殖的题目,对应的数学定义为:`F(0)=1, F(1)=1, F(n)=F(n-1)+F(n-2)`。对应的数列为:1、1、2、3、5、8、13、21、34……。我们现在以凹语言构造这个程序。
14+
15+
创建 `fib.wa` 文件(不是测试文件),构造一个凹语言斐波那契数列的例子:
16+
17+
```wa
18+
func main {
19+
for i := range 10 {
20+
println(Fibonacci(i))
21+
}
22+
}
23+
24+
// 1, 1, 2, 3, 5, ...
25+
func Fibonacci(i: int) => int {
26+
if i >= 2 {
27+
return Fibonacci(i-1) + Fibonacci(i-2)
28+
}
29+
return 1
30+
}
31+
```
32+
33+
执行结果如下:
34+
35+
```
36+
$ wa run fib.wa
37+
1
38+
1
39+
2
40+
3
41+
5
42+
8
43+
13
44+
21
45+
34
46+
55
47+
```
48+
49+
## 2. 测试斐波那契数列
50+
51+
为了方便演示,我们可以构造等价的 `test_fib.wa` 测试文件:
52+
53+
```wa
54+
func Example {
55+
for i := range 10 {
56+
println(Fibonacci(i))
57+
}
58+
59+
// Output:
60+
// 1
61+
// 1
62+
// 2
63+
// 3
64+
// 5
65+
// 8
66+
// 13
67+
// 21
68+
// 34
69+
// 55
70+
}
71+
72+
// 1, 1, 2, 3, 5, ...
73+
func Fibonacci(i: int) => int {
74+
if i >= 2 {
75+
return Fibonacci(i-1) + Fibonacci(i-2)
76+
}
77+
return 1
78+
}
79+
```
80+
81+
其中`Example`对应`main`函数,其中`// Output:`标注的是期望的结果。然后通过`wa test`命令以测试的方式运行:
82+
83+
```
84+
$ wa test test_fib.wa
85+
ok __main__ 97ms
86+
```
87+
88+
表明测试通过。
89+
90+
## 3. 构造一个失败的测试
91+
92+
斐波那契数列的输入参数默认都是非负整数,因此如果出现输入负数等无效输入我们希望返回0。构造测试例子:
93+
94+
```wa
95+
func ExampleFibonacci_invalid {
96+
println(Fibonacci(-1))
97+
println(Fibonacci(-2))
98+
println(Fibonacci(-3))
99+
100+
// Output:
101+
// 0
102+
// 0
103+
// 0
104+
}
105+
```
106+
107+
重新执行测试:
108+
109+
```
110+
$ wa test test_fib.wa
111+
---- __main__.ExampleFibonacci_invalid
112+
expect = "0\n0\n0", got = "1\n1\n1"
113+
FAIL __main__ 90ms
114+
```
115+
116+
测试失败。这时候如果通过`-run=Example`参数只运行`Example`函数依然是成功的:
117+
118+
```
119+
$ wa test -run=Example test_fib.wa
120+
ok __main__ 107ms
121+
```
122+
123+
## 4. 修复失败的测试
124+
125+
改进函数对负数的输出检查:
126+
127+
```wa
128+
func Fibonacci(i: int) => int {
129+
if i < 0 {
130+
return 0
131+
}
132+
if i >= 2 {
133+
return Fibonacci(i-1) + Fibonacci(i-2)
134+
}
135+
return 1
136+
}
137+
```
138+
139+
重新运行测试:
140+
141+
```
142+
$ wa test test_fib.wa
143+
ok __main__ 125ms
144+
```
145+
146+
现在成功了。
147+
148+
## 5. `TestXXX`测试函数
149+
150+
之前都是通过`Example`开头的示例测试,通过验证输出的结果来判断测试代码是否正常。这种`ExampleXXX`示例测试很像传统的集成测试,每个测试函数类型独立运行的`main`函数,并且两次运行之间没有上下文的干扰。
151+
152+
除了测试打印输出,还可以在`TestXXX`测试函数中通过`assert`函数进行测试。`assert`函数是测试环境的内置函数,函数签名如下:
153+
154+
```wa
155+
func assert(ok: bool)
156+
func assert(ok: bool, errMessage: string)
157+
```
158+
159+
第一个参数是必选的测试条件,如果为`false`则测试失败。第二个是可选的测试失败时输出的信息。
160+
161+
先构造一个失败的测试:
162+
163+
```wa
164+
func TestFibonacci {
165+
assert(Fibonacci(-1) == 1, "expect 0")
166+
}
167+
```
168+
169+
运行的结果如下:
170+
171+
```
172+
$ wa test test_fib.wa
173+
assert failed: expect 0 (test_fib.wa:45:8)
174+
module "unittest://test_fib.wa" closed with exit_code(1)
175+
exit status 1
176+
```
177+
178+
失败的信息中包含了失败的原因和对应的位置。修正后的测试函数如下:
179+
180+
```wa
181+
func TestFibonacci {
182+
// assert(Fibonacci(-1) == 1, "expect 0")
183+
184+
assert(Fibonacci(0) == 1)
185+
assert(Fibonacci(1) == 1)
186+
assert(Fibonacci(2) == 2)
187+
assert(Fibonacci(3) == 3)
188+
assert(Fibonacci(4) == 5)
189+
}
190+
```
191+
192+
## 6. 异常的测试
193+
194+
之前我们将负数的输出返回了0,现在我们希望在输入错误是抛出异常,代码如下:
195+
196+
```wa
197+
func Fibonacci(i: int) => int {
198+
if i < 0 {
199+
panic("invalid")
200+
}
201+
if i >= 2 {
202+
return Fibonacci(i-1) + Fibonacci(i-2)
203+
}
204+
return 1
205+
}
206+
```
207+
208+
要测试异常,必须通过`Example`示例测试:
209+
210+
```wa
211+
func FibonacciPanic(i: int) => int {
212+
if i < 0 {
213+
panic("invalid")
214+
}
215+
return Fibonacci(i)
216+
}
217+
218+
func ExampleFibonacci {
219+
FibonacciPanic(-1)
220+
221+
// Output(panic):
222+
// invalid
223+
}
224+
```
225+
226+
通过`// Output(panic):`表注期望输出的异常输出信息。如果有异常并且匹配输出结果则测试通过。
227+
228+
## 7. 小结
229+
230+
凹语言测试框架麻雀虽小五脏俱全,提供了单元测试、集成测试、异常测试,并且支持执行指定的测试函数。
231+

0 commit comments

Comments
 (0)