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

プリントデバッグを失敗させないテクニック

 プリントデバッグを失敗させないテクニック

UV Study : Rust LT会 ~新米Rustaceanたちへ~ (https://uniquevision.connpass.com/event/316789/) にて発表した資料です。

Kentaro Matsumoto

May 13, 2024
Tweet

More Decks by Kentaro Matsumoto

Other Decks in Programming

Transcript

  1. © 2024 estie Inc. matsu7874 SWE @ estie • ソフトウェアエンジニア

    • 技術広報も担当 • estieという不動産業界向けのシステムを開発する ITスタートアップ企業で働いています。 • 『実践Rustプログラミング⼊⾨』(2020) 共著 ⾃⼰紹介 2
  2. © 2024 estie Inc. println!は標準出⼒、eprintln!とdbg!は標準エラー fn main() { println!("Hello, stdout!");

    //=> Hello, stdout! eprintln!("Hello, stderr!"); //=> Hello, stderr! dbg!("Hello, dbg!"); //=> [src/bin/01.rs:4:5] "Hello, dbg!" = "Hello, dbg!" } println! eprintln! dbg! 4
  3. © 2024 estie Inc. {}で変数の中⾝も表⽰できる、が、エラーになるものもある let x = 1; println!("{}",

    x); //=> 1 let v = vec![1, 2, 3]; println!("{}", v); println! eprintln! dbg! 5 error[E0277]: `Vec<{integer}>` doesn't implement `std::fmt::Display` --> src/bin/02.rs:5:20 | 5 | println!("{}", v); | ^ `Vec<{integer}>` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `Vec<{integer}>` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
  4. © 2024 estie Inc. {:?}でデバッグ表⽰, {:#?}でpretty-print let v = vec![1,

    2, 3]; println!("{:?}", v); //=> [1, 2, 3] println!("{:#?}", v); //=> [ // 1, // 2, // 3 // ] println! eprintln! dbg! 6
  5. © 2024 estie Inc. ⾃分で定義したstructも{:?}できないのですか︖ struct MyS { x: usize,

    } fn main() { let my_s = MyS { x: 12 }; println!("{:?}", my_s); } DebugとDisplay 8 error[E0277]: `MyS` doesn't implement `Debug` --> src/bin/04.rs:7:22 | 7 | println!("{:?}", my_s); | ^^^^ `MyS` cannot be formatted using `{:?}` | = help: the trait `Debug` is not implemented for `MyS` = note: add `#[derive(Debug)]` to `MyS` or manually `impl Debug for MyS` help: consider annotating `MyS` with `#[derive(Debug)]` | 1 + #[derive(Debug)] 2 | struct MyS { |
  6. © 2024 estie Inc. #[derive(Debug)]アトリビュートをつけると表⽰できる #[derive(Debug)] struct MyS { x:

    usize, } fn main() { let my_s = MyS { x: 12 }; println!("{:?}", my_s); //=> MyS { x: 12 } } DebugとDisplay 9
  7. © 2024 estie Inc. 各フィールドがDebugを実装していれば structは要素のDebugを使える #[derive(Debug)] struct MyS {

    x: usize, } #[derive(Debug)] struct MyWrapper { my_s: MyS, } DebugとDisplay 10 fn main() { let my_s = MyS { x: 12 }; println!("{:?}", my_s); //=> MyS { x: 12 } let my_w = MyWrapper { my_s }; println!("{:?}", my_w); //=> MyWrapper { my_s: MyS { x: 12 } } }
  8. © 2024 estie Inc. ⾃由に整形したいときはtrait Displayを実装する #[derive(Debug)] struct Restaurant {

    name: String, location: String, rating: usize, } impl std::fmt::Display for Restaurant { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f,"{}({}): {}", self.name, self.location, "★".repeat(self.rating) ) } } DebugとDisplay 11 let r = Restaurant { name: "Diner matsu7874".to_string(), location: "Tokyo".to_string(), rating: 5, }; println!("{:?}", r); //=> Restaurant { name: "Diner matsu7874", location: "Tokyo", rating: 5 } println!("{}", r); //=> Diner matsu7874(Tokyo): ★★★★★
  9. © 2024 estie Inc. dbg!や{:?}で表⽰するためにはstd::fmt::Debugが必要 {}で表⽰するためにはstd::fmt::Displayの実装が必要 DebugとDisplay 12 #[derive(Debug)] struct

    struct名{} impl std::fmt::Display for struct名 { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f,"ここに好きな表⽰形式", /*値を表⽰する場合はここに値を書く*/) } }
  10. © 2024 estie Inc. 成功したテストコードの出⼒は基本的に表⽰されない test tests::test_div ... ok pub

    fn div(n: u32, d: u32) -> Option<(u32, u32)> { if d == 0 { return None; } let mut answer = 0; let mut n = n; while n >= d { n -= d; answer += 1; eprintln!("n={}, answer={}", n, answer); } Some((answer, n)) } 特殊な環境でのプリントデバッグ 14 #[cfg(test)] mod tests { use super::div; #[test] fn test_div() { let actual = div(10, 3); eprintln!("actual={:?}", actual); let expected = Some((3, 1)); assert_eq!(actual, expected); } }
  11. © 2024 estie Inc. 失敗しているテストコードの出⼒は表⽰される pub fn div(n: u32, d:

    u32) -> Option<(u32, u32)> { Some((0, 0)) } #[cfg(test)] mod tests { #[test] fn test_div() { let actual = super::div(10, 3); eprintln!("actual={:?}", actual); let expected = Some((3, 1)); assert_eq!(actual, expected); } } 特殊な環境でのプリントデバッグ 15 test tests::test_div ... FAILED failures: ---- tests::test_div stdout ---- actual=Some((0, 0)) thread 'tests::test_div' panicked at src/bin/07.rs:24:9: assertion `left == right` failed left: Some((0, 0)) right: Some((3, 1))
  12. © 2024 estie Inc. cargo test -- --nocapture で実⾏すると表⽰される $

    cargo test -- --nocapture running 1 test n=7, answer=1 n=4, answer=2 n=1, answer=3 actual=Some((3, 1)) test tests::test_div ... ok 特殊な環境でのプリントデバッグ 16 pub fn div(n: u32, d: u32) -> Option<(u32, u32)> { if d == 0 { return None; } let mut answer = 0; let mut n = n; while n >= d { n -= d; answer += 1; eprintln!("n={}, answer={}", n, answer); } Some((answer, n)) }
  13. © 2024 estie Inc. ビルドスクリプトのbuild.rsの出⼒も基本的に表⽰されない // build.rs fn main() {

    println!("build.rs println"); eprintln!("build.rs eprintln"); println!("cargo:rustc-env=FROM_BUILD_RS_ENV_A=TRUE"); println!("cargo:rustc-env=FROM_BUILD_RS_ENV_B=FALSE"); eprintln!("cargo:rustc-env=FROM_BUILD_RS_ENV_C=FALSE"); } 特殊な環境でのプリントデバッグ 17 [package] name = "print-debug-tutorial" version = "0.1.0" edition = "2021" build = "build.rs"
  14. © 2024 estie Inc. build.rsの出⼒は –vvをつけると表⽰できる $ cargo build –vv

    ...省略 [print-debug-tutorial 0.1.0] build.rs eprintln [print-debug-tutorial 0.1.0] cargo:rustc-env=FROM_BUILD_RS_ENV_C=FALSE [print-debug-tutorial 0.1.0] build.rs println [print-debug-tutorial 0.1.0] cargo:rustc-env=FROM_BUILD_RS_ENV_A=TRUE [print-debug-tutorial 0.1.0] cargo:rustc-env=FROM_BUILD_RS_ENV_B=FALSE ...省略 特殊な環境でのプリントデバッグ 18