Share
Embed
標準パッケージにおけるテストでの利用例から学ぶ testing / quick パッケージ/golang-testing-quick
Go Conference 2019 Spring の発表資料
https://gocon.jp/
Yusuke Hosonuma
May 18, 2019
Transcript
64 slides
-
Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ඪ४ύοέʔδʹ͓͚Δ ςετͰͷར༻ྫ͔ΒֶͿ UFTUJOHRVJDLύοέʔδ
1 Go Conference 2019 Spring 2019/5/18ʢSatʣ ࡉপ ༞հ@DeNA -
ॴଐ • 48&5άϧʔϓˏ%F/" • ςετࣗಈԽνʔϜɿJ04(Pݴޠ ͖ͳͷ • ݴޠɿ4XJGUɺ)BTLFMMɺ-JTQʢʁʣ • झຯɿɺαΠΫϦϯάɺొࢁ
ίϛϡχςΟ • ϖϯΪϯଜ ۙگ • USZ4XJGU50,:0Ͱొஃ Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 3 τʔΫ :VTVLF)PTPOVNB!UPCJʢͱͼʣ -
7 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. (PݴޠͷύοέʔδҰཡ IUUQTHPMBOHPSHQLH
ʮϒϥοΫϘοΫεςετʯͷͨΊͷ6UJMJUZΛఏڙ -
8 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. (PݴޠͷύοέʔδҰཡ IUUQTHPMBOHPSHQLH
ʮϒϥοΫϘοΫεςετʯͷͨΊͷ6UJMJUZΛఏڙ తʹݴͬͯ͠·͑ɺ ʮϥϯμϜʯΛͬͨςετ -
11 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 0 ʴ
1 ʹ 1 1 ʴ 1 ʹ 2 ௨ৗͷςετ -
12 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 0 ʴ
1 ʹ 1 1 ʴ 1 ʹ 2 ௨ৗͷςετ ೖྗ -
13 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 0 ʴ
1 ʹ 1 1 ʴ 1 ʹ 2 ௨ৗͷςετ ೖྗ ظ -
14 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. 1 ʴ
0 ʹ 1 1 ʴ 1 ʹ 2 ௨ৗͷςετ ೖྗ ظ ໌֬ͳೖྗͱظΛ ༩͑ͯݕূ͢Δ -
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) } } } -
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) } } } ໌֬ͳʮೖྗʯͱʮظʯΛ༩͑Δ -
18 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. x ʴ
y ʹ z y ʴ x ʹ z’ ϥϯμϜςετ -
19 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. x ʴ
y ʹ z y ʴ x ʹ z’ ϥϯμϜςετ ೖྗ YͱZΛϥϯμϜʹੜ -
20 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. x ʴ
y ʹ z y ʴ x ʹ z’ ϥϯμϜςετ ೖྗ ͠ࢉަ๏ଇΛຬͨ͢ͷͰ [ͱ[`ৗʹҰக͢Δ -
21 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. x ʴ
y ʹ z y ʴ x ʹ z’ ϥϯμϜςετ ೖྗ ͠ࢉަ๏ଇΛຬͨ͢ͷͰ [ͱ[`ৗʹҰக͢Δ ϥϯμϜʹରͯ͠ ຬ͖ͨ͢ੑ࣭Λݕূ͢Δ -
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()) } } -
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 -
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()) } } νΣοΫ༻ͷϔϧύʔؔ ϥϯμϜͳೖྗ͕ೖͬͯ͘Δఆ -
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 -
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Λฦ͔͢ςετ -
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͕ฦ٫ -
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 -
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 ަ๏ଇΛຬͨ͞ͳ͍ʮҾ͖ࢉʯ -
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 -
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 ͜ΕΒͷͷ߹ʹࣦഊͨ͠ͱ͍͏ใࠂ -
34 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ༻ޠͷཧ •
&YBNQMFCBTFE5FTU ⁃ ໌֬ͳೖྗͱظΛ༩͑Δςετ -
35 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ༻ޠͷཧ •
&YBNQMFCBTFE5FTU ⁃ ໌֬ͳೖྗͱظΛ༩͑Δςετ • 1SPQFSUZCBTFE5FTU ⁃ ϥϯμϜʹج͍ͮͨςετ ⁃ ຬ͖ͨ͢ੑ࣭ʢQSPQFSUZʣΛݕূ ⁃ )BTLFMMͷ2VJDL$IFDL͕ൃ -
36 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ༻ޠͷཧ •
&YBNQMFCBTFE5FTU ⁃ ໌֬ͳೖྗͱظΛ༩͑Δςετ • 1SPQFSUZCBTFE5FTU ⁃ ϥϯμϜʹج͍ͮͨςετ ⁃ ຬ͖ͨ͢ੑ࣭ʢQSPQFSUZʣΛݕূ ⁃ )BTLFMMͷ2VJDL$IFDL͕ൃ ʢͨͿΜʣRVJDLͱ͍͏໋໊͔͜͜Β -
39 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ᶃ ໌നͳ࣮ͱͷൺֱ
• ໌നͳ࣮ • ͍͍ͨͯͷ߹ɺ͍ • ྫɿϑΟϘφονྻΛ࠶ؼͰղ͘ • ͦ͏Ͱͳ͍࣮ • ͍͍ͨͯͷ߹ɺෳࡶ • ྫɿϑΟϘφονྻΛඌ࠶ؼͰղ͘ -
40 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ᶃ ໌നͳ࣮ͱͷൺֱ
• ໌നͳ࣮ • ͍͍ͨͯͷ߹ɺ͍ • ྫɿϑΟϘφονྻΛ࠶ؼͰղ͘ • ͦ͏Ͱͳ͍࣮ • ͍͍ͨͯͷ߹ɺෳࡶ • ྫɿϑΟϘφονྻΛඌ࠶ؼͰղ͘ ͲͪΒಉ͡ೖྗʹରͯ͠ ඞͣಉ݁͡ՌΛฦͣ͢ -
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) } ςετର -
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Λఆ࣌ؒͰൺֱ͢Δ Ұக͢ΕɺҰக͠ͳ͚ΕΛฦ͢ ςετର -
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) } } ςετίʔυ -
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) } } ఆ࣌ؒͰͳ͍໌നͳൺֱؔ ςετίʔυ -
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) } } ςετ༻ͷؔ ςετίʔυ -
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) } } ͭͷؔʹ͍ͭͯಉ݁͡ՌΛฦ͢͜ͱ ςετର ໌നͳ࣮ ςετίʔυ -
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ؔͰಉҰੑΛݕূͰ͖Δ ৽چͷΞϧΰϦζϜൺֱʹ͑Δ -
50 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ᶄ Fuzz
ςετ • 'V[[ςετ • ༧ଌෆՄೳͳೖྗσʔλʢGV[[ʣΛ༩͑ɺ ෆ۩߹͕ൃੜ͢Δέʔε͕ແ͍͔୳͢ -
51 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ᶄ Fuzz
ςετ • 'V[[ςετ • ༧ଌෆՄೳͳೖྗσʔλʢGV[[ʣΛ༩͑ɺ ෆ۩߹͕ൃੜ͢Δέʔε͕ແ͍͔୳͢ ϥϯμϜͳ Fuzz ςετ ࣮֬Ͱͳ͍͕҆৺ײʹͭͳ͕Δ -
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 { } ςετର -
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&.ܗࣜͷσʔλߏ ςετର -
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 { } Τϯίʔυ༻ͷؔ ςετର -
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) } ςετίʔυ -
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) } ςετ༻ͷؔ ςετίʔυ -
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) } ҙͷσʔλͰΤϯίʔυʹࣦഊ͠ͳ͍͜ͱ ςετίʔυ -
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) } σίʔυͨ͠ΒݩͱҰக͢Δ͜ͱ Τϯίʔυɾσίʔυͨ݁͠Ռ ݩσʔλ ςετίʔυ -
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) } σίʔυͨ͠ΒݩͱҰக͢Δ͜ͱ Τϯίʔυɾσίʔυͨ݁͠Ռ ݩσʔλ ϥϯμϜͳೖྗͰຬ͖ͨ͢ੑ࣭Λ ςετίʔυͱͯ͠هड़Ͱ͖Δ ࠓճ ɾΤϥʔʹͳΒͳ͍͜ͱ ɾΤϯίʔυɾσίʔυͨ͠ΒݩʹΔ͜ͱ -
62 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ·ͱΊ •
UFTUJOHRVJDLϥϯμϜʹΑΔςετ • 1SPQFSUZCBTFE5FTUJOHͱݴΘΕΔ • (Pඪ४ύοέʔδͷςετͰΘΕ͍ͯΔ ᶃ໌നͳ࣮ͱͷൺֱ ᶄ'V[[ςετ গͳ͍͚Ͳ -
63 Copyright (C) DeNA Co.,Ltd. All Rights Reserved. ·ͱΊ •
UFTUJOHRVJDLϥϯμϜʹΑΔςετ • 1SPQFSUZCBTFE5FTUJOHͱݴΘΕΔ • (Pඪ४ύοέʔδͷςετͰΘΕ͍ͯΔ ᶃ໌നͳ࣮ͱͷൺֱ ᶄ'V[[ςετ গͳ͍͚Ͳ ར༻γʔϯଟ͘ͳ͍͕ɺ దࡐదॴͰ͑༗ޮͳख๏Ͱʁ ߟ͑ํͱ͓֮ͯ͑ͯ͘͠ͷ༗ޮ