🧪 把测试写在标准里的还是第一次见(可能是我见识太少了)
模块
定义
总之,为了建立工程化的文件,使用 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