🧪 把测试写在标准里的还是第一次见(可能是我见识太少了)
模块
定义
总之,为了建立工程化的文件,使用 cargo 新建工程。
cargo new <工程名>
cargo new --lib <库名>
工程中的 main.rs 或 lib.rs 是所有相关文件的根文件。
利用 mod 定义模块,在模块之中还能再定义模块。
mod my_module{
mod module_in_module{
fn add() {}
}
}
在模块中使用 pub 关键字标明公共方法。结构体和结构体内的字段, pub 是分开的。
主文件以外的文件本身不需要重复定义。如果有文件am.rs,再在am.rs里定义mod am {fn add},那么需要am::am::add才能拿到函数。
路径
- 调用路径:使用
::分割。 - 绝对路径:
crate开头。例crate::my_module::module_in_module。(需要先在根文件里声明pub mod a;) - 相对路径:
my_module::module_in_module。 - 使用
super开始父级的相对路径。 - 用
use简化后面路径的书写。可以用as给予别名。 - 利用花括号调用同级:
use std::{cmp::Ordering, io}; - 利用
*导入所有use std::*;
声明
在 main.rs 里声明模块才能把文件都连接起来,例:
src/
├── calculate.rs
└── main.rs
//calculate.rs
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
// main.rs
mod calculate; // 声明模块
fn main() {
println!("{}", calculate::add(1, 2));
}
拆分
在不同的文件写同一个模块的内容,例:
src/
├── calculate/
│ └── multiply.rs
├── calculate.rs
├── divided.rs
├── minus.rs
└── main.rs
//src\calculate\multiply.rs
pub fn multiply(a: i32, b: i32) -> i32 {
a * b
}
// src/calculate.rs
pub mod multiply;
// pub mod divided; 不能同级作子级
// to create the module `divided`, create file "src\calculate\divided.rs" or "src\calculate\divided\mod.rs"
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
// src/divided.rs
pub fn divided(a: i32, b: i32) -> i32 {
a / b
}
//src/minus.rs
pub mod calculate{
pub fn minus(a: i32, b: i32) -> i32 {
a - b
}
}
mod calculate; // 声明模块
mod minus;
fn main() {
println!("{}", calculate::add(1, 2));
// println!("{}", calculate::minus(1, 2));
println!("{}", minus::calculate::minus(1, 2)); // 无法跨文件共用 mod 括号
// println!("{}", calculate::multiply(1, 2));
println!("{}", calculate::multiply::multiply(1, 2));
// println!("{}", calculate::multiply::divide::divide(1, 2));
}
# Cargo.toml
[lib]
name = "modul"
path = "src/lib.rs"
[[bin]]
name = "modul"
path = "src/main.rs"
测试
基础
在函数前添加 #[test] 表明这是一个测试用的函数。之后运行 cargo test 就可以执行测试函数。
#[test]
fn test(){
}
测试主要分 单元测试 和 集成测试 。
-
单元测试通常是在文件中创建一个名字为test的模块包含测试功能,代码在src目录内。 -
集成测试则是纯外部代码。通常需要在工程中建立一个 和src同级的test文件夹。集成测试只测试lib。
在模块前添加 #[cfg(test)] 表明测试用模块。测试模块只在测试时编译。
#[cfg(test)]
mod tests {
use super::*; //使用这让测试函数使用外部模块定义的代码
#[test]
fn is_true() {
assert!(true);
}
}
宏
执行断言:
assert!(<表达式>); //返回成功或失败
assert_eq!(<表达式1>,<表达式2>); //测试两个表达式是否相等
自定义错误信息:
assert!(false,"错误信息 {}", err);
对于应该 panic 的函数在 #[test] 下使用 #[should_panic]。
使用 #[ignore] 忽略此测试函数。
控制
cargo test 的参数有作用于 cargo test 本身的,也有作用于生成的测试文件的。如果想要传给生成的测试文件参数,将参数放在分隔符 -- 后:
`cargo test <参数> -- <生成二进制文件的参数>`
例: cargo test -- --test-threads=1 。
| 作用于 cargo test 的参数 | 含义 |
|---|---|
<测试名字> | 只运行函数名中包含此名字的测试函数/模块 |
| 作用于测试文件的参数 | 含义 |
|---|---|
--test-threads=1 | 测试线程数 |
--show-output | 显示测试函数的结果 |
--ignored | 只运行被忽略的函数 |
- 主要是 《The Book》 的读书笔记。
- Rustlings 的做题感想
- 封面图片:来自 Undraw