0%

Rust开发命令行工具 001_2 Hello World 编写并运行测试的准备阶段

测试的种类

我特别要给你们看一下如何进行测试.虽然代码很简单,但是也有一些需要验证的工作.主要有两大类测试,一个是从内向外的,我会写一些测试验证程序的内部功能. 另一个是从外向内的,我会写测试模仿用户使用程序.
前面一种称为单元测试(unit tests), 之后我们再讨论这种测试.
这个程序我想主要进行后一种测试,它被称为集成测试或者整合测试(integration test), 它把程序当成一个整体进行测试.

通常的做法是, 为集成测试创建一个目录, 这可以使代码组织的干净, 还能帮助编译器在不进行测试时直接忽略掉这个文件夹.

准备集成测试

使用命令创建文件夹

1
$ mkdir tests

我准备像普通用户运行程序一样测试hello程序, 所以先创建一个tests/cli.rs文件用作命令行接口(command line interface)(CLI), 工程应该看起来是这样了

1
2
3
4
5
6
7
8
9
10
11
$ tree -L 2
.
├── Cargo.lock
├── Cargo.toml
├── src
│   └── main.rs
├── target
│   ├── CACHEDIR.TAG
│   └── debug
└── tests
└── cli.rs

cli.rs里写入下面的代码, 这是rust测试的基本结构

1
2
3
4
#[test]
fn works() {
assert!(true);
}

#[test]属性(attribute)告诉rust测试的时候执行这个函数
assert!宏, 断言一个boolean表达式是 true

我将在测试里使用assert!宏断言boolean表达式是true, 或者使用assert_eq!宏断言某个东西等于一个值.
这个测试将断言字面量truetrue, 所以它永远都会通过.
使用cargo test, 进行测试, 会看到下面的内容

1
2
running 1 test
test works ... ok

再测试一下会失败的测试, 把代码里的true改成false

1
2
3
4
#[test]
fn works() {
assert!(false);
}

运行之后可以看到输出

1
2
running 1 test
test works ... FAILED

可以写很多的assert!assert_eq!断言,如果任何一个断言失败,那么整个测试就失败了.

测试一下ls

仅仅测试true或者false没有任何意义, 删除掉这个函数吧, 我们尝试执行hello程序. 我准备用std::process::Command来运行命令, 并获取执行结果. 我先尝试运行一下ls命令, 这个命令应该在Unixwindows上都好用.

1
2
3
4
5
6
7
8
use std::process::Command;

#[test]
fn runs() {
let mut cmd = Command::new("ls");
let res = cmd.output();
assert!(res.is_ok());
}

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
2
running 1 test
test runs ... ok

改成测试自己写的hello程序

现在把函数修改一下,让它运行hello程序.

1
2
3
4
5
6
#[test]
fn runs() {
let mut cmd = Command::new("hello");
let res = cmd.output();
assert!(res.is_ok());
}

再次运行测试, 结果失败了,因为hello程序找不到.

1
2
running 1 test
test runs ... FAILED

还记得吗, 可执行程序是在arget/debug/hello目录里, 如果你直接在命令行里执行hello程序, 就会发现根本找不到程序.

1
2
$ hello
-bash: hello: command not found

在命令行中运行某个程序是,其实是操作系统去某些预先定义好的目录里根据程序名字去找要对应的程序.
Unix类型的系统中, 可以在shell里查看PATH这个环境变量, 你会看到用冒号(colon)分割的一组目录(在windows里这个变量是$env:Path). 可以用tr(translate characters)将冒号替换成换行(newlines)(\n)来查看一下PATH.

1
2
3
4
5
6
7
8
9
$ echo $PATH | tr : '\n'
/opt/homebrew/bin
/Users/kyclark/.cargo/bin
/Users/kyclark/.local/bin
/usr/local/bin
/usr/bin
/bin
/usr/sbin
/sbin

echo $PATH | tr : ‘\n’
使用管道|将结果发送给tr

即便进入到target/debug目录下,因为系统安全性的考虑,想要执行其中的文件时,必须明确的指示出文件路径。所以直接执行hello程序,还是找不到文件。

1
2
3
4
5
$ cd target/debug/
$ ls hello
hello*
$ hello
-bash: hello: command not found

需要指定具体路径才行。

1
2
$ ./hello
Hello, world!

待续

此路不通,之后解决。

欢迎关注我的其它发布渠道