欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Rust編寫自動化測試實(shí)例權(quán)威指南

 更新時間:2022年12月05日 15:35:00   作者:麒麟閣  
這篇文章主要為大家介紹了Rust編寫自動化測試實(shí)例權(quán)威指南詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

一. 簡述

雖然Rust的類型系統(tǒng)為我們提供了相當(dāng)多的安全保障,但是還是不足以防止所有的錯誤。因此,Rust在語言層面內(nèi)置了編寫測試代碼、執(zhí)行自動化測試任務(wù)的功能。

測試是一門復(fù)雜的技術(shù),本章覆蓋關(guān)于如何編寫優(yōu)秀測試的每一個細(xì)節(jié),但是會討論Rust測試工具的運(yùn)行機(jī)制。我們會向你介紹編寫測試時常用的標(biāo)注和宏、運(yùn)行測試的默認(rèn)行為和選項(xiàng)參數(shù),以及如何將測試用例組織為單元測試與集成測試。

二. 編寫測試

Rust語言中的測試時一個函數(shù),它被用于驗(yàn)證非測試代碼是否按照期望的方式運(yùn)行。測試函數(shù)的函數(shù)體中一般包含3個部分:

  • 準(zhǔn)備所需的數(shù)據(jù)或狀態(tài)
  • 調(diào)用需要測試的代碼
  • 斷言運(yùn)行結(jié)果與我們期望的一致

接下來,我們會一起學(xué)習(xí)用于編寫測試代碼的相關(guān)功能,它們包含test屬性、一些測試宏及should_panic屬性。此時我們將建一個庫項(xiàng)目:cargo new adder —lib

此時adder庫項(xiàng)目自動生成一個src/lib.rs文件,此時cargo會給我們創(chuàng)建一個簡單的測試代碼模塊:

pub fn add(left: usize, right: usize) -> usize {
    left + right
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test] // @1
    fn it_works() {
        let result = add(2, 2);
        assert_eq!(result, 4); // @2
    }
}

我們可以看到@1這一行的#[test]標(biāo)注:它將當(dāng)前的函數(shù)標(biāo)記為一個測試,并使該函數(shù)可以在測試運(yùn)行中被識別出來。要知道,即便是在tests模塊中也可能會存在普通的非測試函數(shù),它們通常被用來執(zhí)行初始化操作或一些常用指令,所以我們必須要將測試函數(shù)標(biāo)注為#[test]。函數(shù)體中@2使用了assert_eq!宏斷言,這是一個典型的測試用例編寫方式。這時我們執(zhí)行命令:cargo test

xxxxx@xxxxxx adder % cargo test
   Compiling adder v0.1.0 (/rust-example/adder)
    Finished test [unoptimized + debuginfo] target(s) in 0.05s
     Running unittests src/lib.rs (target/debug/deps/adder-96bda0c2404f749c)
running 1 test  // 正在執(zhí)行一個測試
test tests::it_works ... ok // 此時函數(shù)
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s // 測試摘要,表示該集合中的所有測試均成功通過,1 passed; 0 failed則統(tǒng)計(jì)了通過和失敗的測試總數(shù)
   Doc-tests adder // 文件測試的結(jié)果
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

此時我們刪除初始化的代碼,我們編寫下面兩個測試函數(shù):

extern crate core;
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn ok_test() {
        assert_eq!(2 + 2, 4);
    }
    #[test]
    fn fail_test() {
        panic!("Make this test fail");
    }
}

此時我們再次執(zhí)行cargo test運(yùn)行測試!可預(yù)見的ok_test肯定是OK的,fail_test我們在里面寫了panic!測試失??!

xxxxxx@xxxxxx adder % cargo test
   Compiling adder v0.1.0 (/rust-example/adder)
    Finished test [unoptimized + debuginfo] target(s) in 0.13s
     Running unittests src/lib.rs (target/debug/deps/adder-96bda0c2404f749c)
running 2 tests
test tests::ok_test ... ok
test tests::fail_test ... FAILED
failures:
---- tests::fail_test stdout ----
thread 'tests::fail_test' panicked at 'Make this test fail', src/lib.rs:11:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
    tests::fail_test
test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
error: test failed, to rerun pass `--lib`

測試信息輸出非常明顯,測試失敗的位置提示很明確。

三. 測試相關(guān)的宏和函數(shù)

下面我們介紹一些我們在編寫測試時會使用到的相關(guān)宏和方法!

3.1. 使用assert!宏檢查結(jié)果

assert!宏由標(biāo)準(zhǔn)庫提供,它可以確保測試中某些條件的值是true。assert!宏可以接收一個能夠被計(jì)算為布爾類型的值作為參數(shù)。當(dāng)這個值為true時,assert!宏什么都不做并正常通過測試。而當(dāng)值時false時,assert!宏就會調(diào)用panic!宏,進(jìn)而導(dǎo)致測試失敗。使用assert!宏可以檢查代碼是否按照我們預(yù)期的方式運(yùn)行。

#[derive(Debug)]
pub struct Rectangle {
    length: u32,
    width: u32,
}
impl Rectangle {
    pub fn can_hold(&self, other: &Rectangle) -> bool {
        self.length > other.length && self.width > other.width
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn larger_can_hold_smaller() {
        let larger = Rectangle { length: 9, width: 7 };
        let smaller = Rectangle { length: 5, width: 1 };
        assert!(larger.can_hold(&smaller));
    }
    #[test]
    fn smaller_cannot_hold_larger() {
        let larger = Rectangle { length: 9, width: 7 };
        let smaller = Rectangle { length: 5, width: 1 };
        assert!(smaller.can_hold(&larger)); // fasle, 斷言失敗
    }
}

此時執(zhí)行cargo test測試代碼:一個成功,一個失敗。

xxxxx@xxxxxxx adder % cargo test
   Compiling adder v0.1.0 (/rust-example/adder)
    Finished test [unoptimized + debuginfo] target(s) in 0.12s
     Running unittests src/lib.rs (target/debug/deps/adder-96bda0c2404f749c)
running 2 tests
test tests::larger_can_hold_smaller ... ok
test tests::smaller_cannot_hold_larger ... FAILED
failures:
---- tests::smaller_cannot_hold_larger stdout ----
thread 'tests::smaller_cannot_hold_larger' panicked at 'assertion failed: smaller.can_hold(&larger)', src/lib.rs:29:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
    tests::smaller_cannot_hold_larger
test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
error: test failed, to rerun pass `--lib`

3.2. 使用assert_eq!宏和assert_ne!宏判斷相等性

在對功能進(jìn)行測試時,我們常常需要將被測試代碼的結(jié)果與我們所期望的結(jié)果相比較,并檢查它們是否相等。在標(biāo)準(zhǔn)庫中提供了一對可以簡化編程的宏:assert_eq!assert_ne!。這兩個宏分別用于比較并斷言兩個參數(shù)相等或不相等。在斷言失敗時,它們還可以自動打印出兩個參數(shù)的值,從而方便我們觀察測試失敗的原因;相反,使用assert!宏則只能得知==判斷表達(dá)式失敗的事實(shí),而無法知曉用于比較的值。

pub fn add_two(a: i32) -> i32 {
    a + 2
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn ok_adds_two_eq() {
        // 斷言結(jié)果相同測試通過
        assert_eq!(4, add_two(2));
    }
    #[test]
    fn fail_adds_two_eq() {
        // 斷言結(jié)果不相同觸發(fā)panic
        assert_eq!(5, add_two(2));
    }
    #[test]
    fn ok_adds_two_ne() {
        // 斷言結(jié)果不一致測試通過
        assert_ne!(5, add_two(2));
    }
    #[test]
    fn fail_adds_two_ne() {
        // 斷言結(jié)果相同觸發(fā)panic
        assert_ne!(4, add_two(2));
    }
}

執(zhí)行測試代碼:

yuelong@yuelongdeMBP adder % cargo test
   Compiling adder v0.1.0 (/Users/yuelong/CodeHome/TestProject/rust-example/adder)
    Finished test [unoptimized + debuginfo] target(s) in 0.12s
     Running unittests src/lib.rs (target/debug/deps/adder-96bda0c2404f749c)
running 4 tests
test tests::ok_adds_two_ne ... ok
test tests::ok_adds_two_eq ... ok
test tests::fail_adds_two_eq ... FAILED
test tests::fail_adds_two_ne ... FAILED
failures:
---- tests::fail_adds_two_eq stdout ----
thread 'tests::fail_adds_two_eq' panicked at 'assertion failed: `(left == right)`
  left: `5`,
 right: `4`', src/lib.rs:16:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
---- tests::fail_adds_two_ne stdout ----
thread 'tests::fail_adds_two_ne' panicked at 'assertion failed: `(left != right)`
  left: `4`,
 right: `4`', src/lib.rs:26:9
failures:
    tests::fail_adds_two_eq
    tests::fail_adds_two_ne
test result: FAILED. 2 passed; 2 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
error: test failed, to rerun pass `--lib`

測試順利通過檢查。

3.3. 添加自定義的錯誤提示信息

我們也可以添加自定義的錯誤提示信息,將其作為可選的參數(shù)傳入assert!、assert_eq!assert_ne!宏。實(shí)際上面任何在assert!、assert_eq!assert_ne!的必要參數(shù)之后出現(xiàn)的參數(shù)都會一起被傳遞給format!宏。因此,你甚至可以將一個包含{}占位符的格式化字符串及相對應(yīng)的填充值作為參數(shù)一起傳遞給這個宏。自定義的錯誤提示信息可以很方便地記錄當(dāng)前斷言的含義;這樣在測試失敗時,我們就可以更容易的知道代碼到底出了什么問題。

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

當(dāng)測試失敗之后:

running 1 test
test tests::greeting_test ... FAILED
failures:
---- tests::greeting_test stdout ----
thread 'tests::greeting_test' panicked at 'Greeting did not contain name, value was `Hello!`', src/lib.rs:16:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
    tests::greeting_test
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

這次的測試輸出中包含了實(shí)際的值,他能幫助我們觀察程序真正發(fā)生的行為,并迅速定位與預(yù)期產(chǎn)生差異的地方。

3.4. 使用should_panic檢查paninc

除了檢查代碼是否返回了正確的結(jié)果,確認(rèn)代碼能否按照預(yù)期處理錯誤狀態(tài)同樣重要。

pub struct Guess {
    value: u32,
}
impl Guess {
    pub fn new(value: u32) -> Guess {
        if value < 1 || value > 100 {
            panic!("Guess value must be between 1 and 100, got {}.", value);
        }
        Guess { value }
    }
    pub fn new_plus(value: u32) -> Guess {
        if value < 1 {
            panic!("Guess value must be between 1 and 100, got {}.", value);
        }
        Guess { value }
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    #[should_panic]
    fn new_test() {
        // 此時肯定會發(fā)生錯誤, 但是因?yàn)榧恿藄hould_panic宏,所有測試通過
        Guess::new(200);
    }
    #[test]
    #[should_panic]
    fn new_plus_test() {
        // 此時不會發(fā)生錯誤, 但是因?yàn)榧恿藄hould_panic宏,所有測試無法通過
        Guess::new(200);
    }
}

執(zhí)行cargo test并不會失敗:

running 2 tests
test tests::new_plus_test - should panic ... FAILED
test tests::new_test - should panic ... ok
failures:
---- tests::new_plus_test stdout ----
note: test did not panic as expected
failures:
    tests::new_plus_test
test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

使用should_panic進(jìn)行的測試可能會有些模糊不清,因?yàn)樗麄儍H僅能夠說明被檢查的代碼會發(fā)生panic。即便函數(shù)發(fā)生panic的原因和我們預(yù)期的不同,使用should_panic進(jìn)行測試也會順利通過。為了讓should_panic測試更加精確一些,我們可以在should_panic屬性中添加可選參數(shù)expected。它會檢查panic發(fā)生時輸出的錯誤提示信息是否包含了指定的文字。例子:

pub struct Guess {
    value: u32,
}
impl Guess {
    pub fn new(value: u32) -> 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);
        } else {
            Guess { value }
        }
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    #[should_panic(expected = "Guess value must be less than or equal to 100")]
    fn new_test() {
        // 此時肯定會發(fā)生錯誤
        Guess::new(0);
    }
}

此時再次執(zhí)行測試:

running 1 test
test tests::new_test - should panic ... FAILED
failures:
---- tests::new_test stdout ----
thread 'tests::new_test' panicked at 'Guess value must be greater than or equal to 1, got 0.', src/lib.rs:8:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
note: panic did not contain expected string
      panic message: `"Guess value must be greater than or equal to 1, got 0."`,
 expected substring: `"Guess value must be less than or equal to 100"`
failures:
    tests::new_test
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

3.5. 使用Result<T, E>編寫測試

到目前為止,我們編寫的測試都會在運(yùn)行失敗時觸發(fā)panic。不過我們也可以用Result<T, E>來編寫測試!例子:

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn new_test() -> Result<(), String> {
        if 2 + 2 == 4 {
            Ok(())
        } else {
            Err(String::from("two plus two does not equal four"))
        }
    }
}

在函數(shù)體中,我們不再調(diào)用assert_eq!宏,而是在測試的時候通過時返回Ok(()),在失敗時返回一個帶有StringErr值。

不要在使用Reuslt<T, E>編寫的測試上標(biāo)注#[should_panic]。在測試失敗時,我們應(yīng)該直接返回一個Err值。

四. 控制測試的運(yùn)行方式

如同cargo run會編譯代碼并運(yùn)行生成的二進(jìn)制文件一樣,cargo test同樣會在測試環(huán)境下編譯代碼,并運(yùn)行生成的測試二進(jìn)制文件。你可以通過指定命令行參數(shù)來改變cargo test的默認(rèn)行為。

cargo test --help // 查看cargo test的可用參數(shù)
cargo test -- --help // 顯示出所有可用在 -- 之后的參數(shù)

4.1. 并行或串行的進(jìn)行測試

當(dāng)我們嘗試運(yùn)行多個測試,Rust會默認(rèn)使用多線程來執(zhí)行它們。這樣可以讓測試更快地運(yùn)行完畢。從來盡早得到代碼是否可以正常工作的反饋。但是由于測試是同時進(jìn)行的,所以開發(fā)者必須保證測試之間不會互相依賴,或者依賴到同一個共享的狀態(tài)或環(huán)境上,例如當(dāng)前工作目錄、環(huán)境變量等。

如果你不想必行運(yùn)行測試,或者希望精確的控制測試時所啟動的線程數(shù)量,那么可以通過給測試二進(jìn)制文件傳入 —test-threads標(biāo)記及期望的具體線程數(shù)量來控制這一行為。

cargo test -- --test-threads=1 // 將線程數(shù)量控制為1,這也意味著程序不會使用任何并行操作,使用單線程執(zhí)行測試會比并行話費(fèi)更多的時間,但是順序執(zhí)行不會再因?yàn)楣蚕頎顟B(tài)而出現(xiàn)可能的干擾情形了

4.2. 顯示函數(shù)輸出

默認(rèn)情況下,Rust的測試庫會在測試通過時捕獲所有被打印至標(biāo)準(zhǔn)輸出中的消息。當(dāng)我們測試通過,它所打印的內(nèi)容就無法顯示在終端上;我們只能看到一條用于指明測試通過的消息。只有在測試失敗時,我么你才能在錯誤提示信息的上方觀察到打印至標(biāo)準(zhǔn)輸出中的內(nèi)容。例子:

pub fn add(x: i32, y: i32) -> i32 {
    println!("x => {}, y => {}", x, y); // @1
    x + y
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn new_test() {
        assert_eq!(4, add(2, 2))
    }
}

我們希望在測試通過時也將值打印出來,那么可以傳入—nocapture標(biāo)記來禁用輸出截獲功能,執(zhí)行下面的命令比較輸出結(jié)果:

cargo test -- --nocapture  // 會將@1也輸出顯示
cargo test                 // 沒有輸出@1

4.3. 只運(yùn)行部分特定名稱的測試

執(zhí)行全部的測試用例有時會花費(fèi)很長時間。而在編寫某個特定部分的代碼時,你也許只需要運(yùn)行和代碼相對應(yīng)地那部分測試。我們可以通過cargo test中傳遞測試名稱來指定需要運(yùn)行的測試。例子:

pub fn add(x: i32, y: i32) -> i32 {
    println!("x => {}, y => {}", x, y);
    x + y
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn new_test() {
        assert_eq!(4, add(2, 2))
    }
    #[test]
    fn new_test_1() {
        assert_eq!(5, add(2, 2))
    }
    #[test]
    fn test_1() {
        assert_eq!(6, add(2, 2))
    }
}

這時我們可以指定測試名稱進(jìn)行單獨(dú)測試:

cargo test new_test_1

另外我們可以使用名稱過濾運(yùn)行多個測試:

cargo test new // 此時就會匹配到 new_test 和 new_test_1這兩個測試

4.4. 通過顯示指定來忽略某些測試

有時,一些特定的測試執(zhí)行起來會非常耗時,所有你可能會想要在大部分的cargo test命令中忽略它們。除了手動將想要運(yùn)行的測試列舉出來,我們也可以使用ignore屬性來標(biāo)記這些耗時的測試,將這些測試排除在正常的測試運(yùn)行之外。

pub fn add(x: i32, y: i32) -> i32 {
    println!("x => {}, y => {}", x, y);
    x + y
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn new_test_1() {
        assert_eq!(5, add(2, 2))
    }
    #[test]
    #[ignore]
    fn test_1() {
        assert_eq!(6, add(2, 2))
    }
}

此時我們執(zhí)行cargo test時就可以很明顯的看到ignored的標(biāo)識:

xxxxxx@xxxxxxx adder % cargo test 
    Finished test [unoptimized + debuginfo] target(s) in 0.00s
     Running unittests src/lib.rs (target/debug/deps/adder-96bda0c2404f749c)
running 3 tests
test tests::test_1 ... ignored
test tests::new_test ... ok
test tests::new_test_1 ... FAILED

此時我們也可以使用cargo test —- —-ignored來單獨(dú)運(yùn)行這些被忽略的測試。

xxxxx@xxxxxx adder % cargo test -- --ignored
    Finished test [unoptimized + debuginfo] target(s) in 0.00s
     Running unittests src/lib.rs (target/debug/deps/adder-96bda0c2404f749c)
running 1 test
test tests::test_1 ... FAILED
failures:
---- tests::test_1 stdout ----

五. 測試的組織結(jié)構(gòu)

Rust社區(qū)主要從以下兩個分類來討論測試:單元測試(unit test)和集成測試(integration test)。單元測試小而專注,每次只單獨(dú)測試一個模塊或私有接口。而集成測試完全位于代碼庫之外,和正常從外部調(diào)用代碼一樣使用外部代碼,只能訪問公共接口,而且再一次測試中可能會聯(lián)用多個模塊。

5.1. 單元測試

單元測試的目的在于將一小段代碼單獨(dú)隔離出來,從而迅速確定這段代碼的功能是否符合預(yù)期。我們一般將單元測試與需要測試的代碼存放在src目錄下的同一文件中。同時也約定俗稱地在每個源代碼文件中都新建一個tests模塊來存放測試函數(shù),并使用cfg(test)對該模塊進(jìn)行標(biāo)注。

tests模塊上標(biāo)注#[cfg(test)]可以讓Rust只在執(zhí)行cargo test命令時編譯和運(yùn)行該部分測試代碼,而在執(zhí)行cargo build時剔除它們。這樣就可以在正常編譯時不包含測試代碼,從而節(jié)省編譯時間和產(chǎn)出物所占用的空間。我們不需要對集成測試標(biāo)注#[cfg(test)],因此集成測試本省就放置在獨(dú)立的目錄中。但是,由于本身測試是和業(yè)務(wù)代碼并列放置在同一文件中,所有我們必須使用#[cfg(test)]進(jìn)行標(biāo)注才能將單元測試的代碼排除在編譯產(chǎn)出物之外。Rust是允許測試私有函數(shù),例子:

// 共有函數(shù)
pub fn add(x: i32, y: i32) -> i32 { x + y }
// 私有函數(shù)
fn sub(x: i32, y: i32) -> i32 { x - y }
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn add_test() {
        assert_eq!(4, add(2, 2))
    }
    #[test]
    fn sub_test() {
        assert_eq!(0, sub(2, 2))
    }
}

5.2. 集成測試

Rust中,集成測試是完全位于代碼庫之外的。集成個測試調(diào)用庫的方式和其他的代碼調(diào)用方式?jīng)]有任何不同,這也意味著你只能調(diào)用對外公開提供的那部分接口。集成測試的目的在于驗(yàn)證庫的不同部分能否協(xié)同起來工作。能夠獨(dú)立對外公開提供的那部分接口。集成測試的目的在于驗(yàn)證庫的不同部分能否協(xié)同起來正常工作。能夠獨(dú)立正常工作的單元代碼的集成運(yùn)行時也會發(fā)生各種問題,所有集成測試的覆蓋同樣是非常重要的。

為了創(chuàng)建集成測試,我們需要首先建立一個tests目錄。tests是文件夾和src文件夾并列。Cargo會自動在這個目錄下尋找集成測試文件。在這個目錄下創(chuàng)建任意多個測試文件,Cargo在編譯時會將每個文件都處理為一個獨(dú)立的包。

我們在執(zhí)行cargo test

xxxxxx@xxxxxxx adder % cargo test
   Compiling adder v0.1.0 (/rust-example/adder)
    Finished test [unoptimized + debuginfo] target(s) in 0.15s
     Running unittests src/lib.rs (target/debug/deps/adder-96bda0c2404f749c)
running 1 test
test tests::add_test ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
     Running tests/adder_test.rs (target/debug/deps/adder_test-4bc3058753e422c8). // 執(zhí)行集成測試
running 1 test
test it_adds_two ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
   Doc-tests adder
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

如果此時有多個測試函數(shù),我們可以指定函數(shù)名,單獨(dú)運(yùn)行特定的集成測試函數(shù):

cargo test --test add_test

隨著集成測試增加,我們可以把tests目錄下的代碼分離到多個文件中。將每個集成測試的文件編譯成獨(dú)立的包有助于隔離作用域,并使集成測試環(huán)境更加貼近于用戶的使用場景。

但是在tests目錄中添加模塊并不是簡單的添加一個文件,如圖:

接著我們就可以在測試函數(shù)中引用了

mod common; // 引入模塊
use adder;
#[test]
fn it_adds_two() {
    common::setup(); // 調(diào)用
    assert_eq!(4, adder::add(2, 2))
}

最后需要注意一點(diǎn),如果我們的項(xiàng)目是一個只有src/main.rs文件而沒有src/lib.rs文件的二進(jìn)制包,那么我們就無法在tests目錄中創(chuàng)建集成測試,也無法使用過usesrc/main.rs中定義的函數(shù)導(dǎo)入作用域。只有代碼包(library crate)才可以將函數(shù)暴露給其他包調(diào)用,而二進(jìn)制包只被用于獨(dú)立執(zhí)行。

以上就是Rust編寫自動化測試實(shí)例權(quán)威指南的詳細(xì)內(nèi)容,更多關(guān)于Rust編寫自動化測試的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Rust 智能指針實(shí)現(xiàn)方法

    Rust 智能指針實(shí)現(xiàn)方法

    這篇文章主要介紹了Rust 智能指針的實(shí)現(xiàn)方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2024-01-01
  • Go調(diào)用Rust方法及外部函數(shù)接口前置

    Go調(diào)用Rust方法及外部函數(shù)接口前置

    這篇文章主要為大家介紹了Go調(diào)用Rust方法及外部函數(shù)接口前置示例實(shí)現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-06-06
  • Rust Struct結(jié)構(gòu)體詳解

    Rust Struct結(jié)構(gòu)體詳解

    結(jié)構(gòu)體,是一種自定義數(shù)據(jù)類型,允許程序員將不同類型的數(shù)據(jù)結(jié)合起來,形成相關(guān)聯(lián)的整體。Rust的結(jié)構(gòu)體還提供方法和關(guān)聯(lián)函數(shù),可以指定那些與結(jié)構(gòu)體數(shù)據(jù)相關(guān)的行為
    2022-10-10
  • Rust生命周期常見誤區(qū)(中英對照)全面指南

    Rust生命周期常見誤區(qū)(中英對照)全面指南

    這篇文章主要WEIDJAI?介紹了Rust生命周期常見誤區(qū)(中英對照)的全面指南,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • Rust使用csv crate構(gòu)建CSV文件讀取器的全過程

    Rust使用csv crate構(gòu)建CSV文件讀取器的全過程

    這篇文章主要學(xué)習(xí)如何基于Rust使用csv這個crate構(gòu)建一個CSV文件讀取器的過程,學(xué)習(xí)了csv相關(guān)的用法以及一些往期學(xué)過的crate的復(fù)習(xí),兼顧了實(shí)用性和Rust的學(xué)習(xí),需要的朋友可以參考下
    2024-05-05
  • rust智能指針的具體使用

    rust智能指針的具體使用

    智能指針是一些數(shù)據(jù)結(jié)構(gòu),它們的行為類似于指針但擁有額外的元數(shù)據(jù)和附加功能,本文就來介紹一下rust智能指針的具體使用,感興趣的可以了解一下
    2023-12-12
  • Rust?中?Mutex?的基本用法

    Rust?中?Mutex?的基本用法

    Rust?標(biāo)準(zhǔn)庫中的?Mutex?結(jié)構(gòu)體位于?std::sync::Mutex?中,它提供了線程安全的數(shù)據(jù)訪問,Mutex?保證了在同一時間只有一個線程可以訪問被鎖定的數(shù)據(jù),這篇文章主要介紹了Rust?中?Mutex?的基本用法,需要的朋友可以參考下
    2024-05-05
  • 詳解Rust 生命周期符號使用的方法和規(guī)律

    詳解Rust 生命周期符號使用的方法和規(guī)律

    生命周期是 Rust 中處理引用和所有權(quán)的關(guān)鍵概念,通過正確使用生命周期符號和遵循相關(guān)規(guī)律,你可以編寫出安全、高效的 Rust 代碼,這篇文章主要介紹了Rust 生命周期符號使用的方法和規(guī)律,需要的朋友可以參考下
    2024-03-03
  • Rust 累計(jì)時間長度的操作方法

    Rust 累計(jì)時間長度的操作方法

    在Rust中,如果你想要記錄累計(jì)時間,通??梢允褂脴?biāo)準(zhǔn)庫中的std::time::Duration類型,這篇文章主要介紹了Rust如何累計(jì)時間長度,需要的朋友可以參考下
    2024-05-05
  • 探索Rust切片與Go有何區(qū)別

    探索Rust切片與Go有何區(qū)別

    這篇文章主要為大家介紹了Rust切片與Go的區(qū)別探索,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01

最新評論