Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Goの時刻に関するテスト/Testing time in Go
Search
Kentaro Kawano
July 07, 2017
Programming
150
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Goの時刻に関するテスト/Testing time in Go
Goの時刻に関するテスト
Kentaro Kawano
July 07, 2017
More Decks by Kentaro Kawano
See All by Kentaro Kawano
Goでのレシーバーとnilの関係 / Receiver and nil relationship in Go
kawaken
0
520
Starting Python
kawaken
0
140
AWS Lambda + Go
kawaken
0
140
goaのdesignをラクに書く/Write goa design easily
kawaken
0
130
Goでのチーム開発とコード管理の悩み/Team development and code management in Go
kawaken
0
130
Pyvmomiとansibleのdynamic inventory
kawaken
0
140
Other Decks in Programming
See All in Programming
使用 Meilisearch 建立新聞搜尋工具
johnroyer
0
160
AI時代のPHPer生存戦略 ~「言語、もうなんでもよくない?」に本気で向き合う~
vivion
0
140
人間の目はかわらない、だからJPEGは30年もつ
yuzneri
1
170
AIが無かった頃の素敵な出会いの話
codmoninc
1
190
ビデオ通話が繋がる0.2秒で何が起きているのか
supurazako
2
150
Welcome to the "Parametricity" 🏙️ − Generic だけど Specific な世界 −
guvalif
PRO
1
180
どこまでゆるくて許されるのか
tk3fftk
0
520
PHPだって関数型したい 〜できること、できないこと〜 / fp-in-php
jsoizo
1
240
コーディングルールの鮮度を保ちたい for SRE NEXT 2026 / keep-fresh-go-internal-conventions-sre-next-2026
handlename
0
150
PHP Application における Kubernetes 内 gRPC 通信
ganchiku
0
530
AIキャラアプリkaiwaの低遅延音声通話基盤をどう作ったか - AWS Gravitonで支える低遅延・低コストAI Agent基盤
mogamit
0
180
はてなアカウント基盤 State of the Union
cockscomb
1
1.3k
Featured
See All Featured
Bootstrapping a Software Product
garrettdimon
PRO
307
120k
Darren the Foodie - Storyboard
khoart
PRO
3
3.4k
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
410
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
880
Principles of Awesome APIs and How to Build Them.
keavy
128
18k
Balancing Empowerment & Direction
lara
6
1.2k
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
260
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
New Earth Scene 8
popppiees
3
2.4k
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.8k
Why You Should Never Use an ORM
jnunemaker
PRO
61
9.9k
So, you think you're a good person
axbom
PRO
2
2.1k
Transcript
Goͷ࣌ࠁʹؔ͢Δςετ 2017/07/07 Umeda.go #2
ࣗݾհ • Տ ݈ଠ࿕ (@kawaken) • γφδʔϚʔέςΟϯάʢגʣ • ϓογϡ௨ج൫ɺLINE৴ج൫ •
Go3͘Β͍ • goaͷίʔυεχϖοτ࡞ͬͯ·͢
࣌ࠁͷςετͷ͠͞ʁ
func CanDeliver() bool { hour := time.Now().Hour() // 8࣌ʙ20࣌ͳΒ৴Մೳ return
8 <= hour && hour <= 20 } ࣌ࠁΛऔಘͯ͠அ͢Δfunc
ςετํ • 8࣌ʙ20࣌: trueͰ͋Δ͜ͱΛ֬ೝ͢Δ • 21࣌ʙ7࣌: falseͰ͋Δ͜ͱΛ֬ೝ͢Δ
μϝͳςετ func TestCanDeliver(t *testing.T) { hour := time.Now().Hour() expected :=
8 <= hour && hour <= 20 // ಉ͡ॲཧ result := CanDeliver() if expected == result { t.Log("OK") } else { t.Fatal("NG") } }
࣌ࠁͷςετͷ͠͞ • time.Now ৗʹҧ͏Λฦ͢ • ͕࣌ؒܦա͠ͳ͍ͱύλʔϯΛཏͰ͖ͳ͍
͍ΖΜͳςετͷύλʔϯ • ݄ลΓͷि • څྉ͕ٳ • य़ͷɺळͷ • ৼସٳ •
2݄29
࣮ͱςετͷύλʔϯ
࣮ͱςετͷύλʔϯ 1. ֎෦͔Βͷೖ 2. ελϒ 3. αʔυύʔςΟʔͷύοέʔδ
1. ֎෦͔Βͷೖ
func CanDeliver(hour int) bool { // 8࣌ʙ20࣌ͳΒ৴Մೳ return 8 <=
hour && hour <= 20 } ͦͦtime.NowΛ͏ඞཁ͕ͳ͍
func TestCanDeliver(t *testing.T) { cases := []struct { hour int
want bool }{ {7, false}, {8, true}, {20, true}, {21, false}, } for _, c := range cases { got := CanDeliver(c.hour) if got != c.want { t.Errorf("CanDeliver(%d) => %t, want %t", c.hour, got, c.want) } } }
2. ελϒ
var now = time.Now // time.NowΛnowʹೖΕ͓ͯ͘ func CanDeliver() bool {
hour := now().Hour() // nowΛ༻ͯ࣌͠ࠁΛऔಘ // 8࣌ʙ20࣌ͳΒ৴Մೳ return 8 <= hour && hour <= 20 } now Λςετ࣌ʹஔ͖͑Δ
func fakeHour(hour int) { // ݻఆͷtime.TimeΛฦ͢funcͰnowΛஔ͖͑Δ now = func() time.Time
{ return time.Date(2017, 7, 7, hour, 0, 0, 0, time.Local) } } func TestCanDeliver(t *testing.T) { // snip... for _, c := range cases { fakeHour(c.hour) // fakeHourͰ࣌ࠁΛॻ͖͑Δ got := CanDeliver() if got != c.want { t.Errorf("hour: %d, CanDeliver() => %t, want %t", c.hour, got, c.want) } } now = time.Now // reset time }
3. αʔυύʔςΟʔͷύοέʔδ
code.cloudfoundry.org/clock • timeͷସͱͯ͠͏ύοέʔδ • ͕ؔ๛ • ςετ࣌ʹɺclock/fakeclock/FakeClockΛ༻
var myClock = clock.NewClock() // myClockʹclock.ClockΛೖ func CanDeliver() bool {
hour := myClock.Now().Hour() // myClockΛ༻ͯ࣌͠ࠁΛऔಘ // 8࣌ʙ20࣌ͳΒ৴Մೳ return 8 <= hour && hour <= 20 } myClock Λςετ࣌ʹஔ͖͑Δ
func fakeHour(hour int) { // ࢦఆ͞Εͨ࣌ࠁ͔Β։࢝͢ΔΑ͏ʹFakeClockͰஔ͖͑Δ myClock = fakeclock.NewFakeClock(time.Date(2017, 7,
7, hour, 0, 0, 0, time.Local)) } func TestCanDeliver(t *testing.T) { // snip... for _, c := range cases { fakeHour(c.hour) // fakeHourͰ࣌ࠁΛॻ͖͑Δ got := CanDeliver() if got != c.want { t.Errorf("hour: %d, CanDeliver() => %t, want %t", c.hour, got, c.want) } } myClock = clock.NewClock() // reset time }
ϞϠϞϠϙΠϯτ • ґଘੑΛ֎෦͔Βೖ • Ͳ͔͜Ͱ time.Now ݺͳ͍ͱ͍͚ͳ͍ • ελϒαʔυύʔςΟʔύοέʔδ •
time.Now Λ༻͍͚ͯ͠ͳ͍
ૉʹtime.Now͍͍ͨ
4. ֎෦͔Βͷೖ̎
func CanDeliver(hour int) bool { // 8࣌ʙ20࣌ͳΒ৴Մೳ return 8 <=
hour && hour <= 20 } func CanDeliverNow() bool { hour := time.Now().Hour() return CanDeliver(hour) }
5. Monkey patch
github.com/bouk/monkey • GoͰϞϯΩʔύονΛ࣮ݱ͢Δύοέʔδ • ؔϙΠϯλΛࠩ͠ସ͑ͨΓͰ͖Δ • શͯͷڥͰಈ࡞͢ΔΘ͚Ͱͳ͍Έ͍ͨ
func CanDeliver() bool { hour := time.Now().Hour() // 8࣌ʙ20࣌ͳΒ৴Մೳ return
8 <= hour && hour <= 20 }
func fakeHour(hour int) { // time.NowΛࢦఆͷ࣌ࠁΛฦ͢funcͰஔ͖͑Δ monkey.Patch( time.Now, func() time.Time
{ return time.Date(2017, 7, 7, hour, 0, 0, 0, time.Local) }, ) } func TestCanDeliver(t *testing.T) { // snip... for _, c := range cases { fakeHour(c.hour) // fakeHourͰ࣌ࠁΛॻ͖͑Δ got := CanDeliver() if got != c.want { t.Errorf("hour: %d, CanDeliver() => %t, want %t", c.hour, got, c.want) } } monkey.Unpatch(time.Now) // reset time }
6. timeύοέʔδΛ֦ு͢Δ
// time.Now func Now() Time { sec, nsec := now()
return Time{sec + unixToInternal, nsec, Local} }
NowΛ͍͡Ε͍͍ͷͰʁ
/* src/time/time.go */ var fakeTime Time // χηͷ࣌ࠁ func Fake(t
Time) { fakeTime = t } func ResetFake() { fakeTime = Time{} } func Now() Time { if !fakeTime.IsZero() { return fakeTime } sec, nsec := now() return Time{sec + unixToInternal, nsec, Local} }
func CanDeliver() bool { hour := time.Now().Hour() // 8࣌ʙ20࣌ͳΒ৴Մೳ return
8 <= hour && hour <= 20 }
func fakeHour(hour int) { time.Fake(time.Date(2017, 7, 7, hour, 0, 0,
0, time.Local)) } func TestCanDeliver(t *testing.T) { // snip... for _, c := range cases { fakeHour(c.hour) // fakeHourͰ࣌ࠁΛॻ͖͑Δ got := CanDeliver() if got != c.want { t.Errorf("hour: %d, CanDeliver() => %t, want %t", c.hour, got, c.want) } } time.ResetFake() // reset time }
΄ΜͱʹͣΕͯΜͷ͔ͳʁʁʁ % /usr/local/go1.8.3_faketime/bin/go test -v ./timepkg === RUN TestCanDeliver ---
PASS: TestCanDeliver (0.00s) sample_test.go:22: 2017-07-07 07:00:00 +0900 JST sample_test.go:22: 2017-07-07 08:00:00 +0900 JST sample_test.go:22: 2017-07-07 20:00:00 +0900 JST sample_test.go:22: 2017-07-07 21:00:00 +0900 JST PASS ok github.com/kawaken/golang-time-testing/timepkg 0.466s
·ͱΊ ࣌ࠁͷςετ͍͕͠ɺճආํ๏͋Δ 1. ࣌ࠁͷऔಘͱɺ࣌ࠁΛॲཧ͢Δͱ͜ΖΛ͚Δ 2. code.cloudfoundry.org/clock ͕ແʁ 3. monkey͋Γʁ