亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

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

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

一. 簡(jiǎn)述

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

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

二. 編寫測(cè)試

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

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

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

此時(shí)adder庫項(xiàng)目自動(dòng)生成一個(gè)src/lib.rs文件,此時(shí)cargo會(huì)給我們創(chuàng)建一個(gè)簡(jiǎn)單的測(cè)試代碼模塊:

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)記為一個(gè)測(cè)試,并使該函數(shù)可以在測(cè)試運(yùn)行中被識(shí)別出來。要知道,即便是在tests模塊中也可能會(huì)存在普通的非測(cè)試函數(shù),它們通常被用來執(zhí)行初始化操作或一些常用指令,所以我們必須要將測(cè)試函數(shù)標(biāo)注為#[test]。函數(shù)體中@2使用了assert_eq!宏斷言,這是一個(gè)典型的測(cè)試用例編寫方式。這時(shí)我們執(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í)行一個(gè)測(cè)試
test tests::it_works ... ok // 此時(shí)函數(shù)
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s // 測(cè)試摘要,表示該集合中的所有測(cè)試均成功通過,1 passed; 0 failed則統(tǒng)計(jì)了通過和失敗的測(cè)試總數(shù)
   Doc-tests adder // 文件測(cè)試的結(jié)果
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

此時(shí)我們刪除初始化的代碼,我們編寫下面兩個(gè)測(cè)試函數(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");
    }
}

此時(shí)我們?cè)俅螆?zhí)行cargo test運(yùn)行測(cè)試!可預(yù)見的ok_test肯定是OK的,fail_test我們?cè)诶锩鎸懥?code>panic!測(cè)試失??!

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`

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

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

下面我們介紹一些我們?cè)诰帉憸y(cè)試時(shí)會(huì)使用到的相關(guān)宏和方法!

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

assert!宏由標(biāo)準(zhǔn)庫提供,它可以確保測(cè)試中某些條件的值是trueassert!宏可以接收一個(gè)能夠被計(jì)算為布爾類型的值作為參數(shù)。當(dāng)這個(gè)值為true時(shí),assert!宏什么都不做并正常通過測(cè)試。而當(dāng)值時(shí)false時(shí),assert!宏就會(huì)調(diào)用panic!宏,進(jìn)而導(dǎo)致測(cè)試失敗。使用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, 斷言失敗
    }
}

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

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!宏判斷相等性

在對(duì)功能進(jìn)行測(cè)試時(shí),我們常常需要將被測(cè)試代碼的結(jié)果與我們所期望的結(jié)果相比較,并檢查它們是否相等。在標(biāo)準(zhǔn)庫中提供了一對(duì)可以簡(jiǎn)化編程的宏:assert_eq!assert_ne!。這兩個(gè)宏分別用于比較并斷言兩個(gè)參數(shù)相等或不相等。在斷言失敗時(shí),它們還可以自動(dòng)打印出兩個(gè)參數(shù)的值,從而方便我們觀察測(cè)試失敗的原因;相反,使用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é)果相同測(cè)試通過
        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é)果不一致測(cè)試通過
        assert_ne!(5, add_two(2));
    }
    #[test]
    fn fail_adds_two_ne() {
        // 斷言結(jié)果相同觸發(fā)panic
        assert_ne!(4, add_two(2));
    }
}

執(zhí)行測(cè)試代碼:

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`

測(cè)試順利通過檢查。

3.3. 添加自定義的錯(cuò)誤提示信息

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

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)測(cè)試失敗之后:

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

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

3.4. 使用should_panic檢查paninc

除了檢查代碼是否返回了正確的結(jié)果,確認(rèn)代碼能否按照預(yù)期處理錯(cuò)誤狀態(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() {
        // 此時(shí)肯定會(huì)發(fā)生錯(cuò)誤, 但是因?yàn)榧恿藄hould_panic宏,所有測(cè)試通過
        Guess::new(200);
    }
    #[test]
    #[should_panic]
    fn new_plus_test() {
        // 此時(shí)不會(huì)發(fā)生錯(cuò)誤, 但是因?yàn)榧恿藄hould_panic宏,所有測(cè)試無法通過
        Guess::new(200);
    }
}

執(zhí)行cargo test并不會(huì)失?。?/p>

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

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() {
        // 此時(shí)肯定會(huì)發(fā)生錯(cuò)誤
        Guess::new(0);
    }
}

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

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>編寫測(cè)試

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

#[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!宏,而是在測(cè)試的時(shí)候通過時(shí)返回Ok(()),在失敗時(shí)返回一個(gè)帶有StringErr值。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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))
    }
}

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

cargo test new_test_1

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

cargo test new // 此時(shí)就會(huì)匹配到 new_test 和 new_test_1這兩個(gè)測(cè)試

4.4. 通過顯示指定來忽略某些測(cè)試

有時(shí),一些特定的測(cè)試執(zhí)行起來會(huì)非常耗時(shí),所有你可能會(huì)想要在大部分的cargo test命令中忽略它們。除了手動(dòng)將想要運(yùn)行的測(cè)試列舉出來,我們也可以使用ignore屬性來標(biāo)記這些耗時(shí)的測(cè)試,將這些測(cè)試排除在正常的測(cè)試運(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))
    }
}

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

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

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

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 ----

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

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

5.1. 單元測(cè)試

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

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

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

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

我們?cè)趫?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í)行集成測(cè)試
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í)有多個(gè)測(cè)試函數(shù),我們可以指定函數(shù)名,單獨(dú)運(yùn)行特定的集成測(cè)試函數(shù):

cargo test --test add_test

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

但是在tests目錄中添加模塊并不是簡(jiǎn)單的添加一個(gè)文件,如圖:

接著我們就可以在測(cè)試函數(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)目是一個(gè)只有src/main.rs文件而沒有src/lib.rs文件的二進(jìn)制包,那么我們就無法在tests目錄中創(chuàng)建集成測(cè)試,也無法使用過usesrc/main.rs中定義的函數(shù)導(dǎo)入作用域。只有代碼包(library crate)才可以將函數(shù)暴露給其他包調(diào)用,而二進(jìn)制包只被用于獨(dú)立執(zhí)行。

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

相關(guān)文章

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

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

    這篇文章主要介紹了Rust 智能指針的實(shí)現(xiàn)方法,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    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ū)(中英對(duì)照)全面指南

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

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

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

    這篇文章主要學(xué)習(xí)如何基于Rust使用csv這個(gè)crate構(gòu)建一個(gè)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í)間只有一個(gè)線程可以訪問被鎖定的數(shù)據(jù),這篇文章主要介紹了Rust?中?Mutex?的基本用法,需要的朋友可以參考下
    2024-05-05
  • 詳解Rust 生命周期符號(hào)使用的方法和規(guī)律

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

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

    Rust 累計(jì)時(shí)間長(zhǎng)度的操作方法

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

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

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

最新評(píng)論