<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 測試 > [testing.md](https://github.com/rust-lang/rust/blob/master/src/doc/book/testing.md) commit 6ba952020fbc91bad64be1ea0650bfba52e6aab4 > Program testing can be a very effective way to show the presence of bugs, but it is hopelessly inadequate for showing their absence. > Edsger W. Dijkstra, "The Humble Programmer" (1972) > 軟件測試是證明bug存在的有效方法,而證明它們不存在時則顯得令人絕望的不足。 > Edsger W. Dijkstra,【謙卑的程序員】(1972) 讓我們討論一下如何測試Rust代碼。在這里我們不會討論什么是測試Rust代碼的正確方法。有很多關于寫測試好壞方法的流派。所有的這些途徑都使用相同的基本工具,所以我們會向你展示他們的語法。 ### `test`屬性(The test attribute) 簡單的說,測試是一個標記為`test`屬性的函數。讓我們用 Cargo 來創建一個叫`adder`的項目: ~~~ $ cargo new adder $ cd adder ~~~ 在你創建一個新項目時 Cargo 會自動生成一個簡單的測試。下面是`src/lib.rs`的內容: ~~~ #[test] fn it_works() { } ~~~ 注意這個`#[test]`。這個屬性表明這是一個測試函數。它現在沒有函數體。它肯定能編譯通過!讓我們用`cargo test`運行測試: ~~~ $ cargo test Compiling adder v0.0.1 (file:///home/you/projects/adder) Running target/adder-91b3e234d4ed382a running 1 test test it_works ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured Doc-tests adder running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ~~~ Cargo 編譯和運行了我們的測試。這里有兩部分輸出:一個是我們寫的測試,另一個是文檔測試。我們稍后再討論這些。現在,看看這行: ~~~ test it_works ... ok ~~~ 注意那個`it_works`。這是我們函數的名字: ~~~ fn it_works() { # } ~~~ 然后我們有一個總結行: ~~~ test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured ~~~ 那么為啥我們這個啥都沒干的測試通過了呢?任何沒有`panic!`的測試通過,`panic!`的測試失敗。讓我們的測試失敗: ~~~ #[test] fn it_works() { assert!(false); } ~~~ `assert!`是Rust提供的一個宏,它接受一個參數:如果參數是`true`,啥也不會發生。如果參數是`false`,它會`panic!`。讓我們再次運行我們的測試: ~~~ $ cargo test Compiling adder v0.0.1 (file:///home/you/projects/adder) Running target/adder-91b3e234d4ed382a running 1 test test it_works ... FAILED failures: ---- it_works stdout ---- thread 'it_works' panicked at 'assertion failed: false', /home/steve/tmp/adder/src/lib.rs:3 failures: it_works test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured thread '<main>' panicked at 'Some tests failed', /home/steve/src/rust/src/libtest/lib.rs:247 ~~~ Rust指出我們的測試失敗了: ~~~ test it_works ... FAILED ~~~ 這反映在了總結行上: ~~~ test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured ~~~ 我們也得到了一個非0的狀態碼.我們在 OS X和 Linux 中使用`$?`: ~~~ $ echo $? 101 ~~~ 在 Windows 中,如果你使用`cmd`: ~~~ > echo %ERRORLEVEL% ~~~ 而如果你使用 PowerShell: ~~~ > echo $LASTEXITCODE # the code itself > echo $? # a boolean, fail or succeed ~~~ 這在你想把`cargo test`集成進其它工具時是非常有用。 我們可以使用另一個屬性反轉我們的失敗的測試:`should_panic`: ~~~ #[test] #[should_panic] fn it_works() { assert!(false); } ~~~ 現在即使我們`panic!`了測試也會通過,并且如果我們的測試通過了則會失敗。讓我試一下: ~~~ $ cargo test Compiling adder v0.0.1 (file:///home/you/projects/adder) Running target/adder-91b3e234d4ed382a running 1 test test it_works ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured Doc-tests adder running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ~~~ Rust提供了另一個宏,`assert_eq!`用來比較兩個參數: ~~~ #[test] #[should_panic] fn it_works() { assert_eq!("Hello", "world"); } ~~~ 那個測試通過了嗎?因為那個`should_panic`屬性,它通過了: ~~~ $ cargo test Compiling adder v0.0.1 (file:///home/you/projects/adder) Running target/adder-91b3e234d4ed382a running 1 test test it_works ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured Doc-tests adder running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ~~~ `should_panic`測試是脆弱的,因為很難保證測試是否會因什么不可預測原因并未失敗。為了解決這個問題,`should_panic`屬性可以添加一個可選的`expected`參數。這個參數可以確保失敗信息中包含我們提供的文字。下面是我們例子的一個更安全的版本: ~~~ #[test] #[should_panic(expected = "assertion failed")] fn it_works() { assert_eq!("Hello", "world"); } ~~~ 這就是全部的基礎內容!讓我們寫一個“真實”的測試: ~~~ pub fn add_two(a: i32) -> i32 { a + 2 } #[test] fn it_works() { assert_eq!(4, add_two(2)); } ~~~ `assert_eq!`是非常常見的;用已知的參數調用一些函數然后與期望的輸出進行比較。 ### `ignore`屬性 有時一些特定的測試可能非常耗時。這時可以通過`ignore`屬性來默認禁用: ~~~ #[test] fn it_works() { assert_eq!(4, add_two(2)); } #[test] #[ignore] fn expensive_test() { // code that takes an hour to run } ~~~ 現在我們運行測試并發現`it_works`被執行了,而`expensive_test`沒有 ~~~ $ cargo test Compiling adder v0.0.1 (file:///home/you/projects/adder) Running target/adder-91b3e234d4ed382a running 2 tests test expensive_test ... ignored test it_works ... ok test result: ok. 1 passed; 0 failed; 1 ignored; 0 measured Doc-tests adder running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ~~~ 耗時的測試可以通過調用`cargo test -- --ignored`來執行: ~~~ $ cargo test -- --ignored Running target/adder-91b3e234d4ed382a running 1 test test expensive_test ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured Doc-tests adder running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ~~~ `--ignored`參數是 test 程序的參數,而不是 Cargo 的,這也是為什么命令是`cargo test -- --ignored`。 ### `tests`模塊 然而以這樣的方式來實現我們的測試的例子并不是地道的做法:它缺少`tests`模塊。如果要實現我們的測試實例,一個比較慣用的做法應該是如下的: ~~~ pub fn add_two(a: i32) -> i32 { a + 2 } #[cfg(test)] mod tests { use super::add_two; #[test] fn it_works() { assert_eq!(4, add_two(2)); } } ~~~ 這里產生了一些變化。第一個變化是引入了一個`cfg`屬性的`mod tests`。這個模塊允許我們把所有測試集中到一起,并且需要的話還可以定義輔助函數,它們不會成為我們包裝箱的一部分。`cfg`屬性只會在我們嘗試去運行測試時才會編譯測試代碼。這樣可以節省編譯時間,并且也確保我們的測試代碼完全不會出現在我們的正式構建中。 第二個變化是`use`聲明。因為我們在一個內部模塊中,我們需要把我們要測試的函數導入到當前空間中。如果你有一個大型模塊的話這會非常煩人,所以這里有經常使用一個`glob`功能。讓我們修改我們的`src/lib.rs`來使用這個: ~~~ pub fn add_two(a: i32) -> i32 { a + 2 } #[cfg(test)] mod tests { use super::*; #[test] fn it_works() { assert_eq!(4, add_two(2)); } } ~~~ 注意`use`行的變化。現在運行我們的測試: ~~~ $ cargo test Updating registry `https://github.com/rust-lang/crates.io-index` Compiling adder v0.0.1 (file:///home/you/projects/adder) Running target/adder-91b3e234d4ed382a running 1 test test tests::it_works ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured Doc-tests adder running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ~~~ 它能工作了! 目前的習慣是使用`test`模塊來存放你的“單元測試”。任何只是測試一小部分功能的測試理應放在這里。那么“集成測試”怎么辦呢?我們有`tests`目錄來處理這些。 ### `tests`目錄 為了進行集成測試,讓我們創建一個`tests`目錄,然后放一個`tests/lib.rs`文件進去,輸入如下內容: ~~~ extern crate adder; #[test] fn it_works() { assert_eq!(4, adder::add_two(2)); } ~~~ 這看起來與我們剛才的測試很像,不過有些許的不同。我們現在有一行`extern crate adder`在開頭。這是因為在`tests`目錄中的測試另一個完全不同的包裝箱,所以我們需要導入我們的庫。這也是為什么`tests`是一個寫集成測試的好地方:它們就像其它程序一樣使用我們的庫。 讓我們運行一下: ~~~ $ cargo test Compiling adder v0.0.1 (file:///home/you/projects/adder) Running target/adder-91b3e234d4ed382a running 1 test test tests::it_works ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured Running target/lib-c18e7d3494509e74 running 1 test test it_works ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured Doc-tests adder running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured ~~~ 現在我們有了三個部分:我們之前的兩個測試,然后還有我們新添加的。 這就是`tests`目錄的全部內容。它不需要`test`模塊因為它整個就是關于測試的。 讓我們最后看看第三部分:文檔測試。 ### 文檔測試 沒有什么是比帶有例子的文檔更好的了。當然也沒有什么比不能工作的例子更糟的,因為文檔完成之后代碼已經被改寫。為此,Rust支持自動運行你文檔中的例子(**注意:**這只在庫 crate中有用,而在二進制 crate 中沒用)。這是一個完整的有例子的`src/lib.rs`: ~~~ //! The `adder` crate provides functions that add numbers to other numbers. //! //! # Examples //! //! ``` //! assert_eq!(4, adder::add_two(2)); //! ``` /// This function adds two to its argument. /// /// # Examples /// /// ``` /// use adder::add_two; /// /// assert_eq!(4, add_two(2)); /// ``` pub fn add_two(a: i32) -> i32 { a + 2 } #[cfg(test)] mod tests { use super::*; #[test] fn it_works() { assert_eq!(4, add_two(2)); } } ~~~ 注意模塊級的文檔以`//!`開頭然后函數級的文檔以`///`開頭。Rust文檔在注釋中支持Markdown語法,所以它支持3個反單引號代碼塊語法。想上面例子那樣,加入一個`# Examples`部分被認為是一個慣例。 讓我們再次運行測試: ~~~ $ cargo test Compiling adder v0.0.1 (file:///home/steve/tmp/adder) Running target/adder-91b3e234d4ed382a running 1 test test tests::it_works ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured Running target/lib-c18e7d3494509e74 running 1 test test it_works ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured Doc-tests adder running 2 tests test add_two_0 ... ok test _0 ... ok test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured ~~~ 現在我們運行了3種測試!注意文檔測試的名稱:`_0`生成為模塊測試,而`add_two_0`函數測試。如果你添加更多用例的話它們會像`add_two_1`這樣自動加一。 我們還沒有講到所有編寫文檔測試的所有細節。關于更多,請看[文檔章節](#)。 最后再強調一次:文檔測試不能在二進制 crate 中運行。關于文件編排的細節請看[crate 和模塊](#)部分。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看