你需要知道的 32 個 Rust 庫 - 4
19,Getset
以前的 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);
}
20,Mockall
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! 手動實現模擬對象。
21,QuickCheck
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))
}
}
22,Proptest
和 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);
}
}
23,Heck
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");
}
24,num_cpus
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));
}
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/amyf3pSmG_OCcMHmJw45fw