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

標準パッケージにおけるテストでの利用例から学ぶ testing / quick パッ...

標準パッケージにおけるテストでの利用例から学ぶ testing / quick パッケージ/golang-testing-quick

Go Conference 2019 Spring の発表資料
https://gocon.jp/

Yusuke Hosonuma

May 18, 2019
Tweet

More Decks by Yusuke Hosonuma

Other Decks in Programming

Transcript

  1. ॴଐ • 48&5άϧʔϓˏ%F/" • ςετࣗಈԽνʔϜɿJ04(Pݴޠ ޷͖ͳ΋ͷ • ݴޠɿ4XJGUɺ)BTLFMMɺ-JTQʢʁʣ • झຯɿɺαΠΫϦϯάɺొࢁ

    ίϛϡχςΟ • ϖϯΪϯଜ ۙگ • USZ4XJGU50,:0Ͱొஃ Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 3 ෼τʔΫ :VTVLF)PTPOVNB!UPCJʢͱͼʣ
  2. 8 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. (PݴޠͷύοέʔδҰཡ IUUQTHPMBOHPSHQLH

    ʮϒϥοΫϘοΫεςετʯͷͨΊͷ6UJMJUZΛఏڙ ୺తʹݴͬͯ͠·͑͹ɺ ʮϥϯμϜ஋ʯΛ࢖ͬͨςετ
  3. 12 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 0 ʴ

    1 ʹ 1 1 ʴ 1 ʹ 2 ௨ৗͷςετ ೖྗ஋
  4. 13 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 0 ʴ

    1 ʹ 1 1 ʴ 1 ʹ 2 ௨ৗͷςετ ೖྗ஋ ظ଴஋
  5. 14 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 1 ʴ

    0 ʹ 1 1 ʴ 1 ʹ 2 ௨ৗͷςετ ೖྗ஋ ظ଴஋ ໌֬ͳೖྗ஋ͱظ଴஋Λ ༩͑ͯݕূ͢Δ
  6. 15 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ௨ৗͷςετ import

    "testing" func TestAdd(t *testing.T) { tests := []struct { x int y int want int }{ {x: 0, y: 1, want: 1}, // 0 + 1 = 1 {x: 1, y: 1, want: 2}, // 1 + 1 = 2 } for _, tt := range tests { if got := Add(tt.x, tt.y); got != tt.want { t.Errorf("Add() = %v, want %v", got, tt.want) } } }
  7. 16 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ௨ৗͷςετ import

    "testing" func TestAdd(t *testing.T) { tests := []struct { x int y int want int }{ {x: 0, y: 1, want: 1}, // 0 + 1 = 1 {x: 1, y: 1, want: 2}, // 1 + 1 = 2 } for _, tt := range tests { if got := Add(tt.x, tt.y); got != tt.want { t.Errorf("Add() = %v, want %v", got, tt.want) } } } ໌֬ͳʮೖྗ஋ʯͱʮظ଴஋ʯΛ༩͑Δ
  8. 18 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. x ʴ

    y ʹ z y ʴ x ʹ z’ ϥϯμϜςετ
  9. 19 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. x ʴ

    y ʹ z y ʴ x ʹ z’ ϥϯμϜςετ ೖྗ஋ YͱZΛϥϯμϜʹੜ੒
  10. 20 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. x ʴ

    y ʹ z y ʴ x ʹ z’ ϥϯμϜςετ ೖྗ஋ ଍͠ࢉ͸ަ׵๏ଇΛຬͨ͢ͷͰ [ͱ[`͸ৗʹҰக͢Δ
  11. 21 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. x ʴ

    y ʹ z y ʴ x ʹ z’ ϥϯμϜςετ ೖྗ஋ ଍͠ࢉ͸ަ׵๏ଇΛຬͨ͢ͷͰ [ͱ[`͸ৗʹҰக͢Δ ϥϯμϜ஋ʹରͯ͠ ຬͨ͢΂͖ੑ࣭Λݕূ͢Δ
  12. 22 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ϥϯμϜςετ import

    ( "testing" "testing/quick" ) func TestAddQuick(t *testing.T) { f := func(x, y int) bool { return Add(x, y) == Add(y, x) } if err := quick.Check(f, nil); err != nil { t.Error(err.Error()) } }
  13. 23 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ϥϯμϜςετ import

    ( "testing" "testing/quick" ) func TestAddQuick(t *testing.T) { f := func(x, y int) bool { return Add(x, y) == Add(y, x) } if err := quick.Check(f, nil); err != nil { t.Error(err.Error()) } } UFTUJOHRVJDLΛJNQPSU
  14. 24 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ϥϯμϜςετ import

    ( “testing" "testing/quick" ) func TestAddQuick(t *testing.T) { f := func(x, y int) bool { return Add(x, y) == Add(y, x) } if err := quick.Check(f, nil); err != nil { t.Error(err.Error()) } } νΣοΫ༻ͷϔϧύʔؔ਺ ϥϯμϜͳೖྗ஋͕ೖͬͯ͘Δ૝ఆ
  15. 25 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ϥϯμϜςετ import

    ( "testing" "testing/quick" ) func TestAddQuick(t *testing.T) { f := func(x, y int) bool { return Add(x, y) == Add(y, x) } if err := quick.Check(f, nil); err != nil { t.Error(err.Error()) } } ަ׵๏ଇΛຬͨͤ͹USVF
  16. 26 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ϥϯμϜςετ import

    ( "testing" "testing/quick" ) func TestAddQuick(t *testing.T) { f := func(x, y int) bool { return Add(x, y) == Add(y, x) } if err := quick.Check(f, nil); err != nil { t.Error(err.Error()) } } ؔ਺͕ৗʹUSVFΛฦ͔͢ςετ
  17. 27 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ϥϯμϜςετ import

    ( "testing" "testing/quick" ) func TestAddQuick(t *testing.T) { f := func(x, y int) bool { return Add(x, y) == Add(y, x) } if err := quick.Check(f, nil); err != nil { t.Error(err.Error()) } } USVFΛฦ͞ͳ͍৔߹͸&SSPS͕ฦ٫
  18. 29 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ࣦഊ͢Δέʔε func

    Add(x, y int) int { return x - y } // ίϯιʔϧग़ྗ --- FAIL: TestAddQuick (0.00s) #1: failed on input -8046014121776288896, -2929560796466791850
  19. 30 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ࣦഊ͢Δέʔε func

    Add(x, y int) int { return x - y } // ίϯιʔϧग़ྗ --- FAIL: TestAddQuick (0.00s) #1: failed on input -8046014121776288896, -2929560796466791850 ަ׵๏ଇΛຬͨ͞ͳ͍ʮҾ͖ࢉʯ
  20. 31 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ࣦഊ͢Δέʔε func

    Add(x, y int) int { return x - y } // ίϯιʔϧग़ྗ --- FAIL: TestAddQuick (0.00s) #1: failed on input -8046014121776288896, -2929560796466791850 Y Z
  21. 32 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ࣦഊ͢Δέʔε func

    Add(x, y int) int { return x - y } // ίϯιʔϧग़ྗ --- FAIL: TestAddQuick (0.00s) #1: failed on input -8046014121776288896, -2929560796466791850 Y Z ͜ΕΒͷ஋ͷ৔߹ʹࣦഊͨ͠ͱ͍͏ใࠂ
  22. 34 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ༻ޠͷ੔ཧ •

    &YBNQMFCBTFE5FTU ⁃ ໌֬ͳೖྗ஋ͱظ଴஋Λ༩͑Δςετ
  23. 35 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ༻ޠͷ੔ཧ •

    &YBNQMFCBTFE5FTU ⁃ ໌֬ͳೖྗ஋ͱظ଴஋Λ༩͑Δςετ • 1SPQFSUZCBTFE5FTU ⁃ ϥϯμϜ஋ʹج͍ͮͨςετ ⁃ ຬͨ͢΂͖ੑ࣭ʢQSPQFSUZʣΛݕূ ⁃ )BTLFMMͷ2VJDL$IFDL͕ൃ঵
  24. 36 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ༻ޠͷ੔ཧ •

    &YBNQMFCBTFE5FTU ⁃ ໌֬ͳೖྗ஋ͱظ଴஋Λ༩͑Δςετ • 1SPQFSUZCBTFE5FTU ⁃ ϥϯμϜ஋ʹج͍ͮͨςετ ⁃ ຬͨ͢΂͖ੑ࣭ʢQSPQFSUZʣΛݕূ ⁃ )BTLFMMͷ2VJDL$IFDL͕ൃ঵ ʢͨͿΜʣRVJDLͱ͍͏໋໊͸͔͜͜Β
  25. 39 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ᶃ ໌നͳ࣮૷ͱͷൺֱ

    • ໌നͳ࣮૷ • ͍͍ͨͯͷ৔߹ɺ஗͍ • ྫɿϑΟϘφον਺ྻΛ࠶ؼͰղ͘ • ͦ͏Ͱͳ͍࣮૷ • ͍͍ͨͯͷ৔߹ɺෳࡶ • ྫɿϑΟϘφον਺ྻΛ຤ඌ࠶ؼͰղ͘
  26. 40 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ᶃ ໌നͳ࣮૷ͱͷൺֱ

    • ໌നͳ࣮૷ • ͍͍ͨͯͷ৔߹ɺ஗͍ • ྫɿϑΟϘφον਺ྻΛ࠶ؼͰղ͘ • ͦ͏Ͱͳ͍࣮૷ • ͍͍ͨͯͷ৔߹ɺෳࡶ • ྫɿϑΟϘφον਺ྻΛ຤ඌ࠶ؼͰղ͘ ͲͪΒ΋ಉ͡ೖྗʹରͯ͠͸ ඞͣಉ݁͡ՌΛฦ͢͸ͣ
  27. 42 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. $POTUBOU5JNF#ZUF&Rؔ਺ //

    ConstantTimeByteEq returns 1 if x == y and 0 otherwise. func ConstantTimeByteEq(x, y uint8) int { return int((uint32(x^y) - 1) >> 31) } ςετର৅
  28. 43 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. $POTUBOU5JNF#ZUF&Rؔ਺ //

    ConstantTimeByteEq returns 1 if x == y and 0 otherwise. func ConstantTimeByteEq(x, y uint8) int { return int((uint32(x^y) - 1) >> 31) } YͱZΛఆ਺࣌ؒͰൺֱ͢Δ Ұக͢Ε͹ɺҰக͠ͳ͚Ε͹Λฦ͢ ςετର৅
  29. 44 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. $POTUBOU5JNF#ZUF&Rؔ਺ func

    byteEq(a, b uint8) int { if a == b { return 1 } return 0 } func TestConstantTimeByteEq(t *testing.T) { err := quick.CheckEqual(ConstantTimeByteEq, byteEq, nil) if err != nil { t.Error(err) } } ςετίʔυ
  30. 45 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. $POTUBOU5JNF#ZUF&Rؔ਺ func

    byteEq(a, b uint8) int { if a == b { return 1 } return 0 } func TestConstantTimeByteEq(t *testing.T) { err := quick.CheckEqual(ConstantTimeByteEq, byteEq, nil) if err != nil { t.Error(err) } } ఆ਺࣌ؒͰ͸ͳ͍໌നͳൺֱؔ਺ ςετίʔυ
  31. 46 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. $POTUBOU5JNF#ZUF&Rؔ਺ func

    byteEq(a, b uint8) int { if a == b { return 1 } return 0 } func TestConstantTimeByteEq(t *testing.T) { err := quick.CheckEqual(ConstantTimeByteEq, byteEq, nil) if err != nil { t.Error(err) } } ςετ༻ͷؔ਺ ςετίʔυ
  32. 47 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. $POTUBOU5JNF#ZUF&Rؔ਺ func

    byteEq(a, b uint8) int { if a == b { return 1 } return 0 } func TestConstantTimeByteEq(t *testing.T) { err := quick.CheckEqual(ConstantTimeByteEq, byteEq, nil) if err != nil { t.Error(err) } } ͭͷؔ਺ʹ͍ͭͯಉ݁͡ՌΛฦ͢͜ͱ ςετର৅ ໌നͳ࣮૷ ςετίʔυ
  33. 48 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. $POTUBOU5JNF#ZUF&Rؔ਺ func

    byteEq(a, b uint8) int { if a == b { return 1 } return 0 } func TestConstantTimeByteEq(t *testing.T) { err := quick.CheckEqual(ConstantTimeByteEq, byteEq, nil) if err != nil { t.Error(err) } } ͭͷؔ਺ʹ͍ͭͯಉ݁͡ՌΛฦ͢͜ͱ ςετର৅ ໌നͳ࣮૷ ಉ͡࢓༷ʢͷ͸ͣʣͷؔ਺Ͱ͋Ε͹ CheckEqualؔ਺ͰಉҰੑΛݕূͰ͖Δ ৽چͷΞϧΰϦζϜൺֱʹ΋࢖͑Δ
  34. 50 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ᶄ Fuzz

    ςετ • 'V[[ςετ • ༧ଌෆՄೳͳೖྗσʔλʢGV[[ʣΛ༩͑ɺ
 ෆ۩߹͕ൃੜ͢Δέʔε͕ແ͍͔୳͢
  35. 51 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ᶄ Fuzz

    ςετ • 'V[[ςετ • ༧ଌෆՄೳͳೖྗσʔλʢGV[[ʣΛ༩͑ɺ
 ෆ۩߹͕ൃੜ͢Δέʔε͕ແ͍͔୳͢ ϥϯμϜͳ Fuzz ςετ͸ ࣮֬Ͱ͸ͳ͍͕҆৺ײʹͭͳ͕Δ
  36. 53 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. &ODPEFؔ਺ //

    A Block represents a PEM encoded structure. // // The encoded form is: // -----BEGIN Type----- // Headers // base64-encoded Bytes // -----END Type—— // where Headers is a possibly empty sequence of Key: Value lines. type Block struct { Type string Headers map[string]string Bytes []byte } // Encode writes the PEM encoding of b to out. func Encode(out io.Writer, b *Block) error { } ςετର৅
  37. 54 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. &ODPEFؔ਺ //

    A Block represents a PEM encoded structure. // // The encoded form is: // -----BEGIN Type----- // Headers // base64-encoded Bytes // -----END Type----- // where Headers is a possibly empty sequence of Key: Value lines. type Block struct { Type string Headers map[string]string Bytes []byte } // Encode writes the PEM encoding of b to out. func Encode(out io.Writer, b *Block) error { } 1&.ܗࣜͷσʔλߏ଄ ςετର৅
  38. 55 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. &ODPEFؔ਺ //

    A Block represents a PEM encoded structure. // // The encoded form is: // -----BEGIN Type----- // Headers // base64-encoded Bytes // -----END Type----- // where Headers is a possibly empty sequence of Key: Value lines. type Block struct { Type string Headers map[string]string Bytes []byte } // Encode writes the PEM encoding of b to out. func Encode(out io.Writer, b *Block) error { } Τϯίʔυ༻ͷؔ਺ ςετର৅
  39. 56 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. &ODPEFؔ਺ func

    TestFuzz(t *testing.T) { testRoundtrip := func(block Block) bool { var buf bytes.Buffer if err := Encode(&buf, &block); err != nil { t.Errorf("Encode of %#v resulted in error: %s", &block, err) return false } decoded, rest := Decode(buf.Bytes()) if !reflect.DeepEqual(decoded, &block) { t.Errorf("Encode of %#v decoded as %#v", &block, decoded) return false } return true } quick.Check(testRoundtrip, nil) } ςετίʔυ
  40. 57 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. &ODPEFؔ਺ func

    TestFuzz(t *testing.T) { testRoundtrip := func(block Block) bool { var buf bytes.Buffer if err := Encode(&buf, &block); err != nil { t.Errorf("Encode of %#v resulted in error: %s", &block, err) return false } decoded, rest := Decode(buf.Bytes()) if !reflect.DeepEqual(decoded, &block) { t.Errorf("Encode of %#v decoded as %#v", &block, decoded) return false } return true } quick.Check(testRoundtrip, nil) } ςετ༻ͷؔ਺ ςετίʔυ
  41. 58 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. &ODPEFؔ਺ func

    TestFuzz(t *testing.T) { testRoundtrip := func(block Block) bool { var buf bytes.Buffer if err := Encode(&buf, &block); err != nil { t.Errorf("Encode of %#v resulted in error: %s", &block, err) return false } decoded, rest := Decode(buf.Bytes()) if !reflect.DeepEqual(decoded, &block) { t.Errorf("Encode of %#v decoded as %#v", &block, decoded) return false } return true } quick.Check(testRoundtrip, nil) } ೚ҙͷσʔλͰΤϯίʔυʹࣦഊ͠ͳ͍͜ͱ ςετίʔυ
  42. 59 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. &ODPEFؔ਺ func

    TestFuzz(t *testing.T) { testRoundtrip := func(block Block) bool { var buf bytes.Buffer if err := Encode(&buf, &block); err != nil { t.Errorf("Encode of %#v resulted in error: %s", &block, err) return false } decoded, rest := Decode(buf.Bytes()) if !reflect.DeepEqual(decoded, &block) { t.Errorf("Encode of %#v decoded as %#v", &block, decoded) return false } return true } quick.Check(testRoundtrip, nil) } σίʔυͨ͠ΒݩͱҰக͢Δ͜ͱ Τϯίʔυɾσίʔυͨ݁͠Ռ ݩσʔλ ςετίʔυ
  43. 60 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. &ODPEFؔ਺ func

    TestFuzz(t *testing.T) { testRoundtrip := func(block Block) bool { var buf bytes.Buffer if err := Encode(&buf, &block); err != nil { t.Errorf("Encode of %#v resulted in error: %s", &block, err) return false } decoded, rest := Decode(buf.Bytes()) if !reflect.DeepEqual(decoded, &block) { t.Errorf("Encode of %#v decoded as %#v", &block, decoded) return false } return true } quick.Check(testRoundtrip, nil) } σίʔυͨ͠ΒݩͱҰக͢Δ͜ͱ Τϯίʔυɾσίʔυͨ݁͠Ռ ݩσʔλ ϥϯμϜͳೖྗ஋Ͱ΋ຬͨ͢΂͖ੑ࣭Λ ςετίʔυͱͯ͠هड़Ͱ͖Δ ࠓճ͸ ɾΤϥʔʹͳΒͳ͍͜ͱ ɾΤϯίʔυɾσίʔυͨ͠Βݩʹ໭Δ͜ͱ
  44. 62 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ·ͱΊ •

    UFTUJOHRVJDL͸ϥϯμϜ஋ʹΑΔςετ • 1SPQFSUZCBTFE5FTUJOHͱ΋ݴΘΕΔ • (Pඪ४ύοέʔδͷςετͰ΋࢖ΘΕ͍ͯΔ ᶃ໌നͳ࣮૷ͱͷൺֱ ᶄ'V[[ςετ গͳ͍͚Ͳ
  45. 63 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ·ͱΊ •

    UFTUJOHRVJDL͸ϥϯμϜ஋ʹΑΔςετ • 1SPQFSUZCBTFE5FTUJOHͱ΋ݴΘΕΔ • (Pඪ४ύοέʔδͷςετͰ΋࢖ΘΕ͍ͯΔ ᶃ໌നͳ࣮૷ͱͷൺֱ ᶄ'V[[ςετ গͳ͍͚Ͳ ར༻γʔϯ͸ଟ͘ͳ͍͕ɺ దࡐదॴͰ࢖͑͹༗ޮͳख๏Ͱ͸ʁ ߟ͑ํͱ͓֮ͯ͑ͯ͘͠ͷ΋༗ޮ