[英]How to move tests into a separate file for binaries in Rust's Cargo?
我使用 Cargo 創建了一個新的二進制文件:
cargo new my_binary --bin
my_binary/src/main.rs
中的一個function可以用來測試:
fn function_from_main() {
println!("Test OK");
}
#[test]
fn my_test() {
function_from_main();
}
並且cargo test -- --nocapture
按預期運行測試。
將此測試移至單獨文件的最直接方法是什么(將function_from_main
保留在my_binary/src/main.rs
中)?
我試圖這樣做但不確定如何從單獨的文件中調用function_from_main
my_test
。
Rust 編程語言有一章專門介紹測試,你應該閱讀它以獲得基本的理解。
將單元測試(允許訪問代碼內部的test
)放入每個特定文件的test
模塊中是很常見的:
fn function_from_main() {
println!("Test OK");
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn my_test() {
function_from_main();
}
}
模塊可以移動到新文件,盡管這對於單元測試模塊來說並不常見:
主文件
fn function_from_main() {
println!("Test OK");
}
#[cfg(test)]
mod test;
測試.rs
use super::*;
#[test]
fn my_test() {
function_from_main();
}
有關文件和模塊如何相互映射的詳細信息,請參閱將模塊分成不同的文件。
單獨文件中的測試更常見的情況是集成測試。 書中還有一個專門介紹板條箱外測試的部分。 這些類型的測試非常適合作為代碼的使用者來執行代碼。
文檔的該部分包括介紹性示例和描述性文本:
我們在項目目錄的頂層創建一個測試目錄,在src旁邊。 Cargo 知道在這個目錄中尋找集成測試文件。 然后我們可以在這個目錄中創建任意數量的測試文件,Cargo 會將每個文件編譯為一個單獨的 crate。
讓我們創建一個集成測試。 將示例11-12 中的代碼仍在src/lib.rs文件中,創建一個測試目錄,創建一個名為tests/integration_test.rs的新文件,然后輸入示例11-13 中的代碼:
文件名:tests/integration_test.rs
use adder; #[test] fn it_adds_two() { assert_eq!(4, adder::add_two(2)); }
示例 11-13:加法器箱中函數的集成測試
我們在代碼頂部添加了
use adder
,我們在單元測試中不需要它。 原因是 tests 目錄中的每個測試都是一個單獨的 crate,所以我們需要將我們的庫放入每個 test crate 的范圍內。
請注意,該函數被稱為adder::add_two
。 關於 Rust 模塊系統的更多細節可以在包、板條箱和模塊章節中找到。
由於這些測試像用戶一樣運行您的 crate,如果您想測試一個binary ,您應該執行 binary 。 像assert_cmd這樣的crate可以幫助減少這種類型的測試的痛苦。
在其他情況下,您應該將大二進制文件分解為一個大庫和一個小二進制文件。 然后,您可以為庫的公共 API 編寫集成測試。
另見:
如果你有一個模塊foo.rs並且想要將你的單元測試放在一個名為foo_test.rs的文件中,你會發現這並不總是 Rust 尋找子模塊的地方。
可以使用#[path]
屬性指定模塊對應的文件位置:
#[cfg(test)]
#[path = "./foo_test.rs"]
mod foo_test;
你說得對; function_from_main
在main.rs
之外是不可訪問的。
您需要創建一個src/lib.rs
並src/lib.rs
移動要測試的函數。 然后你就可以使用extern crate my_binary;
來自您的測試模塊,並使您的函數出現在my_binary
命名空間下。
我確實相信您應該遵循閱讀 Rust 書中測試章節的建議,但是,這仍然不能完全回答您的問題,如何分離測試文件和源文件。
假設您有一個lib.rs
源文件並想要一個test_lib.rs
文件。 為此,您只需要:
在你的lib.rs
:
mod test_lib;
// rest of source
然后在你的test_lib.rs
中:
#[cfg(test)]
use super::*;
#[test]
fn test1() {
// test logic
}
// more tests
然后,你和cargo test
應該都很開心。
修飾*@mmai 的回答:
#[rustfmt::skip]
#[cfg(test)]
#[path = "./foo_test.rs"]
mod foo_test;
cargo fmt
似乎對新測試文件的路徑不滿意。 如果有人有更好的解決方案,我會很高興聽到它,因為我希望cargo fmt
也能格式化我的測試文件!
*抱歉:我添加這個只是作為對現有答案的評論,但我沒有足夠的聲譽。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.