1.6 测试
原文链接: https://rust-unofficial.github.io/too-many-lists/first-test.html
好了,push 和 pop 都写好了,现在可以真正测试我们的栈了!Rust 和 cargo 把测试当作一等公民,所以这会超级简单。我们只需写一个函数,并用 #[test] 标注。
在 Rust 社区里,我们通常把测试放在被测代码旁边。不过一般会为测试新建一个命名空间,避免与「真实」代码冲突。就像我们用 mod 指定 first.rs 应包含在 lib.rs 里一样,也可以用 mod 基本上内联创建一个全新文件:
1
2
3
4
5
6
7
8
| // 在 first.rs 中
mod test {
#[test]
fn basics() {
// TODO
}
}
|
用 cargo test 运行。
1
2
3
4
5
6
7
8
9
10
| > cargo test
Compiling lists v0.1.0 (/Users/ADesires/dev/temp/lists)
Finished dev [unoptimized + debuginfo] target(s) in 1.00s
Running /Users/ADesires/dev/lists/target/debug/deps/lists-86544f1d97438f1f
running 1 test
test first::test::basics ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
; 0 filtered out
|
耶,啥也不干的测试通过了!让它干点事。用 assert_eq! 宏。这不是什么特殊的测试魔法。它只是比较你给它的两个东西,不匹配就让程序 panic。没错,向测试框架表示失败的方式就是抓狂!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| mod test {
#[test]
fn basics() {
let mut list = List::new();
// 检查空链表行为正确
assert_eq!(list.pop(), None);
// 填充链表
list.push(1);
list.push(2);
list.push(3);
// 检查正常弹出
assert_eq!(list.pop(), Some(3));
assert_eq!(list.pop(), Some(2));
// 再推入一些,确保没有损坏
list.push(4);
list.push(5);
// 检查正常弹出
assert_eq!(list.pop(), Some(5));
assert_eq!(list.pop(), Some(4));
// 检查耗尽
assert_eq!(list.pop(), Some(1));
assert_eq!(list.pop(), None);
}
}
|
1
2
3
4
5
6
7
| > cargo test
error[E0433]: failed to resolve: use of undeclared type or module `List`
--> src/first.rs:43:24
|
43 | let mut list = List::new();
| ^^^^ use of undeclared type or module `List`
|
哎呀!因为我们新建了模块,需要显式引入 List 才能用。
1
2
3
4
| mod test {
use super::List;
// 其余相同
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| > cargo test
warning: unused import: `super::List`
--> src/first.rs:45:9
|
45 | use super::List;
| ^^^^^^^^^^^
|
= note: #[warn(unused_imports)] on by default
Finished dev [unoptimized + debuginfo] target(s) in 0.43s
Running /Users/ADesires/dev/lists/target/debug/deps/lists-86544f1d97438f1f
running 1 test
test first::test::basics ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
; 0 filtered out
|
耶!
那个警告怎么回事……?我们明明在测试里用了 List!
……但只在测试时!为了安抚编译器(也对使用者友好),应标明整个 test 模块只在运行测试时编译。
1
2
3
4
5
| #[cfg(test)]
mod test {
use super::List;
// 其余相同
}
|
测试部分就这些了!