生命周期
当引用的生命周期可能以几种不同的方式相关联时,就必须标注生命周期了。
借用检查器Borrow Checker
- 确保数据存活的时间长于其引用(Outlive)
- 比较作用域,以确定所有的借用是否有效
例:
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
| fn main() { let string1 = String::from("abcd"); let string2 = "xyz"; let s: &'static str = "hello world";
let result = longest(string1.as_str(), string2); println!("{result}"); }
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y } }
struct Import<'a> { part: &'a str }
impl<'a> Import<'a> { fn level(&self) -> i32 { 3 } }
|
三条规则(在没有显式生命周期注解时)
- 编译器为每个输入类型中的每个生命周期分配不同的生命周期参数
- 如果只有一个输入生命周期参数,该生命周期将被分配给所有的输出生命周期参数
- 如果有多个输入生命周期参数,但其中一个是&sef或&mut self(因为这是一个方法),那么self的生命周期会被分配给所有的输出生命周期参数
编写测试
例:
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 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| #[derive(Debug)] struct Rectangle { width: u32, height: u32 }
impl Rectangle { fn can_hold(&self, other: &Rectangle) -> bool { self.width > other.width &&self.height > other.height } }
#[cfg(test)] mod test { use super::*;
#[test] fn larger_can_hold_smaller() { let larger = Rectangle { width: 8, height: 7 };
let smaller = Rectangle { width: 5, height: 1 }; assert!(larger.can_hold(&smaller)); }
#[test] fn larger_cannot_hold_smaller() { let larger = Rectangle { width: 8, height: 7 };
let smaller = Rectangle { width: 5, height: 1 }; assert!(!smaller.can_hold(&larger)); }
}
|
执行与组织测试
测试命令的参数
- 先列出cargo test的参数 cargo test –help
- 然后跟着– cargo test – –help ,再列出Test binary(测试二进制文件)的参数
测试的默认运行模式:使用线程并行运行
必须确保:
- 各个测试不互相依赖
- 不依赖于共享的状态(包括环境:目录、环境变量等)
单线程测试:
1
| cargo test -- --test-threads=1
|
在测试时将函数输出打印出来:
1
| cargo test -- --show-output
|
运行指定的测试:
1
| cargo test 函数名称(多个函数可以取其公有名称的部分)
|
在#[test]后加上#[ignore]后该测试默认不运行。
运行该被忽略的测试:
或者全部运行:
1
| cargo test -- --include-ignored
|
单元测试(Unit tests):小而集中的测试,每次只测试一个模块,并且可以测试私有接口
集成测试(Integration tests):完全外部的测试,它们以其他外部代码的方式使用你的代码,仅使用公共接口,并且可能
在一个测试中覆盖多个模块
如果项目只有binary crate(只有src/main.rs)不能创建集成测试
推荐的项目结构是:
- src/main.rs保持简单,主要用于调用
- src/Iib.rs包含主要逻辑
这样可以对ib.rs进行集成测试
原因是只有lib crate才能暴露函数供其他crate使用