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
160
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
150
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
Go 1.27 における memory allocation の高速化
andpad
0
170
Laravel Boostに学ぶ、AIにPHPを書かせる技術 〜OSSの実装から蒸留するエージェント制御の王道〜
kentaroutakeda
3
690
自動化したのに回らない テスト運用の壁―AI時代の品質責任と生産性
mfunaki
0
160
変わらないものが、変わるものを決める — 意図駆動開発 × イベントソーシング × イミュータブル | What Doesn't Change Decides What Can — IDD × Event Sourcing × Immutability
tomohisa
0
1.6k
S3 を使うアプリケーションをローカル完結で動かすことに全力を注いでみた / Running S3 Apps Offline
contour_gara
0
460
AI Readyの正体はデータマネジメントだ メダリオン2.0の最前線
freee
PRO
0
220
実装をデザインガイドラインに追従させるための取り組み / 260731-dip-mosh-design-system
dachi023
0
440
プロポーザルを書いてもらう
pvcresin
0
500
いまどきの Codex で開発する visionOS アプリの開発スタイルについて
karad
0
140
ITヒヤリハットを整理してみた ~ライフサイクルと原因から考える再発防止策~
koukimiura
1
140
the container ship “Apple Silicon”@WWDC26 Recap -Japan-\(region).swift
shingangan
0
120
関東Kaggler会_NVIDIA_Nemotron_コンペ_振り返り
rick_ds
0
560
Featured
See All Featured
sira's awesome portfolio website redesign presentation
elsirapls
0
320
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
890
30 Presentation Tips
portentint
PRO
1
370
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
201
75k
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
5
1.2k
The SEO identity crisis: Don't let AI make you average
varn
0
530
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.5k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
The Art of Programming - Codeland 2020
erikaheidi
57
14k
Balancing Empowerment & Direction
lara
6
1.2k
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
360
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
2
3.8k
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͋Γʁ