Rust学习笔记之测试、文档和基准

本文详细介绍了Rust编程中的测试方法,包括断言、单元测试、集成测试、文档编写和基准测试。阐述了如何使用Cargo进行测试,如何编写文档并生成文档,以及如何进行性能评估。此外,还讲解了如何通过实践案例——逻辑门模拟,巩固所学知识。
摘要由CSDN通过智能技术生成

测试是保证软件质量的关键一环,这一节主要讲 Cargo 还有怎么写测试,也包括如何为代码写文档,如何评估代码的性能。

断言

基本上单元测试都会通过断言来判断是否输出相同的预期结果:

布尔值:

assert!(true); // 最简单的断言
assert!(a==b, "{} was not equal to {}", a, b);
let a = 23;
let b = 87;
assert_eq!(a, b, "{} and {} are not equal", a, b); // 相等
assert_ne!(); // 不等

debug_assert!:类似于 assert!,但这个不是放在专门测试代码里的,是放在业务代码里的。在默认的 Debug 开发下,可以给出一些断言来验证执行过程中的结果的正确性。

单元测试

单元测试是轻量级的,可以快速进行的测试,针对都是一个独立的小功能进行测试,例如函数。

最简单的 Rust 单元测试:

// first_unit_test.rs

#[test]
fn basic_test() {
   
  assert!(true);
}

生成二进制可执行文件:rustc --test first_unit_test.rs
运行该二进制可执行文件,结果:

➜ rust_projects ./first_unit_test     

running 1 test
test basic_test ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

所有的测试默认是并行的,除非运行的时候通过环境变量指定测试的时候只要一个线程:RUST_TEST_THREADS=1

RUST_TEST_THREADS=1 ./first_unit_test 

隔离测试代码

测试越来越复杂的时候,我们希望能把测试代码和程序逻辑代码分开。那么可以把所有与测试相关的代码放到一个模块里。这时候可以使用使用 #[cfg(test)]

cfg 用于条件编译,也不是仅仅可以用在测试代码里。它可以通过 flag 决定包含或者排除该部分代码。在 #[cfg(test)] 中,flag 就是 test。意思就是说,只有运行 cargo test 的时候,测试代码才会被包含和编译进去。

比如说,编写一个函数用于生成测试用例,但你肯定不希望这个函数被包含在实际代码里。

先用 cargo 创建一个项目 cargo new unit_test --lib,之后 lib.rs 代码修改如下(可以看到创建项目生成的样例里的测试就有 #[cfg(test)]):

fn sum(a: i8, b: i8) -> i8 {
   
    a + b
}

#[cfg(test)]
mod tests {
   
    fn sum_inputs_outputs() -> Vec<((i8, i8), i8)> {
   
        vec![((1, 1), 2), ((0, 0), 0), ((2, -2), 0)]
    }

    #[test]
    fn test_sum() {
   
        for (input, output) in sum_inputs_outputs() {
   
            assert_eq!(crate::sum(input.0, input.1), output);
        }
    }
}

sum_inputs_outputs 用来生成输入和输出的测试用例,被用在 test_sum() 中。但是,要注意到这个函数没有 #[test] 注解。#[test] 属性可以使得代码不在最终发布的代码中。然而,sum_inputs_outputs 没有标记 #[test],但它放在了 test 模块中。

未通过测试

有一些情况下,你可能希望针对特定的输入是不能通过测试(失败)的,那么可能就想要测试框架可以断言在这种情况下是失败的。Rust 提供了一个 #[should_panic] 就是干这活的。

#[test]
#[should_panic]
fn this_panics() {
   
    assert_eq!(1, 2);
}

忽略测试

如果从持续集成,或者说敏捷开发的角度,是不应该忽略测试的,更不应该随便删除测试代码。如果你确定不想使用某个测试,或者说整个测试特别的重量级(或许应该考虑重构测试了),那么可以使用 #[ignore]

pub fn silly_loop() {
   
    for _ in 1..1_0000_0000 {
   }
}

#[cfg(test)]
mod tests {
   

    #[test]
    #[ignore]
    fn test_silly_loop() {
   
        crate::silly_loop();
    }
}

集成测试

单元测试可以用来测试私有接口和独立模块,集成测试则更像端到端的黑盒测试,针对的是公有的接口。从代码角度,两种并没有太大的区别。

新建一个库项目:

carg
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值