iT邦幫忙

0

RISC-V on Rust 從零開始(4) - Rust 測試工具

這次要來談的是Rust的測試框架,並且重新調整目錄架構。

撰寫測試

Rust本身就自帶測試框架,無須安裝額外library,這邊直接把上次所寫的main改寫成test case如下:

fn main() {
    let mut core: RVCore = Default::default();
    core.run(5);
}

#[test]
fn test_core_run() {
    // Copy from main
    let mut core: RVCore = Default::default();
    core.run(5);
}

可以看到在定義fn的前面多了一個#[test] 屬性,代表這是一個test case 的定義,凡是帶有test屬性的function就會自動被當作測試執行。

cargo test 就可以看到測試結果:

#[test]
running 1 test
test test_core_run ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

只是把core跑起來沒有用處,測試需要斷言(assertion)來判斷程式的正確性:

#[test]
fn test_core_run() {
    let mut core: RVCore = Default::default();
    assert_eq!(0, core.pc);

    core.run(5);
    assert_eq!(20, core.pc);
}

assert_eq是Rust內建的macro,很多測試框架的convention都是把預期值放左邊,實際值放右邊,這裡也遵循此規則。初始化之後我們預期core的PC應該為0,跑了5個指令後,假設每個指令長度為4,PC就會變成5*4 = 20。重新執行cargo test,一樣可以看到test pass的輸出。

為了觀察test fail會發生什麼事,先把最後一行改成如下:

assert_eq!(10, core.pc);

執行cargo test就會看到test fail的訊息,以及是哪個test case 的哪一行fail:

thread 'test_core_run' panicked at 'assertion failed: `(left == right)`
  left: `10`,
 right: `20`', src/main.rs:33:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

在test case數量很多時,這些都是很有用的資訊,可以幫助我們快速定位出錯的地方。

調整目錄結構

到目前為止所有程式碼都寫在同一個檔案,雖然易於管理,當程式碼逐漸增加,可讀性很容易隨之降低。這邊將RVCore的實作獨立成為module:

  • 建立src/rv_core.rs,將RVCore的定義以及test code全部搬過去
  • 修改RVCore可見度,所有會被外部使用的成員都要加上pub修飾詞,目前有2個地方需要修改
    • pub struct RVCore // RVCore需要被外部的main.rs使用,必須為public
    • pub fn run() // main.rs會呼叫此method
  • 修改test code,用tests module包起來並且加上cfg(test)屬性,以避免cargo run編譯test code,以加速編譯。修改結果如下:
#[cfg(test)]
mod tests {
    use super::*; // 使RVCore所有成員在此module中可見

    #[test]
    fn test_core_run() {
        let mut core: RVCore = Default::default();
        assert_eq!(0, core.pc);

        core.run(5);
        assert_eq!(20, core.pc);
    }
}
  • 修改main.rs,加上適當的prefix
    • 在一開始加上mod rv_core,宣告rv_core模組
    • 所有的RVCore都要改成rv_core::RVCore,代表我想使用的是rv_core模組裡面的RVCore

依照Rust官方的教學,unit tests一般放在src/底下,目前直接與待測程式碼放在同檔案,以方便test code存取待測物。教學也有提到可以在src/旁邊新增一個tests/資料夾來放test code,不過那是屬於integration test的範疇,之後有需要再來研究。

完整的repo可以參考此連結


尚未有邦友留言

立即登入留言