你需要知道的 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