Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RustBook Ch.11 Testing

RustBook Ch.11 Testing

2019-02-23(Sat)に、RustBook勉強会にて使用したスライドです。

Katsuki Kobayashi

February 23, 2019
Tweet

More Decks by Katsuki Kobayashi

Other Decks in Technology

Transcript

  1. ࣗಈςετΛॻ͜͏! μΠΫετϥઌੜᐌ͘ (1972 ೥ͷΤοηΠ) “Program testing can be very effective

    way to show the presence of bugs, but it is hopelessly inadequate for showing their absence.” όάͷଘࡏΛࣔ͢ޮՌతͳํ๏Ͱ͸͋Δ͕ɺ ແ͍ࣄΛࣔ͢ʹ͸ઈ๬తʹෆॆ෼Ͱ͋Δ Ͱ΋ɺ ʮςετΛؤுΔ΂͖Ͱ͸ͳ͍ʯ ɺ ͱ͍͏ҙຯͰ͸ͳ͍ Katsuki Kobayashi RustBook ษڧձ
  2. ྫ: add_two() (1/2) add_two() ೖྗ͞Εͨ஋ʹ 2 ΛՃ͑ͯฦؔ͢਺ ೖग़ྗ͸ͱ΋ʹ੔਺ ίϯύΠϧ͢Δͱ Rust

    ͕νΣοΫ ܕͷҰக (String ΛೖΕͨΒΤϥʔ) borrow (มͳࢀরΛͨ͠ΒΤϥʔ) ؔ਺ͷڍಈ͸ϊʔνΣοΫ 10 ଍͞ΕΑ͏͕ 50 Ҿ͔ΕΑ͏͕ Τϥʔʹ͸ͳΒͳ͍ ʮࣗಈςετʯͷग़൪ Katsuki Kobayashi RustBook ษڧձ
  3. ྫ: add_two() (2/2) ςετͷํ๏ͷྫ 3 Λ༩͑ͨΒ 5 Λฦ͢ͱ assert ͢Δ

    ͜ͷςετΛɺίʔυͷมߋͷ౓ʹߦͳ͏ ਖ਼͍͠ڍಈΛ͍ͯ͠ΔࣄΛ֬ೝ Katsuki Kobayashi RustBook ษڧձ
  4. How to Write Tests Rust ͷςετ ίʔυ͕ظ଴௨Γಈ͔͘Λ֬ೝ͢Δςετؔ਺ ςετؔ਺Ͱ͸ҰൠʹҎԼͷ 3 ͭͷΞΫγϣϯ

    Λ࣮ߦ ඞཁͳσʔλ΍ঢ়ଶΛ४උ͢Δ ςετ͍ͨ͠ίʔυΛ࣮ߦ͢Δ ݁Ռ͕ظ଴௨Γ͔Ξαʔτ͢Δ Ҏ߱ɺRust ͕ςετͷͨΊʹఏڙ͍ͯ͠Δ΋ ͷΛ঺հ test attribute ϚΫϩ should_panic attributeɺ౳ Katsuki Kobayashi RustBook ษڧձ
  5. The Anatomy of a Test Function(1/7) ͿͬͪΌ͚ɺRust ͷςετͱ͸ test attribute

    Λ͚ͭͨؔ਺ͷ͜ͱ attribute: Chapt. 5 Ͱ࢖ͬͨ derive ͱ͔ test attribute ͷ෇͚ํ: fn ͷલʹ #[test] Λ෇͚Δ test attribute Λ෇͚Δͱ cargo test ίϚϯυ ςετϥϯφʔΛϏϧυ࣮ͯ͠ߦ ϨϙʔτΛදࣔ (passes or fails) Katsuki Kobayashi RustBook ษڧձ
  6. The Anatomy of a Test Function(2/7) cargo new adder --lib

    ͢Δ % cargo new adder --lib Created library ‘adder‘ package src/libs.rs ͕ҎԼͷ಺༰Ͱ࡞੒͞ΕΔ 1 #[cfg(test)] 2 mod tests { 3 #[test] 4 fn it_works() { 5 assert_eq!(2 + 2, 4); 6 } 7 } ͱΓ͋͑ͣ #[cfg(test)] ͱ mod tests ͷߦ ͸ແࢹ Katsuki Kobayashi RustBook ษڧձ
  7. The Anatomy of a Test Function(3/7) 1 #[cfg(test)] 2 mod

    tests { 3 #[test] 4 fn it_works() { 5 assert_eq!(2 + 2, 4); 6 } 7 } #[test] ςετؔ਺Λࣔ͢ ڞ௨ॲཧ౳Λॻ͘ඇςετؔ਺΋ಉ͡Ϟδϡʔϧ ಺ʹॻ͚ΔΑ͏ʹͳ͍ͬͯΔ assert_eq!(2 + 2, 4) 2 + 2 ͕ 4 Ͱ͋ΔࣄΛΞαʔτ Katsuki Kobayashi RustBook ษڧձ
  8. The Anatomy of a Test Function(4/7) % cargo test Compiling

    adder v0.1.0 (/home/rare/work/slides/RustBook/samples/adder) Finished dev [unoptimized + debuginfo] target(s) in 0.53s Running target/debug/deps/adder-1d0dfd1494bab5c6 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 Playground Ͱ΋ςετͰ͖Δʜʜ ignored, filtered ʹ͍ͭͯ͸࣍અͰઆ໌ measured ʹ͍ͭͯ͸ݱࡏ͸ nightly ͚ͩ ϕϯνϚʔΫςετ༻ Katsuki Kobayashi RustBook ษڧձ
  9. The Anatomy of a Test Function(5/7) Doc-tests adder ͱ͍͏ग़ྗ͕͋Δ υΩϡϝϯτςετͷ݁Ռ

    API ͷυΩϡϝϯτͷίʔσΟϯάྫ΋ίϯύΠ ϧ/ςετՄೳ υΩϡϝϯτͱίʔυͷಉظʹ໾ཱͭ!! Katsuki Kobayashi RustBook ษڧձ
  10. The Anatomy of a Test Function(5/7) Doc-tests adder ͱ͍͏ग़ྗ͕͋Δ υΩϡϝϯτςετͷ݁Ռ

    API ͷυΩϡϝϯτͷίʔσΟϯάྫ΋ίϯύΠ ϧ/ςετՄೳ υΩϡϝϯτͱίʔυͷಉظʹ໾ཱͭ!! Chapt. 14 “Documentation Comments” Ͱ΍Δͷ Ͱεϧʔ͠·͢ Katsuki Kobayashi RustBook ษڧձ
  11. The Anatomy of a Test Function(6/7) ςετͷ໊લΛมߋ it_works() Λ exploration()

    ʹͯ͠ΈΔ Playground ແࣄʹ݁Ռͷදࣔʹ൓ө running 1 test test tests::exploration ... ok Katsuki Kobayashi RustBook ษڧձ
  12. The Anatomy of a Test Function(7/7) ࣦഊ͢ΔςετΛೖΕͯΈΔ panic! ϚΫϩΛ࢖ͬͯ another()

    ؔ਺Λ࡞Δ Playground 1 #[test] 2 fn another() { 3 panic!("Make␣this␣test␣fail"); 4 } ແࣄࣦഊ͢Δ (લճΑΓ 2 ߲ͭ໨͕૿͑ͯΔ) test tests::another ... FAILED failures: ---- tests::another stdout ---- thread ’tests::another’ panicked at ’Make this test fail!’, src/lib.rs:10:9 failures: tests::another Katsuki Kobayashi RustBook ษڧձ
  13. Checking Results with the assert! (1/5) assert! ϚΫϩ true: Կ΋͠ͳ͍

    false: panic! Λίʔϧ Chapt. 5 ͷ Rectanble ߏ଄ମΛྫʹ Playground 1 #[derive(Debug)] 2 pub struct Rectangle { 3 length: u32, 4 width: u32, 5 } 6 7 impl Rectangle { 8 pub fn can_hold(&self, other: &Rectangle) -> bool { 9 self.length > other.length && self.width > other.width 10 } 11 } Katsuki Kobayashi RustBook ษڧձ
  14. Checking Results with the assert! (2/5) 1 #[derive(Debug)] 2 pub

    struct Rectangle { 3 length: u32, 4 width: u32, 5 } 6 7 impl Rectangle { 8 pub fn can_hold(&self, other: &Rectangle) -> bool { 9 self.length > other.length && self.width > other.width 10 } 11 } can_hold() ϝιου ϒʔϧ஋Λฦ͢ → assert! Ͱͷςετʹ࠷ద!! length ͕ 8 , width ͕ 7 ͷ Rectangle ͕ length ͕ 5 , width ͕ 1 ͷ Rectangle Λ hold Ͱ ͖ΔࣄΛςετ Katsuki Kobayashi RustBook ษڧձ
  15. Checking Results with the assert! (3/5) larger_can_hold_smaller() ςετ Playground (use

    super::*; ͢Δඞཁ͋Γ) 1 #[test] 2 fn larger_can_hold_smaller() { 3 let larger = Rectangle { length: 8, width: 7 }; 4 let smaller = Rectangle { length: 5, width: 1 }; 5 6 assert!(larger.can_hold(&smaller)); 7 } running 1 test test tests::larger_can_hold_smaller ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out can_hold() ͸ true Λฦ͢ͷͰ pass ͢Δ Katsuki Kobayashi RustBook ษڧձ
  16. Checking Results with the assert! (4/5) smaller_cannot_hold_larger() ςετ Playground 1

    #[test] 2 fn smaller_cannot_hold_larger() { 3 let larger = Rectangle { length: 8, width: 7 }; 4 let smaller = Rectangle { length: 5, width: 1 }; 5 6 assert!(!smaller.can_hold(&larger)); // ’!’ ͕ϛι 7 } running 2 tests test tests::larger_can_hold_smaller ... ok test tests::smaller_cannot_hold_larger ... ok test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out can_hold() ͕ false Λฦ͢ͷͰ pass ͢Δ Katsuki Kobayashi RustBook ษڧձ
  17. Checking Results with the assert! (5/5) όάΛ࢓ࠐΜͰΈΔ length ͷෆ౳߸͕ٯ Playground

    1 impl Rectangle { 2 pub fn can_hold(&self, other: &Rectangle) -> bool { 3 self.length < other.length && self.width > other.width 4 } // ^ 5 } ໨࿦ݟ௨Γ fail ͢Δ running 2 tests test tests::larger_can_hold_smaller ... FAILED test tests::smaller_cannot_hold_larger ... ok failures: ---- tests::larger_can_hold_smaller stdout ---- thread ’tests::larger_can_hold_smaller’ panicked at ’assertion failed: larger. note: Run with ‘RUST_BACKTRACE=1‘ for a backtrace. Katsuki Kobayashi RustBook ษڧձ
  18. Testing Equality with the assert_eq! (1/4) ςετͷҰൠతͳํ๏͸ظ଴஋ͱ݁Ռͷൺֱ assert! ϚΫϩʹ ==

    Λ౉ͯ͠΋Α͍ assert_eq!, assert_ne! ϚΫϩ΋͋Δ ͜ΕΒ͸ظ଴஋ͱ݁Ռͷ྆ํΛදࣔͯ͘͠ΕΔ Katsuki Kobayashi RustBook ษڧձ
  19. Testing Equality with the assert_eq! (2/4) add_two() ʹΑΔྫ: (Playground) 1

    fn main() {} 2 pub fn add_two(a: i32) -> i32 { 3 a + 2 4 } 5 6 #[cfg(test)] 7 mod tests { 8 use super::*; 9 10 #[test] 11 fn it_adds_two() { 12 assert_eq!(4, add_two(2)); 13 } 14 } test tests::it_adds_two ... ok Katsuki Kobayashi RustBook ษڧձ
  20. Testing Equality with the assert_eq! (3/4) ࣦഊ͢ΔΑ͏ʹ͢Δ (Playground) 1 fn

    main() {} 2 pub fn add_two(a: i32) -> i32 { 3 a + 3 // ͳ͔ͥ 3 Λ଍͢ 4 } thread ’tests::it_adds_two’ panicked at ’assertion failed: ‘(left == right)‘ left: ‘4‘, right: ‘5‘’, src/lib.rs:11:9 left ͱ right ͕දࣔ͞ΕΔ ଞͷݴޠ΍ςετϑϨʔϜϫʔΫͩͱ expected ͱ actual ͱݺΜͩΓ͢Δ Rust ͸ظ଴஋ͱ݁Ռͷॱ൪Λؾʹ͠ͳ͍ͷͰ assert_eq!(add_two(2), 4); ͱͯ͠΋ OK Katsuki Kobayashi RustBook ษڧձ
  21. Testing Equality with the assert_eq! (4/4) assert_ne!ϚΫϩ΋͋Δ 2 ͭͷ஋͕ҟͳΕ͹ passɺ౳͚͠Ε͹

    fail ʮ݁Ռ͕ਖ਼֬ʹղΒͳ͍͕ಛఆͷ஋ʹ͸ͳΒͳ͍ʯ ͱ͍͏ςετʹ࢖͏ ྫ͑͹ɺ݁Ռ͕࣮ߦ͢Δ࣌ؒʹΑͬͯมԽ͢Δ ΋ͷ assert_eq!ͱ assert_ne! ࢖༻͢Δ஋ʹ͸ PartialEq ͱ Debug τϨΠτ͕࣮ ૷͞Ε͍ͯΔඞཁ͕͋Δ ’==’ ͱ ’! =’ Ͱൺֱ ݁ՌΛσόοάϑΥʔϚοτͰදࣔ͢Δ ಠࣗʹ࣮૷ͨ͠ߏ଄ମ΍ enum ʹ͍ͭͯ ͸#[derive(PartialEq, Debug)] ͱ෇͚Ε͹େ ఍ OK Katsuki Kobayashi RustBook ษڧձ
  22. Adding Custom Failure Messages(1/5) ࣦഊ࣌ͷϝοηʔδΛ௥ՃͰ͖Δ assert!, assert_eq!, assert_ne! ϚΫϩͷҾ ਺ͷଓ͖ʹ

    format! ϚΫϩʹ౉͢Ҿ਺Λ෇͚Δ “{} textholder” Λॻ͍ͯ஋ΛදࣔͰ͖Δ Katsuki Kobayashi RustBook ษڧձ
  23. Adding Custom Failure Messages(2/5) greet ؔ਺ʹΑΔྫ (Playground) 1 pub fn

    greeting(name: &str) -> String { 2 format!("Hello␣{}!", name) 3 } 4 5 #[cfg(test)] 6 mod tests { 7 use super::*; 8 9 #[test] 10 fn greeting_contains_name() { 11 let result = greeting("Carol"); 12 assert!(result.contains("Carol")); 13 } 14 } ࠓޙͷ࢓༷มԽ΁ͷରԠͷͨΊɺग़ྗʹҾ਺ (໊લ) ؚ͕·Ε͍ͯΔ͔Ͱςετ͍ͯ͠Δ Katsuki Kobayashi RustBook ษڧձ
  24. Adding Custom Failure Messages(3/5) ౰વɺςετ͸௨Δ running 1 test test tests::greeting_contains_name

    ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Ͱ͸ɺյ͠·͠ΐ͏ (Playground) 1 pub fn greeting(_name: &str) -> String { 2 String::from("Hello!") // Ҿ਺Λؚ·ͳ͍Α͏ʹ 3 } Katsuki Kobayashi RustBook ษڧձ
  25. Adding Custom Failure Messages(4/5) յΕ·ͨ͠ failures: ---- tests::greeting_contains_name stdout ----

    thread ’tests::greeting_contains_name’ panicked at \ ’assertion failed: result.contains("Carol")’, src/lib.rs:12:9 note: Run with ‘RUST_BACKTRACE=1‘ for a backtrace. Ͱ΋ ςετ͕ࣦഊͨ͠ assert ͷ಺༰͚ͩදࣔ͞ΕΔ result.contains("Carol") greeting() ؔ਺ͷग़ྗΛදࣔͨ͠ํ͕ศར Katsuki Kobayashi RustBook ษڧձ
  26. Adding Custom Failure Messages(5/5) ςετΛมߋ͢Δ (Playground) 1 #[test] 2 fn

    greeting_contains_name() { 3 let result = greeting("Carol"); 4 assert!( 5 result.contains("Carol"), 6 "Greeting␣did␣not␣contain␣name,␣value␣was␣‘{}‘", result 7 ); 8 } failures: ---- tests::greeting_contains_name stdout ---- thread ’tests::greeting_contains_name’ panicked at \ ’Greeting did not contain name, value was ‘Hello!‘’, src/lib.rs:12:9 note: Run with ‘RUST_BACKTRACE=1‘ for a backtrace. Katsuki Kobayashi RustBook ษڧձ
  27. Panic with should_panic (1/8) ݁Ռ͕ਖ਼͍͔͠ͷνΣοΫ͚ͩͰͳ͘ɺΤϥʔ ৚݅ʹ͍ͭͯͷνΣοΫ΋ॏཁ ྫͱͯ͠ Guess type(9 ষ)

    Ͱઆ໌͠·͢ ߏ଄ମͷ value ϑΟʔϧυ: 1 ∼ 100 new() ϝιουͰ஋͕ൣғ֎ͳ panic ͢Δ 1 pub struct Guess { 2 value: i32, 3 } 4 impl Guess { 5 pub fn new(value: i32) -> Guess { 6 if value < 1 || value > 100 { 7 panic!("Guess␣value␣must␣be␣between␣1␣and␣100,␣got␣{}.", value); 8 } 9 Guess { 10 value 11 } 12 } 13 } Katsuki Kobayashi RustBook ษڧձ
  28. Panic with should_panic (2/8) ൣғ֎ͷ஋ΛೖΕͯ panic ͤ͞ΔςετΛॻ͘ attribute Λ௥Ճ͢Δ :

    should_panic panic ͨ͠Β pass, ͠ͳ͔ͬͨΒ fail (Playground) 1 #[cfg(test)] 2 mod tests { 3 use super::*; 4 5 #[test] 6 #[should_panic] // ॱ൪͸ٯͰ΋ྑ͍໛༷ 7 fn greater_than_100() { 8 Guess::new(200); 9 } 10 } running 1 test test tests::greater_than_100 ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Katsuki Kobayashi RustBook ษڧձ
  29. Panic with should_panic (3/8) όάΛ࢓ࠐΈ·͠ΐ͏ (Playground) 1 impl Guess {

    2 pub fn new(value: i32) -> Guess { 3 if value < 1 /* ΑΓେ͖͍৚݅Λফ͢ 100 */ { 4 panic!("Guess␣value␣must␣be␣between␣1␣and␣100,␣got␣{}.", 5 value); 6 } 7 Guess { 8 value 9 } 10 } 11 } ແࣄʹࣦഊ͢Δ running 1 test test tests::greater_than_100 ... FAILED Katsuki Kobayashi RustBook ษڧձ
  30. Panic with should_panic (4/8) running 1 test test tests::greater_than_100 ...

    FAILED ϝοηʔδ͕ෆ਌੾ Ճ͑ͯɺshould_panic ͸ෆਖ਼֬ʹͳΓ͕ͪ ςετ͕ظ଴ͱ͸ҟͳΔ panic Λىͯ͜͠΋ pass ͢Δ ΋͏ͪΐͬͱ਌੾͔ͭਖ਼֬ʹ͢ΔͨΊʹ expected ύϥϝʔλʔΛ should_panic attribute ʹ௥Ճ͢Δ Katsuki Kobayashi RustBook ษڧձ
  31. Panic with should_panic (5/8) new() ϝιουΛมߋ ॳظ஋͕େ͖͗͢Δ͔ɺখ͗͢͞Δ͔Ͱɺpanic ࣌ ͷϝοηʔδΛมߋ͢Δ 1

    pub fn new(value: i32) -> Guess { 2 if value < 1 { 3 panic!("Guess␣value␣must␣be␣greater␣than␣or␣equal␣to␣1,␣got␣{}.", 4 value); 5 } else if value > 100 { 6 panic!("Guess␣value␣must␣be␣less␣than␣or␣equal␣to␣100,␣got␣{}.", 7 value); 8 } 9 } Katsuki Kobayashi RustBook ษڧձ
  32. Panic with should_panic (6/8) should_panic ʹ expected ύϥϝʔλ (Playground) panic

    ࣌ͷϝοηʔδͷ substring Λࢦఆ͢Δ 1 #[cfg(test)] 2 mod tests { 3 use super::*; 4 5 #[test] 6 #[should_panic( 7 expected = "Guess value must be less than or equal to 100")] 8 fn greater_than_100() { 9 Guess::new(200); 10 } 11 } running 1 test test tests::greater_than_100 ... ok Katsuki Kobayashi RustBook ษڧձ
  33. Panic with should_panic (7/8) όάΛ࢓ࠐΉ panic ͷจݴΛೖΕସ͑ͨ (Playground) 1 if

    value < 1 { 2 panic!("Guess␣value␣must␣be␣less␣than␣or␣equal␣to␣100,␣got␣{}.", 3 value); 4 } else if value > 100 { 5 panic!("Guess␣value␣must␣be␣greater␣than␣or␣equal␣to␣1,␣got␣{}.", 6 value); 7 } Katsuki Kobayashi RustBook ษڧձ
  34. Panic with should_panic (8/8) ແࣄࣦഊ͢Δ ύχοΫͷจݴ͕දࣔ දࣔ͞ΕΔ΂͖จݴ͕ note ʹදࣔ failures:

    ---- tests::greater_than_100 stdout ---- thread ’tests::greater_than_100’ panicked at \ ’Guess value must be greater than or equal to 1, got 200.’, src/lib.rs:14:13 note: Run with ‘RUST_BACKTRACE=1‘ for a backtrace. note: Panic did not include expected string \ ’Guess value must be less than or equal to 100’ Katsuki Kobayashi RustBook ษڧձ
  35. Using Result<T,E> (1/3) ͜͜·Ͱɺςετʹ panic! Λ࢖͖ͬͯͨ ςετʹ͸ Result<T, E> ΋࢖͑Δ

    ઌఔݟͨ it_works() ؔ਺Λ Result Ͱॻ͖׵͑ ੒ޭ࣌ʹ Ok(()) Λฦ͠ɺࣦഊ࣌ʹจݴΛؚΜͩ Err Λฦ͢ (Playground) 1 #[cfg(test)] 2 mod tests { 3 #[test] 4 fn it_works() -> Result<(), String> { 5 if 2 + 2 == 4 { 6 Ok(()) 7 } else { 8 Err(String::from("two␣plus␣two␣does␣not␣equal␣four")) 9 } 10 } 11 } Katsuki Kobayashi RustBook ษڧձ
  36. Using Result<T,E> (2/3) ग़ྗ test tests::it_works ... ok test result:

    ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out (௥ࢼ): 2 + 2 Λ 2 + 3 ͱͨ͠ΒҎԼͷΑ͏ʹ assert_eq! Έ͍ͨͳग़ྗ͕ͩ ࠨล͸ςετόΠφϦͷ݁Ռ (ඇ 0) ͷ஋Λҙຯ͍ͯ͠ Δ໛༷ ӈล͸੒ޭ࣌ͷ݁Ռ (0) Error: "two plus two does not equal four" thread ’tests::it_works’ panicked at \ ’assertion failed: ‘(left == right)‘ left: ‘1‘, right: ‘0‘: the test returned a termination value \ with a non-zero status code (1) which indicates a failure’, src/libtest/lib.rs Katsuki Kobayashi RustBook ษڧձ
  37. Controlling How Tests Are Run (1/2) cargo test ίϚϯυ ςετϞʔυͰίʔυΛίϯύΠϧ࣮͠ߦ

    σϑΥϧτͰ͸શͯͷςετΛύϥϨϧͰ࣮ߦ͠ɺ ࣮ߦதʹੜ੒͞Εͨग़ྗΛΩϟϓνϟ͢Δ ίϚϯυϥΠϯΦϓγϣϯͰڍಈΛมߋͰ͖Δ Φϓγϣϯ͸ 2 छྨ͋Δ cargo test ΁ͷΦϓγϣϯ ςετόΠφϦ΁ͷΦϓγϣϯ 2 छྨͷΦϓγϣϯ͸ηύϨʔλʔ ”-- (ϋΠ ϑϯ 2 ͭ)“ Ͱ෼ׂ͢Δ Katsuki Kobayashi RustBook ษڧձ
  38. Controlling How Tests Are Run (2/2) % cargo test --help

    | head cargo-test Execute all unit and integration tests of a local package USAGE: cargo test [OPTIONS] [TESTNAME] [-- <args>...] OPTIONS: --lib Test only this package’s library --bin <NAME>... Test only the specified binary --bins Test all binaries % cargo test -- --help | head Compiling hello v0.1.0 (/tmp/hello) Finished dev [unoptimized + debuginfo] target(s) in 0.59s Running target/debug/deps/hello-ef71f4ccd46d6561 Usage: --help [OPTIONS] [FILTER] Options: --include-ignored Run ignored and not ignored tests --ignored Run only ignored tests --test Run tests and not benchmarks --bench Run benchmarks instead of tests --list List all tests and benchmarks -h, --help Display this message (longer with --help) Katsuki Kobayashi RustBook ษڧձ
  39. Running Tests in Parallel or Conse...(1/2) σϑΥϧτͰ͸ෳ਺ͷςετΛεϨουͰฒ ྻ࣮ߦ͢Δ ϑΟʔυόοΫΛߴ଎ʹड͚औΕΔ ϫʔΫεϖʔεͷঢ়ଶ΍؀ڥม਺ʹґଘ͍ͯ͠ͳ

    ͍ඞཁ͕͋Δ ବ໨ͳྫ ͍͔ͭ͘ͷςετ͕ text-output.txt ʹσʔλΛॻ͘ ֤ςετ͕ϑΝΠϧͷσʔλͷ஋ʹΑͬͯ assert ͢Δ ବ໨ͳྫͷղܾํ๏ ϑΝΠϧ໊Λมߋ͢Δ ಉ࣌ʹ࣮ߦ͞Εͳ͍Α͏ʹ͢Δ Katsuki Kobayashi RustBook ษڧձ
  40. Showing Function Output(1/5) σϑΥϧτͰ͸ςετ͕ pass ͨ͠৔߹ඪ४ग़ ྗ͸ࣺͯΒΕΔ println!() Λ࢖ͬͨؔ਺Ͱͷྫ 1

    fn prints_and_returns_10(a: i32) -> i32 { 2 println!("I␣got␣the␣value␣{}", a); 3 10 4 } Katsuki Kobayashi RustBook ษڧձ
  41. Showing Function Output(2/5) ςετίʔυ (Playground) ͨͩ͠ɺPlayground Ͱ͸ίϚϯυϥΠϯΦϓγϣϯ͕౉ͤͳ͍ʜʜ! 1 #[cfg(test)] 2

    mod tests { 3 use super::*; 4 5 #[test] 6 fn this_test_will_pass() { 7 let value = prints_and_returns_10(4); 8 assert_eq!(10, value); 9 } 10 11 #[test] 12 fn this_test_will_fail() { 13 let value = prints_and_returns_10(8); 14 assert_eq!(5, value); 15 } 16 } Katsuki Kobayashi RustBook ษڧձ
  42. Showing Function Output(3/5) ςετ݁Ռ (Կ΋͚ͭͳ͍) pass ͨ͠ςετͷग़ྗ͸දࣔ͞Εͳ͍ 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 == r left: ‘5‘, right: ‘10‘’, src/lib.rs:20:9 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 Katsuki Kobayashi RustBook ษڧձ
  43. Showing Function Output(4/5) cargo test -- --nocapture Ͱ࣮ߦ ੒ޭ࣌ͷදࣔ΋ग़ྗ͞ΕΔ ςετग़ྗͱςετͷ݁Ռ͕ΠϯλϦʔϒ͞Εͯ

    ͠·͏ˡ ฒྻ࣮ߦ͢ΔͨΊ running 2 tests I got the value 8 thread ’I got the value 4 tests::this_test_will_fail’ panicked at ’assertion failed: ‘(left == right)‘ left: ‘5‘, right: ‘10‘’, src/lib.rs:20:9 note: Run with ‘RUST_BACKTRACE=1‘ environment variable to display a backtrace. test tests::this_test_will_pass ... ok test tests::this_test_will_fail ... FAILED failures: failures: tests::this_test_will_fail test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out Katsuki Kobayashi RustBook ษڧձ
  44. Showing Function Output(5/5) cargo test -- --test-threads=1 --nocapture Ͱ࣮ߦ running

    2 tests test tests::this_test_will_fail ... I got the value 8 thread ’main’ panicked at ’assertion failed: ‘(left == right)‘ left: ‘5‘, right: ‘10‘’, src/lib.rs:20:9 note: Run with ‘RUST_BACKTRACE=1‘ environment variable to display a backtrace. FAILED test tests::this_test_will_pass ... I got the value 4 ok failures: failures: tests::this_test_will_fail test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out Katsuki Kobayashi RustBook ษڧձ
  45. Running a Subset of Tests (1/5) શͯͷ test suite Λ࣮ߦ͢Δͱ௕͔͔࣌ؒΔ৔

    ߹͕͋Δ cargo test ʹ࣮ߦ͍ͨ͠ςετ໊ΛҾ਺ͱ͠ ͯ༩͑ΒΕΔ ྫͱͯ͠ add_two() ؔ਺ͷςετΛ 3 ͭॻ͘ Katsuki Kobayashi RustBook ษڧձ
  46. Running a Subset of Tests (2/5) (Playground) 1 #[cfg(test)] 2

    mod tests { 3 use super::*; 4 5 #[test] 6 fn add_two_and_two() { 7 assert_eq!(4, add_two(2)); 8 } 9 10 #[test] 11 fn add_three_and_two() { 12 assert_eq!(5, add_two(3)); 13 } 14 15 #[test] 16 fn one_hundred() { 17 assert_eq!(102, add_two(100)); 18 } 19 } Katsuki Kobayashi RustBook ษڧձ
  47. Running a Subset of Tests (3/5) ී௨ʹ cargo test running

    3 tests test tests::add_three_and_two ... ok test tests::add_two_and_two ... ok test tests::one_hundred ... ok test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out cargo test one_hundred 2 ͭͷςετ͕࣮ߦ͞Ε͍ͯͳ͍ࣄ͕දࣔ͞ΕΔ running 1 test test tests::one_hundred ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; \ 2 filtered out ^^^^^^^^^^^^^^ Katsuki Kobayashi RustBook ษڧձ
  48. Running a Subset of Tests (4/5) cargo test add ςετ໊ͷҰ෦͚ͩॻ͍ͯ΋Α͘ɺώοτͨ͠ς

    ετ͕࣮ߦ͞ΕΔ one_hundred ςετ͚࣮ͩߦ͞Εͳ͍ ςετ໊͸Ϟδϡʔϧ໊Ͱ΋ࢦఆͰ͖Δ cargo test e ͱ͔Ͱ΋શ෦͔͔Δ running 2 tests test tests::add_three_and_two ... ok test tests::add_two_and_two ... ok test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out Katsuki Kobayashi RustBook ษڧձ
  49. Running a Subset of Tests (5/5) ignore attribute --ignored ΦϓγϣϯΛ෇͚ͨͱ͖͚࣮ͩߦ

    1 #[test] 2 #[ignore] 3 fn expensive_test() { 4 // code that takes an hour to run 5 } % cargo test 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 ^^^^^^^^^ % cargo test -- --ignored running 1 test test expensive_test ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 1 filtered out Katsuki Kobayashi RustBook ษڧձ
  50. Test Organization ςετ͸ෳࡶ ਓʹΑͬͯ༻ޠ΍ߏ੒͕ҟͳΔ Rust ίϛϡχςΟʔͰೋͭͷΧςΰϦͷ໘Ͱ ςετΛߟ͑Δ unit test খ͍͞୯Ґ

    (Ϟδϡʔϧͱ͔) ͰϑΥʔΧεͯ͠ ϓϥΠϕʔτͳΠϯλʔϑΣʔε΋ςετ integration test ֎෦ͷίʔυ͕ϥΠϒϥϦΛ࢖͏Α͏ʹςετ ެ։ΠϯλʔϑΣʔεͷΈΛଞͷϞδϡʔϧͱҰ ॹʹ࣮ߦͯ͠ςετ ςετΛॻ͘͜ͱ͸ɺϥΠϒϥϦͷஅย͕ɺ ผʑʹɺҰॹʹɺظ଴௨Γʹಈ͘͜ͱΛ֬ೝ͢ ΔͨΊʹॏཁͰ͋Δ Katsuki Kobayashi RustBook ษڧձ
  51. Unit Tests (1/5) unit test ͷ໨త ίʔυͷ֤୯Ґ͕ଞͷίʔυ͔Β෼཭Ͱ͖͍ͯ Δ͔ Ͳͷ෦෼͕ਖ਼͘͠ಈ͍ͯɺͲͷ෦෼͕ਖ਼͘͠ಈ͍ ͍ͯͳ͍͔

    ׳शతʹ͸ src ҎԼͷ֤ϑΝΠϧͰ tests ͱ͍͏໊લͷϞ δϡʔϧΛ࡞੒ tests Ϟδϡʔϧ͸ςετؔ਺Λ࣋ͪɺ cfg(test) ͰΞϊςʔτ͞ΕΔ Katsuki Kobayashi RustBook ษڧձ
  52. Unit Tests (2/5) #[cfg(test)] ίϯύΠϥʹ cargo test ͰͷΈϏϧυ͢ΔΑ͏ ڭ͑Δ ίϯύΠϧ࣌ؒ΍ϑΝΠϧαΠζΛ཈͑Δ

    ޙͰ΍Δ integration test ͸ src ʹஔ͔ͳ͍͠ɺ #[cfg(test)] ΋෇͚ͳ͍ cargo new --lib Ͱੜ੒͞ΕΔίʔυʹ΋෇͍ ͯΔ (Playground) Ϟδϡʔϧதͷϔϧύʔؔ਺ʹ΋ద༻͞ΕΔ 1 #[cfg(test)] 2 mod tests { 3 #[test] 4 fn it_works() { 5 assert_eq!(2 + 2, 4); 6 } 7 } Katsuki Kobayashi RustBook ษڧձ
  53. Unit Tests (3/5) ϓϥΠϕʔτؔ਺Λ௚઀ςετ͢Δ͔൱͔ ٞ࿦͞Ε͍ͯΔ ଞͷݴޠͩͱɺ೉͔ͬͨ͠ΓɺෆՄೳͩͬͨΓ Rust ͷ privacy rule

    ͳΒͰ͖ͯ͠·͏ ϓϥΠϕʔτؔ਺ internal_adder() Ͱߟ ͑Δ 1 pub fn add_two(a: i32) -> i32 { 2 internal_adder(a, 2) 3 } 4 5 fn internal_adder(a: i32, b: i32) -> i32 { 6 a + b 7 } Katsuki Kobayashi RustBook ษڧձ
  54. Unit Tests (4/5) ςετຊମ internal_addr() Λ௚઀ίʔϧ (Playground) 1 #[cfg(test)] 2

    mod tests { 3 use super::*; 4 5 #[test] 6 fn internal() { 7 assert_eq!(4, internal_adder(2, 2)); 8 } 9 } Katsuki Kobayashi RustBook ษڧձ
  55. Unit Tests (5/5) internal_addr() ͸ pub ͕෇͍͍ͯͳ͍ tests ͸୯ʹผͷϞδϡʔϧͰ͋ΔͷͰ internal_addr()

    Λ tests ͷείʔϓʹ࣋ͬͯ ͍͚Δ running 1 test test tests::internal ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out ϓϥΠϕʔτؔ਺͸ςετ͠ͳ͍΂͖೿ͷํ ʹ΋ಛʹԿ΋ڧ͍·ͤΜ Katsuki Kobayashi RustBook ษڧձ
  56. Integration Tests (1/11) ϥΠϒϥϦͷެ։ API Λଞͷίʔυ͕࢖͏ͷͱ ಉ͡Α͏ʹςετ͢Δ ໨త͸ϥΠϒϥϦͷύʔπ͕ɺҰॹʹਖ਼͘͠ಈ͘ ͔Λςετ͢Δ͜ͱ ୯ମͰ͸ಈ࡞͢Δ͚Ͳ

    integrate ͞ΕΔͱ໰୊Λى ͜͢͜ͱ͸··͋Δ integrate ͞Εͨίʔυͷ test coverage ͸ॏཁ integration test ͷͨΊʹ͸ɺ·ͣ tests σΟϨ ΫτϦΛ࡞Δ Katsuki Kobayashi RustBook ษڧձ
  57. Integration Tests (2/11) tests σΟϨΫτϦ ϓϩδΣΫτͷҰ൪্ͷϨϕϧʹ࡞Δ (src ͱಉ͡ ֊૚) cargo

    ͕ͦ͜Λݟͯɺ֤ϑΝΠϧ͝ͱʹ crate Λ ࡞Δ ୯ମςετͷ src/lib.rs Λͪΐͬͱมߋ͠ ͯ tests/integration_test.rs ʹϦωʔϜ 1 use adder; 2 3 #[test] 4 fn internal() { 5 assert_eq!(4, adder::add_two(2)); 6 } Katsuki Kobayashi RustBook ษڧձ
  58. Integration Tests (3/11) 1 use adder; 2 3 #[test] 4

    fn internal() { 5 assert_eq!(4, adder::add_two(2)); 6 } Կ͕มΘͬͨ? use super::*; ͕ use adder; ʹ test ͕ผ crate Ͱ͋ΔͨΊ ϥΠϒϥϦ໊͸ adder ʹ͢Δ͜ͱ (1 ഊ) Cargo.toml ͷ name Λॻ͚͹ OK #cfg(test) ͕ͳ͍ tests σΟϨΫτϦʹஔ͍ͨ͜ͱͰ cargo ͕ͦͷΑ͏ ʹѻͬͯ͘ΕΔ Katsuki Kobayashi RustBook ษڧձ
  59. Integration Tests (3/11) 1 use adder; 2 3 #[test] 4

    fn internal() { 5 assert_eq!(4, adder::add_two(2)); 6 } Կ͕มΘͬͨ? use super::*; ͕ use adder; ʹ test ͕ผ crate Ͱ͋ΔͨΊ ϥΠϒϥϦ໊͸ adder ʹ͢Δ͜ͱ (1 ഊ) Cargo.toml ͷ name Λॻ͚͹ OK #cfg(test) ͕ͳ͍ tests σΟϨΫτϦʹஔ͍ͨ͜ͱͰ cargo ͕ͦͷΑ͏ ʹѻͬͯ͘ΕΔ Playground Ͱ͸Ͳ͏͠Α͏΋ͳ͍ orz Katsuki Kobayashi RustBook ษڧձ
  60. Integration Tests (4/11) % cargo test Finished dev [unoptimized +

    debuginfo] target(s) in 0.00s Running target/debug/deps/adder-1d0dfd1494bab5c6 running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Running target/debug/deps/integration_test-22e1bbc18e3cf744 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 Katsuki Kobayashi RustBook ษڧձ
  61. Integration Tests (5/11) ߲໨͕ 3 ͭදࣔ͞ΕΔ unit test: ͖͞΄Ͳ·Ͱͷ integration

    test doc test integration test ͸ Running target/debug/deps/integration_test-XXXXXX ͷߦ͔Β࢝·͍ͬͯΔ ͦͷޙɺ֤ςετͷ݁Ռ͕ग़ྗ͞Εɺ࠷ޙʹ summary ͕ग़ͯ͘Δ ͦͯ͠ doc test ͕ଓ͘ tests σΟϨΫτϦʹೖΕͨϑΝΠϧຖʹηΫγϣ ϯ͕Ͱ͖ͯ݁Ռදࣔ͞ΕΔ Katsuki Kobayashi RustBook ษڧձ
  62. Integration Tests (6/11) cargo test ΁ͷҾ਺ͰಛఆͷςετΛ࣮ߦ --test ΦϓγϣϯΛ cargo ʹ౉͢

    --test Λ͚ͭͳ͍ͱɺunit, integration, doc Ͱ֘౰ ͢Δؔ਺ͷΈ࣮ߦ͠ʹ͍͘ % cargo test --test integration_test Finished dev [unoptimized + debuginfo] target(s) in 0.00s Running target/debug/deps/integration_test-22e1bbc18e3cf744 running 1 test test it_adds_two ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Katsuki Kobayashi RustBook ษڧձ
  63. Integration Tests (7/11) ςετػೳ͝ͱʹϑΝΠϧΛ෼͚͍ͨ৔߹ tests σΟϨΫτϦͷ֤ϑΝΠϧ͸ͦΕͧΕผͷ crate ͱͯ͠ίϯύΠϧ͞ΕΔ ผͷ crate

    ͱͯ͠ѻ͏͜ͱʹ͍ͭͯ Ϣʔβʔ͕࣮ࡍʹ crate Λ࢖͏৔߹ʹ͍ۙঢ়ଶʹͳ ΔͷͰྑ͍ src ҎԼͷϑΝΠϧͱ͸ৼ෣͍Λڞ༗Ͱ͖ͳ͍ ϔϧύʔؔ਺͸ Chapt. 7 ͰߦͳͬͨΑ͏ʹڞ༗Ϟ δϡʔϧͱͯ͠ extract ͢Ε͹Α͍ Katsuki Kobayashi RustBook ษڧձ
  64. Integration Tests (8/11) ڞ༗ϞδϡʔϧԽͷྫ tests/common.rs Λͭ͘Δ #[test] Λ͚ͭͨؔ਺͕ͳ͍ͷͰ setup() ͸࣮

    ߦ͞Εͳ͍ 1 pub fn setup() { 2 // setup code specific to your library’s tests would go here 3 } % cargo test Compiling adder v0.1.0 (/home/rare/work/slides/RustBook/samples/integration Finished dev [unoptimized + debuginfo] target(s) in 0.52s Running target/debug/deps/adder-1d0dfd1494bab5c6 running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Running target/debug/deps/common-9c75c5df2f50cca9 running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Katsuki Kobayashi RustBook ษڧձ
  65. Integration Tests (9/11) ςετͷ݁Ռදࣔʹ͸ग़͖ͯͯ΄͘͠ͳ͍ ׳शతͳํ๏ͱͯ͠͸ tests/common.rs ⇒ tests/common/mod.rs ͱ͢Δ tests

    σΟϨΫτϦͷαϒσΟϨΫτϦ͸ίϯύ Πϧ͞Εͳ͍ (cargo build ͷ͸ͳ͠?) ͠ɺςε τ݁Ռʹ΋දࣔ͞Εͳ͍ % cargo test Finished dev [unoptimized + debuginfo] target(s) in 0.01s Running target/debug/deps/adder-1d0dfd1494bab5c6 running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Running target/debug/deps/integration_test-22e1bbc18e3cf744 running 1 test test it_adds_two ... ok test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Katsuki Kobayashi RustBook ษڧձ
  66. Integration Tests (10/11) setup() Λ࢖͏ʹ͸? ҎԼͷΑ͏ʹϞδϡʔϧͱͯ͠࢖͑͹Α͍ mod common; ͸ Chapt.

    7 ͷͱ͖ͱಉ͡ common::setup() ͰίʔϧͰ͖ΔΑ͏ʹͳΔ 1 use adder; 2 3 mod common; 4 5 #[test] 6 fn it_adds_two() { 7 common::setup(); 8 assert_eq!(4, adder::add_two(2)); 9 } Katsuki Kobayashi RustBook ษڧձ
  67. Integration Tests (11/11) src/main.rs ͚ͩ͋ͬͯ src/libs.rs ͕ແ ͍ binary crate

    ͷςετ͸? tests σΟϨΫτϦʹ integration test ͸࡞Εͳ͍ use Λ͔ͭͬͯ src/main.rs Ͱఆٛ͞Ε͍ͯΔ ؔ਺Λείʔϓʹ࣋ͬͯ͜ΒΕͳ͍ library crate ͔͠ଞͷ crate ͔Β͸࢖͑ͳ͍ Rust ͷϓϩδΣΫτͰ͸ src/main.rs ͔Β͸ src/lib.rs ʹ͋Δϩδο ΫΛ୯ʹίʔϧ͢Δ͚ͩʹ͢Δ ͜ͷߏ੒ͩͱॏཁͳػೳ͸ use Ͱ integration test ͢Δ͜ͱ͕Ͱ͖Δ src/main.rs ͸ϥΠϒϥϦ෦෼͕ਖ਼͘͠ಈ͚͹ಈ ͘Α͏ͳখ͍͞ίʔυʹ͓ͯ͘͠ Katsuki Kobayashi RustBook ษڧձ
  68. Summary (1/2) Rust ͷ test feature ظ଴௨Γʹίʔυ͕ಈ࡞͚ͭͮ͠ΔͨΊʹͲ͏ػ ೳ͢Δ΂͖͔Λࢦఆ͢Δํ๏Λఏڙ unit test

    ϥΠϒϥϦͷ֤ύʔπΛผʑʹςετͰ͖Δ private ͳ࣮૷ͷςετ͕Ͱ͖Δ integration test ϥΠϒϥϦͷଟ͘ͷύʔπ͕Ұॹʹਖ਼͘͠ಈ͔͘ ςετͰ͖Δ ϥΠϒϥϦͷެ։ API Λ࣮ࡍʹ࢖ΘΕΔͷͱಉ͡ ํ๏ͰςετͰ͖Δ Katsuki Kobayashi RustBook ษڧձ