以前的Java程序员会喜欢这个crate。Getset crate包含用于生成getter和setter方法的过程性宏。
use getset::{CopyGetters, Getters, MutGetters, Setters};
#[derive(Getters, Setters, MutGetters, CopyGetters, Default)]
pub struct Foo<T>
where
T: Copy + Clone + Default,
{
#[getset(get, set, get_mut)]
private: T,
#[getset(get_copy = "pub", set = "pub", get_mut = "pub")]
public: T,
}
fn main() {
let mut foo = Foo::default();
foo.set_private(1);
(*foo.private_mut()) += 1;
assert_eq!(*foo.private(), 2);
}
Mockall crate为(几乎所有)Trait和结构体提供了自动生成的模拟对象,这些对象可以在单元测试中使用,而不是使用原始类型的对象,这可以使编写高级单元测试或测试复杂的边缘情况变得更容易。
#[cfg(test)]
use mockall::{automock, predicate::*};
#[cfg_attr(test, automock)]
trait CalcTrait {
fn foo(&self, x: u32) -> u32;
}
fn calculation(calc: impl CalcTrait, x: u32) -> u32 {
calc.foo(x)
}
#[test]
fn test() {
let mut mock = MockCalcTrait::new();
mock.expect_foo().with(eq(4)).times(1).returning(|x| x + 1);
assert_eq!(5, calculation(mock, 4));
}
可以使用#[automock]属性宏自动生成模拟对象。但是,它有其局限性,因此有时必须使用过程宏mock!手动实现模拟对象。
QuickCheck是一个基于属性的测试框架。它允许测试带有大量任意输入数据的代码。如果发现了错误,它会自动找到最小的测试用例来重现错误。
#[cfg(test)]
mod tests {
fn reverse<T: Clone>(xs: &[T]) -> Vec<T> {
let mut rev = vec!();
for x in xs {
rev.insert(0, x.clone())
}
rev
}
#[quickcheck]
fn double_reversal_is_identity(xs: Vec<isize>) -> bool {
xs == reverse(&reverse(&xs))
}
}
和quickcheck一样,protest也是一个基于属性的测试框架。然而,与quickcheck相比,它可以更灵活的生成输入数据,尽管对于复杂的数据,它可能比quickcheck运行时间长得多。
proptest! {
#[test]
fn doesnt_crash(s in "\\PC*") {
parse_date(&s);
}
#[test]
fn parses_date_back_to_original(y in 0u32..10000,
m in 1u32..13,
d in 1u32..32)
{
let result = parse_date(&format!("{:04}-{:02}-{:02}", y, m, d)).unwrap();
prop_assert_eq!((y, m, d), result);
}
}
Heck crate用于将文本转换为各种常用的变量命名样式,如CamelCase、snake_case等。
use heck::ToShoutyKebabCase;
#[test]
fn test() {
assert_eq!("i am very angry!".to_shouty_kebab_case(), "I-AM-VERY-ANGRY");
}
num_cpus crate 用于确定物理CPU内核的数量或可以在系统上有效执行的并行任务的数量。
fn main() {
println!("Logical CPUs: {}", num_cpus::get());
println!("Physical CPUs: {}", num_cpus::get_physical());
}
25,Humantime
Humantime crate 以人类可读的格式为std::time::{Duration, SystemTime}提供了格式化器和解析器。它还通过humantime-serde crate与serde集成。
例如,可以在应用程序/服务配置中以可读格式指定Duration值,而不是在变量名中使用度量单位,从而减少错误的可能性:
use serde::{Deserialize, Serialize};
use std::time::Duration;
#[test]
fn format() {
let duration = Duration::new(9420, 0);
let as_str = "2h 37m";
assert_eq!(humantime::format_duration(duration).to_string(), as_str);
assert_eq!(humantime::parse_duration(as_str), Ok(duration));
}
#[derive(Serialize, Deserialize)]
struct Foo {
#[serde(with = "humantime_serde")]
timeout: Duration,
}
#[test]
fn serde() {
let input = r#" { "timeout": "3 days 1hour 12min 5s" } "#;
let foo: Foo = serde_json::from_str(input).unwrap();
assert_eq!(foo.timeout, Duration::new(263525, 0));
}
Copyright© 2013-2020
All Rights Reserved 京ICP备2023019179号-8