当前位置: 首页 > news >正文

测试Rust代码

文章目录

  • 一、assert!
  • 二、使用 assert_eq! 和 assert_ne! 宏来测试相等
    • 1.自定义报错消息
    • 2.使用 should_panic 检查 panic
    • 3.测试函数返回Result类型
  • 三、cargo test 和cargo test --
    • cargo test -- --test-threads=1
    • cargo test -- --show-output打印失败运行的case的输出log
    • 运行部分case
    • 忽略test case
  • 四、rust测试组织
    • 单元测试
    • 集成测试
      • 在集成测试中引入公共的测试代码
      • 集成测试不能直接测试二进制crate
  • 参考

一、assert!

fn main() {}
#[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 tests {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 smaller_cannot_hold_larger() {let larger = Rectangle {width: 8,height: 7,};let smaller = Rectangle {width: 5,height: 1,};assert!(!smaller.can_hold(&larger));}
}

编译及运行:

▶ cargo test
warning: function `main` is never used--> src/lib.rs:1:4|
1 | fn main() {}|    ^^^^|= note: `#[warn(dead_code)]` on by defaultwarning: struct `Rectangle` is never constructed--> src/lib.rs:3:8|
3 | struct Rectangle {|        ^^^^^^^^^warning: method `can_hold` is never used--> src/lib.rs:9:8|
8 | impl Rectangle {| -------------- method in this implementation
9 |     fn can_hold(&self, other: &Rectangle) -> bool {|        ^^^^^^^^warning: `adder` (lib) generated 3 warningsFinished `test` profile [unoptimized + debuginfo] target(s) in 0.00sRunning unittests src/lib.rs (target/debug/deps/adder-6facd3ec2ad675f4)running 2 tests
test tests::smaller_cannot_hold_larger ... ok
test tests::larger_can_hold_smaller ... oktest result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00sDoc-tests adderrunning 0 teststest result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.0

二、使用 assert_eq! 和 assert_ne! 宏来测试相等

fn main() {}
pub fn add_two(a: i32) -> i32 {a + 2
}#[cfg(test)]
mod tests {use super::*;#[test]fn it_adds_two() {// 传递给assert_eq!或assert_ne!的参数必须实现PartialEq和Debug的traitassert_eq!(4, add_two(2));}
}

1.自定义报错消息

fn main() {}
pub fn greeting(name: &str) -> String {String::from("Hello!")
}#[test]
fn greeting_contains_name() {let result = greeting("Carol");assert!(result.contains("Carol"),"Greeting did not contain name, value was `{}`",result);
}

2.使用 should_panic 检查 panic

fn main() {}
pub struct Guess {value: i32,
}impl Guess {pub fn new(value: i32) -> Guess {if value < 1 || value > 100 {panic!("Guess value must be between 1 and 100, got {}.", value);}Guess {value}}
}#[cfg(test)]
mod tests {use super::*;#[test]#[should_panic]fn greater_than_100() {Guess::new(200);}
}

test cast总指定具体的#[should_panic]的内容,会与实际的发生panic!()的内容进行比较

fn main() {}
pub struct Guess {value: i32,
}// --snip--impl Guess {pub fn new(value: i32) -> Guess {if value < 1 {panic!("Guess value must be greater than or equal to 1, got {}.",value);} else if value > 100 {panic!("Guess value must be less than or equal to 100, got {}.",value);}Guess { value }}
}#[cfg(test)]
mod tests {use super::*;#[test]#[should_panic(expected = "Guess value must be less than or equal to 100")]fn greater_than_100() {Guess::new(200);}
}

3.测试函数返回Result类型

#![allow(unused)]
fn main() {}
#[cfg(test)]
mod tests {#[test]fn it_works() -> Result<(), String> {if 1 + 2 == 4 {Ok(())} else {Err(String::from("two plus two does not equal four"))}}
}
▶ cargo testCompiling adder v0.1.0 (/home/wangji/code/rust/2024_rust/rust_project/adder)Finished `test` profile [unoptimized + debuginfo] target(s) in 0.63sRunning unittests src/lib.rs (target/debug/deps/adder-6facd3ec2ad675f4)running 1 test
test tests::it_works ... FAILEDfailures:---- tests::it_works stdout ----
Error: "two plus two does not equal four"failures:tests::it_workstest result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00serror: test failed, to rerun pass `--lib`

三、cargo test 和cargo test –

cargo test – --test-threads=1

cargo test – 是为生成的二进制测试程序设置一些额外参数
cargo test 是适用于本身的参数

▶ cargo test -- --test-threads=1

cargo test – --show-output打印失败运行的case的输出log

默认失败的case中,如果被测函数有一些打印的话,是不会有输出内容的

▶ cargo test -- --show-output
#![allow(unused)]
fn main() {}
fn prints_and_returns_10(a: i32) -> i32 {println!("I got the value {}", a);10
}#[cfg(test)]
mod tests {use super::*;#[test]fn this_test_will_pass() {let value = prints_and_returns_10(4);assert_eq!(10, value);}#[test]fn this_test_will_fail() {let value = prints_and_returns_10(8);assert_eq!(5, value);}
}

运行部分case

#![allow(unused)]
fn main() {}
pub fn add_two(a: i32) -> i32 {a + 2
}#[cfg(test)]
mod tests {use super::*;#[test]fn add_two_and_two() {assert_eq!(4, add_two(2));}#[test]fn add_three_and_two() {assert_eq!(5, add_two(3));}#[test]fn one_hundred() {assert_eq!(102, add_two(100));}
}

仅运行一个test case

▶ cargo test one_hundredFinished `test` profile [unoptimized + debuginfo] target(s) in 0.00sRunning unittests src/lib.rs (target/debug/deps/adder-6facd3ec2ad675f4)running 1 test
test tests::one_hundred ... oktest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 2 filtered out; finished in 0.00s

运行add前缀的case

▶ cargo test addFinished `test` profile [unoptimized + debuginfo] target(s) in 0.00sRunning unittests src/lib.rs (target/debug/deps/adder-6facd3ec2ad675f4)running 2 tests
test tests::add_two_and_two ... ok
test tests::add_three_and_two ... oktest result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out; finished in 0.00s

运行test模块中的case

▶ cargo test tests::

忽略test case

#![allow(unused)]
fn main() {}
mod tests {#[test]fn it_works() {assert_eq!(2 + 2, 4);}#[test]#[ignore]fn expensive_test() {// 需要运行一个小时的代码}
}

编译及运行

▶ cargo test tests:: -- --test-threads=10

就是要运行ignore的case

▶ cargo test  -- --test-threads=10 --ignored

四、rust测试组织

单元测试

单元测试的代码和被测试的代码是在同一个文件中的

fn main() {}pub fn add_two(a: i32) -> i32 {internal_adder(a, 2)
}fn internal_adder(a: i32, b: i32) -> i32 {a + b
}// 测试模块一般呈称之为tests
#[cfg(test)]
mod tests {use super::*; //子模块访问父模块的函数// rust 可以测试私有函数// 单元测试代码可以与被测代码在一个文件中(通常在),也可以不在一个文件中#[test]fn internal() {assert_eq!(4, internal_adder(2, 2));}
}

集成测试

在这里插入图片描述

use adder; //来自于Cargo.toml中的name = "adder"
// cargo会将tests目录下的每个文件编译成一个单独的crate#[test]
fn it_adds_two() {assert_eq!(4, adder::add_two(2));
}
▶ cargo  test

在这里插入图片描述
仅仅运行集成测试

▶ cargo test --test integration_test
warning: function `main` is never used--> src/lib.rs:1:4|
1 | fn main() {}|    ^^^^|= note: `#[warn(dead_code)]` on by defaultwarning: `adder` (lib) generated 1 warningFinished `test` profile [unoptimized + debuginfo] target(s) in 0.94sRunning tests/integration_test.rs (target/debug/deps/integration_test-97da6b451065e35f)running 1 test
test it_adds_two ... oktest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

子目录中的文件不会被单独编译成一个crate,进行运行

在这里插入图片描述

在集成测试中引入公共的测试代码

use adder; //来自于Cargo.toml中的name = "adder"// cargo会将tests目录下的每个文件编译成一个单独的crate// 模块定义语法
// 内容要么来自common.rs文件,要么来自common目录下的文件
mod common;#[test]
fn it_adds_two() {common::setup();assert_eq!(4, adder::add_two(2));
}

在这里插入图片描述

集成测试不能直接测试二进制crate

二进制crate具有main.rs的项目,解决办法:需要一个轻量级的库crate去包装二进制的crate,通过库crate间接测试二进制crate

参考

  • 第11章~测试Rust代码(上)
  • 如何编写测试

http://www.mrgr.cn/news/69877.html

相关文章:

  • react的创建与书写
  • 随笔20241113 数据分组与期次累加计算功能实现
  • 产品经理如何提升项目管理能力
  • 基于springboot+vue实现的大型超市数据处理系统 (源码+L文+ppt)4-015
  • 成都睿明智科技有限公司解锁抖音电商新玩法
  • PHP:通往动态Web开发世界的桥梁
  • 程序运行的一些基础知识
  • 16、liunx硬盘修复
  • 材质(三)——材质参数集和材质函数
  • [C++11] 类中新特性的添加
  • 第三十一篇——微分(下):搞懂“奇点”,理解“连续性”
  • 【Flume实操】实时监听 NetCat 端口和本地文件数据到 HDFS 案例分析
  • 第11课 string类型的应用
  • 工单系统在手,双重挑战无忧
  • 用 Python 从零开始创建神经网络(三):添加层级(Adding Layers)
  • 【图】图学习
  • 了解Hadoop:大数据处理的核心框架
  • JUC并发队列及应用
  • 计算机研究生方向,零基础入门到精通,收藏这篇就够了
  • halcon仿射变换核心技术分析
  • 2024年【危险化学品生产单位主要负责人】找解析及危险化学品生产单位主要负责人考试技巧
  • 910. 最小差值 II
  • 《Python网络安全项目实战》项目3 处理文件中的数据_练习题(2)
  • GB/T 43206—2023信息安全技术信息系统密码应用测评要求(二)
  • 闭包的知识
  • CMS那点事