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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Kentaro Kawano
July 07, 2017
Programming
140
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
510
Starting Python
kawaken
0
130
AWS Lambda + Go
kawaken
0
130
goaのdesignをラクに書く/Write goa design easily
kawaken
0
120
Goでのチーム開発とコード管理の悩み/Team development and code management in Go
kawaken
0
120
Pyvmomiとansibleのdynamic inventory
kawaken
0
130
Other Decks in Programming
See All in Programming
SPMマルチモジュールで テストカバレッジを取得する技法
yosshi4486
0
140
関係性から理解する"同一性"の型用語たち
pvcresin
2
640
さぁV100、メモリをお食べ・・・
nilpe
0
130
Swiftのレキシカルスコープ管理
kntkymt
0
210
Why Laravel apps break—Mastering the fundamentals to keep them maintainable
kentaroutakeda
1
340
Javaの型とAI時代に型が大事な理由 / java types and type in AI era
kishida
2
110
「AIで開発し、AIを届ける」をEvalでつなぐ 〜AIネイティブに始めるプロダクト開発の実践〜 / Connecting "Develop with AI, deliver AI" with Eval
rkaga
4
2.4k
LLM本来の能力を解き放つサンドボックス技術とAI民主化への適用
yukukotani
3
2.8k
[2026年度第1回ORセミナー] 計画最適化ベンチャーと競技プログラミング人材
terryu16
0
250
AI駆動開発で崩れていくコードベースを立て直す
kyoko_nr_nr
1
440
AIとASP.NET Coreで雑Webアプリを作った話
mayuki
0
320
代数的データ型って何が嬉しいの? #frontend_phpcon_do
kajitack
8
3.2k
Featured
See All Featured
Building the Perfect Custom Keyboard
takai
2
780
Designing Powerful Visuals for Engaging Learning
tmiket
1
400
Exploring anti-patterns in Rails
aemeredith
3
390
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
0
310
The Curse of the Amulet
leimatthew05
1
13k
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
380
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.5k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
How Software Deployment tools have changed in the past 20 years
geshan
0
34k
Automating Front-end Workflow
addyosmani
1370
210k
Side Projects
sachag
455
43k
Are puppies a ranking factor?
jonoalderson
1
3.5k
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͋Γʁ