<style> .textleft { text-align:left; } .reveal, .reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 { font-family:Arial, Microsoft JhengHei;} .reveal .progress { height: 14px !important; } .progress span { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAMCAIAAAAs6UAAAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QUNCQzIyREQ0QjdEMTFFMzlEMDM4Qzc3MEY0NzdGMDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QUNCQzIyREU0QjdEMTFFMzlEMDM4Qzc3MEY0NzdGMDgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpBQ0JDMjJEQjRCN0QxMUUzOUQwMzhDNzcwRjQ3N0YwOCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpBQ0JDMjJEQzRCN0QxMUUzOUQwMzhDNzcwRjQ3N0YwOCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PovDFgYAAAAmSURBVHjaYvjPwMAAxjMZmBhA9H8INv4P4TPM/A+m04zBNECAAQBCWQv9SUQpVgAAAABJRU5ErkJggg==) repeat-x !important; } .progress span:after, .progress span.nyancat { content: ""; background: url(data:image/gif;base64,R0lGODlhIgAVAKIHAL3/9/+Zmf8zmf/MmZmZmf+Z/wAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/wtYTVAgRGF0YVhNUDw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpDMkJBNjY5RTU1NEJFMzExOUM4QUM2MDAwNDQzRERBQyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpCREIzOEIzMzRCN0IxMUUzODhEQjgwOTYzMTgyNTE0QiIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpCREIzOEIzMjRCN0IxMUUzODhEQjgwOTYzMTgyNTE0QiIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChXaW5kb3dzKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkM1QkE2NjlFNTU0QkUzMTE5QzhBQzYwMDA0NDNEREFDIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOkMyQkE2NjlFNTU0QkUzMTE5QzhBQzYwMDA0NDNEREFDIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8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) ; width: 34px !important; height: 21px !important; border: none !important; float: right; margin-top: -7px; margin-right: -10px; } .my-icon-css { width: 100%; height: 200px; background-position:center; background-repeat: no-repeat; background-image:url('https://mir-s3-cdn-cf.behance.net/project_modules/disp/fe36cc42774743.57ee5f329fae6.gif'); } </style> <!-- .slide: data-transition="slide" --> # <h2>ch11. Testing</h2> <div class="my-icon-css"></div> @Kais(VagrantPi) ###### tags: `Rust`, `簡報`, `Rust 讀書會` --- <!-- .slide: data-transition="convex" --> ## Agenda - Writing tests - Runung tests - Test Organization --- <!-- .slide: data-transition="convex" --> ## Writing tests ---- ### assert_eq!、assert_ne! <!-- .slide: data-transition="convex" --> ```rust #[cfg(test)] mod tests { #[test] fn it_works() { assert_eq!(2 + 2, 4); } } ``` ---- <!-- .slide: data-transition="convex" --> ``` $ cargo test Compiling adder v0.1.0 (file:///projects/adder) Finished dev [unoptimized + debuginfo] target(s) in 0.22 secs Running target/debug/deps/adder-ce99bcc2479f4607 running 1 test test tests::it_works ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Doc-tests adder running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out ``` ---- <!-- .slide: data-transition="convex" --> ``` test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out ``` - passed: 通過測試 - failed: 未通過 - ignored: 忽略 - measured: 性能測試(benchmark tests),目前只有 Rust 開發版(nightly Rust)才有 - filtered out: 過濾、忽略的 ---- <!-- .slide: data-transition="convex" --> ### assert! ```rust #[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 { // tests mod 如需測試外部 mod 就需要引入,這裡選擇全局導入 // 以便使用全部外部 mod 定義的內容 use super::*; #[test] fn larger_can_hold_smaller() { let larger = Rectangle { length: 8, width: 7 }; let smaller = Rectangle { length: 5, width: 1 }; assert!(larger.can_hold(&smaller)); } #[test] fn smaller_cannot_hold_larger() { let larger = Rectangle { length: 8, width: 7 }; let smaller = Rectangle { length: 5, width: 1 }; assert!(!smaller.can_hold(&larger)); } } ``` ``` running 2 tests test tests::smaller_cannot_hold_larger ... ok test tests::larger_can_hold_smaller ... ok test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out ``` ---- <!-- .slide: data-transition="convex" --> ### 自訂錯誤訊息 ```diff pub fn greeting(name: &str) -> String { - format!("Hello {}!", name) + String::from("Hello!") } #[cfg(test)] mod tests { use super::*; #[test] fn greeting_contains_name() { let result = greeting("Carol"); assert!(result.contains("Carol")); } } ``` ---- <!-- .slide: data-transition="convex" --> ``` running 1 test test tests::greeting_contains_name ... FAILED failures: ---- tests::greeting_contains_name stdout ---- thread 'tests::greeting_contains_name' panicked at 'assertion failed: result.contains("Carol")', src/lib.rs:12:8 note: Run with `RUST_BACKTRACE=1` for a backtrace. failures: tests::greeting_contains_name ``` ---- <!-- .slide: data-transition="convex" --> ```rust #[test] fn greeting_contains_name() { let result = greeting("Carol"); assert!( result.contains("Carol"), "Greeting did not contain name, value was `{}`", result ); } ``` ---- <!-- .slide: data-transition="convex" --> ``` ---- tests::greeting_contains_name stdout ---- thread 'tests::greeting_contains_name' panicked at 'Greeting did not contain name, value was `Hello!`', src/lib.rs:12:8 note: Run with `RUST_BACKTRACE=1` for a backtrace. ``` ---- <!-- .slide: data-transition="convex" --> ### should_panic ```rust 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 } } } #[cfg(test)] mod tests { use super::*; #[test] #[should_panic] fn greater_than_100() { Guess::new(200); } } ``` ``` running 1 test test tests::greater_than_100 ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out ``` ---- <!-- .slide: data-transition="convex" --> ### should_panic(expected="...") ```rust 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); } Guess { value } } } #[cfg(test)] mod tests { use super::*; #[test] #[should_panic(expected = "Guess value must be less than or equal to 100")] fn greater_than_100() { Guess::new(200); } #[test] #[should_panic(expected = "Guess value must be greater than or equal to 1")] fn less_than_1() { Guess::new(0); } } ``` --- <!-- .slide: data-transition="convex" --> ## Runung tests ---- <!-- .slide: data-transition="convex" --> ## 並行執行 ``` $ cargo test -- --test-threads=1 ``` ---- <!-- .slide: data-transition="convex" --> ## 顯示函示輸出 ```rust fn prints_and_returns_10(a: i32) -> i32 { println!("I got the value {}", a); 10 } #[cfg(test)] mod tests { use super::*; #[test] fn this_test_will_pass() { let value = prints_and_returns_10(4); assert_eq!(10, value); } #[test] fn this_test_will_fail() { let value = prints_and_returns_10(8); assert_eq!(5, value); } } ``` ---- <!-- .slide: data-transition="convex" --> ``` running 2 tests test tests::this_test_will_pass ... ok test tests::this_test_will_fail ... FAILED failures: ---- tests::this_test_will_fail stdout ---- I got the value 8 thread 'tests::this_test_will_fail' panicked at 'assertion failed: `(left == right)` left: `5`, right: `10`', src/lib.rs:19:8 note: Run with `RUST_BACKTRACE=1` for a backtrace. failures: tests::this_test_will_fail test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out ``` 如果連成功的都要輸出,可以使用 ``` $ cargo test -- --nocapture ``` ---- <!-- .slide: data-transition="convex" --> ### 只跑單個測試 ```rust pub fn add_two(a: i32) -> i32 { a + 2 } #[cfg(test)] mod tests { use super::*; #[test] fn add_two_and_two() { assert_eq!(4, add_two(2)); } #[test] fn add_three_and_two() { assert_eq!(5, add_two(3)); } #[test] fn one_hundred() { assert_eq!(102, add_two(100)); } } ``` ---- <!-- .slide: data-transition="convex" --> ``` $ cargo test one_hundred Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs Running target/debug/deps/adder-06a75b4a1f2515e9 running 1 test test tests::one_hundred ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 2 filtered out ``` ---- <!-- .slide: data-transition="convex" --> ### 只跑過濾過的多個測試 ``` $ cargo test add Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs Running target/debug/deps/adder-06a75b4a1f2515e9 running 2 tests test tests::add_two_and_two ... ok test tests::add_three_and_two ... ok test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out ``` ---- <!-- .slide: data-transition="convex" --> ### 忽略某些測試 ```rust #[test] fn it_works() { assert_eq!(2 + 2, 4); } #[test] #[ignore] fn expensive_test() { // code that takes an hour to run } ``` ---- <!-- .slide: data-transition="convex" --> ``` $ cargo test Compiling adder v0.1.0 (file:///projects/adder) Finished dev [unoptimized + debuginfo] target(s) in 0.24 secs Running target/debug/deps/adder-ce99bcc2479f4607 running 2 tests test expensive_test ... ignored test it_works ... ok test result: ok. 1 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out ``` ---- <!-- .slide: data-transition="convex" --> 也可以只跑 ignored 的測試 ``` $ cargo test -- --ignored Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs Running target/debug/deps/adder-ce99bcc2479f4607 running 1 test test expensive_test ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out ``` --- <!-- .slide: data-transition="convex" --> ## Test Organization ---- <!-- .slide: data-transition="convex" --> ## 單元測試(unit tests) ---- <!-- .slide: data-transition="convex" --> ### 測試 module 與 cfg(test) - `#[cfg(test)]` 註解用來告訴 Rust 只在執行 `cargo test` 時才測試,在 `cargo build` 不會做 - cfg 属性代表 configuration,用來告訴 Rust 編譯或執行時的設定 ---- <!-- .slide: data-transition="convex" --> ### 測試私有函數 src/lib.rs ```rust pub fn add_two(a: i32) -> i32 { internal_adder(a, 2) } fn internal_adder(a: i32, b: i32) -> i32 { a + b } #[cfg(test)] mod tests { use super::*; #[test] fn internal() { assert_eq!(4, internal_adder(2, 2)); } } ``` ---- <!-- .slide: data-transition="convex" --> ## 整合測試(integration tests) ---- <!-- .slide: data-transition="convex" --> 需要在專案根目錄建立 `tests` 目錄 tests/integration_test.rs ```rust // adder 為整個專案的名稱 // 在單元測試中不用寫,不過整合測試中 // 每個 tests 底下的測試檔案都是獨立的 crate // 所以需要將所每一個檔案都引入 extern crate adder; // 這裡不需要 #[cfg(test)] #[test] fn it_adds_two() { assert_eq!(4, adder::add_two(2)); } ``` ---- <!-- .slide: data-transition="convex" --> ``` $ cargo test Compiling adder v0.1.0 (file:///projects/adder) Finished dev [unoptimized + debuginfo] target(s) in 0.31 secs Running target/debug/deps/adder-abcabcabc running 1 test test tests::internal ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Running target/debug/deps/integration_test-ce99bcc2479f4607 running 1 test test it_adds_two ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Doc-tests adder running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out ``` 輸出的三個部分分別為: 單元測試、整合測試、文件測試 ---- <!-- .slide: data-transition="convex" --> ### 只執行指定的整合測試 只跑 tests/integration_test.rs 中的測試 ``` $ cargo test --test integration_test Finished dev [unoptimized + debuginfo] target(s) in 0.0 secs Running target/debug/integration_test-952a27e0126bb565 running 1 test test it_adds_two ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out ``` ---- <!-- .slide: data-transition="convex" --> ### 整合測試中的子 module tests/common.rs ```rust pub fn setup() { // setup code specific to your library's tests would go here } ``` ---- <!-- .slide: data-transition="convex" --> ``` running 1 test test tests::internal ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Running target/debug/deps/common-b8b07b6f1be2db70 running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Running target/debug/deps/integration_test-d993c68b431d39df running 1 test test it_adds_two ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Doc-tests adder running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out ``` ``` 測試時不希望測試到 common.rs,我們只希望在其他整合測試時用到它 tests/common.rs -> tests/common/mod.rs ``` ---- <!-- .slide: data-transition="convex" --> tests/integration_test.rs ```rust extern crate adder; mod common; #[test] fn it_adds_two() { common::setup(); assert_eq!(4, adder::add_two(2)); } ``` --- <!-- .slide: data-transition="convex" --> ## Thanks for listening ~
{"metaMigratedAt":"2023-06-14T18:56:19.520Z","metaMigratedFrom":"Content","title":"<h2>ch11. Testing</h2>","breaks":true,"contributors":"[{\"id\":\"69ade472-3ed3-499d-8a69-767243a31621\",\"add\":19157,\"del\":1009}]"}
    1228 views