测试的种类
我特别要给你们看一下如何进行测试.虽然代码很简单,但是也有一些需要验证的工作.主要有两大类测试,一个是从内向外的,我会写一些测试验证程序的内部功能. 另一个是从外向内的,我会写测试模仿用户使用程序.
前面一种称为单元测试(unit tests), 之后我们再讨论这种测试.
这个程序我想主要进行后一种测试,它被称为集成测试或者整合测试(integration test), 它把程序当成一个整体进行测试.
通常的做法是, 为集成测试创建一个目录, 这可以使代码组织的干净, 还能帮助编译器在不进行测试时直接忽略掉这个文件夹.
准备集成测试
使用命令创建文件夹
1 | $ mkdir tests |
我准备像普通用户运行程序一样测试hello
程序, 所以先创建一个tests/cli.rs
文件用作命令行接口(command line interface)(CLI), 工程应该看起来是这样了
1 | $ tree -L 2 |
在cli.rs
里写入下面的代码, 这是rust
测试的基本结构
1 |
|
#[test]
属性(attribute)告诉rust
测试的时候执行这个函数assert!
宏, 断言一个boolean
表达式是true
我将在测试里使用assert!
宏断言boolean
表达式是true
, 或者使用assert_eq!
宏断言某个东西等于一个值.
这个测试将断言字面量true
为true
, 所以它永远都会通过.
使用cargo test
, 进行测试, 会看到下面的内容
1 | running 1 test |
再测试一下会失败的测试, 把代码里的true
改成false
1 |
|
运行之后可以看到输出
1 | running 1 test |
可以写很多的
assert!
和assert_eq!
断言,如果任何一个断言失败,那么整个测试就失败了.
测试一下ls
仅仅测试true
或者false
没有任何意义, 删除掉这个函数吧, 我们尝试执行hello
程序. 我准备用std::process::Command
来运行命令, 并获取执行结果. 我先尝试运行一下ls
命令, 这个命令应该在Unix
和windows
上都好用.
1 | use std::process::Command; |
use std::process::Command;
导入std::process::Command
, 用来创建一个新的command
let mut cmd = Command::new(“ls”);
新建一个command
来运行ls
.mut
的作用是让这个变量是可变的.
注意,Rust
中, 默认的变量都是不可变的, 也就是说他们的值不能变化.
也许中文的变量
就不再合适了,也许应该叫定量
?
let res = cmd.output();
接收执行的输出结果, 类型是Result
assert!(res.is_ok());
验证结果是Ok
值
运行cargo test
之后会看到通过了
1 | running 1 test |
改成测试自己写的hello
程序
现在把函数修改一下,让它运行hello
程序.
1 |
|
再次运行测试, 结果失败了,因为hello
程序找不到.
1 | running 1 test |
还记得吗, 可执行程序是在arget/debug/hello
目录里, 如果你直接在命令行里执行hello
程序, 就会发现根本找不到程序.
1 | $ hello |
在命令行中运行某个程序是,其实是操作系统去某些预先定义好的目录里根据程序名字去找要对应的程序.
在Unix
类型的系统中, 可以在shell
里查看PATH
这个环境变量, 你会看到用冒号(colon
)分割的一组目录(在windows
里这个变量是$env:Path
). 可以用tr
(translate characters)将冒号替换成换行(newlines
)(\n
)来查看一下PATH
.
1 | $ echo $PATH | tr : '\n' |
echo $PATH | tr : ‘\n’
使用管道|
将结果发送给tr
即便进入到target/debug
目录下,因为系统安全性的考虑,想要执行其中的文件时,必须明确的指示出文件路径。所以直接执行hello
程序,还是找不到文件。
1 | $ cd target/debug/ |
需要指定具体路径才行。
1 | $ ./hello |
待续
此路不通,之后解决。