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
Datetime tests with cakephp/chronos
Search
hideki kinjyo
PRO
March 31, 2019
Programming
0
1.1k
Datetime tests with cakephp/chronos
#phperkaigi 2019でのLT内容です。
cakephp/chronosを利用して強いテスタビリティを手に入れる話
hideki kinjyo
PRO
March 31, 2019
Tweet
Share
More Decks by hideki kinjyo
See All by hideki kinjyo
Composerが「依存解決」のためにどんな工夫をしているか #phpcon
o0h
PRO
1
390
Composerの依存解決 #phpstudy
o0h
PRO
0
110
「影響が少ない」を自分の目でみてみる
o0h
PRO
3
1.6k
PHPによる"非"構造化プログラミング入門 -本当に熱いスパゲティコードを求めて- #phperkaigi
o0h
PRO
0
1.6k
もう少しテストを書きたいんじゃ〜 #phpstudy
o0h
PRO
23
5.2k
『テスト書いた方が開発が早いじゃん』を解き明かす #phpcon_nagoya
o0h
PRO
10
3.8k
色んなオートローダーを覗き見る #phpcon_okinawa
o0h
PRO
5
680
ヒューマンエラーの本を読んだ ~報告会~
o0h
PRO
3
350
みんなでワイワイ「テスト駆動開発」の話をやる会 #techramen24conf
o0h
PRO
4
680
Other Decks in Programming
See All in Programming
LLMOpsのパフォーマンスを支える技術と現場で実践した改善
po3rin
8
930
ワープロって実は計算機で
pepepper
2
1.3k
実践!App Intents対応
yuukiw00w
1
280
LLMは麻雀を知らなすぎるから俺が教育してやる
po3rin
3
2.1k
DockerからECSへ 〜 AWSの海に出る前に知っておきたいこと 〜
ota1022
2
360
Google I/O Extended Incheon 2025 ~ What's new in Android development tools
pluu
1
290
Understanding Kotlin Multiplatform
l2hyunwoo
0
260
マイコンでもRustのtestがしたい その2/KernelVM Tokyo 18
tnishinaga
2
2.3k
新世界の理解
koriym
0
140
生成AI、実際どう? - ニーリーの場合
nealle
0
110
#QiitaBash TDDで(自分の)開発がどう変わったか
ryosukedtomita
1
370
GitHub Copilotの全体像と活用のヒント AI駆動開発の最初の一歩
74th
7
2.8k
Featured
See All Featured
Building Flexible Design Systems
yeseniaperezcruz
328
39k
Typedesign – Prime Four
hannesfritz
42
2.8k
Bootstrapping a Software Product
garrettdimon
PRO
307
110k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
161
15k
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
7
810
Designing Experiences People Love
moore
142
24k
Side Projects
sachag
455
43k
Designing for humans not robots
tammielis
253
25k
Connecting the Dots Between Site Speed, User Experience & Your Business [WebExpo 2025]
tammyeverts
8
460
4 Signs Your Business is Dying
shpigford
184
22k
Speed Design
sergeychernyshev
32
1.1k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
110
20k
Transcript
࣌Λࢧ͢ΔPHP #phperkaigi 2019.03.31 Hideki Kinjyo twitter: @o0h_ / github: o0h
ಥͰ͕͢
Έͳ͞Μࢥ͍·ͤΜ͔
͋ʙɺ͕࣌ؒͱ·Ε͍͍ͷʹɻ
Ͱ͢ΑͶʁ
ͦΕɺPHPͰͰ͖ΔΑʂ
ຊͷ͝հ
cakephp/chronos
ࣗݾհ • ίωώτגࣜձࣾ • αʔόʔαΠυΤϯδχΞ • ओʹCakePHPͳͲ • ࠷ۙɺ{ॳ}ॻ੶Λࣥච͠·ͨ͠ ͡Ί·ͯ͠ʂ
TL;DR • cakephp/chronos A standalone DateTime library originally based off
of Carbon • Date(calendar) / DateTimeͷศརͳॲཧΛఏڙ ͢Δ • ࣌ॲཧΛҕৡ͢Δ͜ͱͰɺ γεςϜ࣌ʹґଘ͠ͳ͍ʮݱࡏ࣌ʯΛॲཧ͕ Մೳʹ
Α͋͘Γͦ͏ͳ
དྷ݄ɺզ͕ࣾ ͕ECαΠτʮଠ ܅ͷ͓หശʯ Λ࢝Ίͯɺ7प ͩɻ ײँͷؾ࣋ͪΛ ͜Ίͨɺεϖγϟ ϧηʔϧΛΖ ͏Α ࣾͷਓ
͕ࣾɺϫλ γʹͱͬͯ ΤϞ͍ࣄΛ ͤͯ͘Εͨ ͧɻ͜Εઈ ରʹࣦഊͰ͖ ͳ͍ɺ͕Μ Δ͔͠ͳ͍ʂ ৽ೖࣾһϫλγ
͋ʙΒΑͬʂͱɻ $template = 'itsumono_hanbai_page'; if (time() >= strtotime(START_SALE_DATETIME_STR)) { $template
= 'special_taro_sale'; } render($template);
͜ΕͰɺ ʹͳͬͨΒϖʔ δ͕ΓସΘ Δɻྑ͔ͬͨɺ ྑ͍ײ͡ʹ ࣄ͕Ͱ͖ͨͧɻ ৽ೖࣾһϫλγ
͊ɺ͕Μͬ ͨͶʂ͏Ұ ਓલ͍͔ۙ ͳʁ(স)͜Εͳ ΒɺΈΜ ͳେتͼʹҧ ͍ͳ͍ɻ͠ ͘ͳΔͧʙʙʂ པΕΔઌഐ
ͱ͜ΖͰ͞ʂ ͜Εͬͯɺ ͏CI௨ͨ͠ ͔ͳʁͲ͏ͩͬ ͨʁ པΕΔઌഐ
͋ɺઌഐʂς ετͬͯ͜ͱ Ͱ͔͢ʁϩʔ ΧϧͰɺγ εςϜλΠϜ Λมߋͯ͠ಈ ࡞֬ೝ͠· ͨ͠ɻ ৽ೖࣾһϫλγ
ͰɺΉΉΉɺ ͔֬ʹςετ ίʔυɾɾɾ runkitͱ͔ೖ ΕͪΌ͍ͬͯ ͍Ͱ͔͢Ͷʁ ৽ೖࣾһϫλγ
͏Μ͏Μɺͦ ͏ͩΑͶɻͦ Μͳ࣌ʹɺͱͬ ͯศརͳ Μͷ͕͋ΔΜ ͩɻ པΕΔઌഐ
cakephp/chronos͞ʂ
৭ʑͱػೳ͕ ͋ΔΑ པΕΔઌഐ
ԼͷΒͷ ؔ৺ͱͯ͠ɺ ʮtesting aidʯػೳ͕ ʹཱͪͦ͏ͩ ͔Βɺհ͢ ΔͶɻ པΕΔઌഐ
setTestNow()
before $template = 'itsumono_hanbai_page'; if (time() >= strtotime(START_SALE_DATETIME_STR)) { $template
= 'special_taro_sale'; } render($template);
·ͣɺʮݱࡏʯʹ͍ͭͯ ͯ͢Chronosܦ༝ͰऔΓग़͢Α͏ʹॻ͖͑ΔΑ use Cake\Chronos\Chronos; $template = 'itsumono_hanbai_page'; if (Chronos::now() >=
strtotime(START_SALE_DATETIME_STR)) { $template = 'special_taro_sale'; } render($template);
͍ͭͰʹɺ ૬खํॻ͖͑ͯ͠·͓͏ use Cake\Chronos\Chronos; $template = 'itsumono_hanbai_page'; if (Chronos::now() >=
new Chronos(START_SALE_DATETIME_STR) ) { $template = 'special_taro_sale'; } render($template);
ൺֱϝιουΛ͏ͱ ܕνΣοΫͰ͖ΔͷͰɺ͓ΈͰɻ use Cake\Chronos\Chronos; $template = 'itsumono_hanbai_page'; if (Chronos::now()->gte(new Chronos(START_SALE_DATETIME_STR))
) { $template = 'special_taro_sale'; } render($template);
ϓϩμΫτίʔ υͷ४උͰ ͖ͨɻͯ͞ɺ ͜ΕͰςετ ͕ॻ͚ΔΜͩ Αʂ པΕΔઌഐ
testίʔυΛॻ͍ͯΈΔ /** * @test */ public function セール開始前() { Chronos::setTestNow('2019-03-10');
$targetPageUrl = '/'; $actual = get($targetPageUrl); $this->assertTitleIs( '太郎君のお弁当箱', $actual ); }
testίʔυΛॻ͍ͯΈΔ /** * @test */ public function セール開始前() { Chronos::setTestNow('2019-03-10');
$targetPageUrl = '/'; $actual = get($targetPageUrl); $this->assertTitleIs( '太郎君のお弁当箱', $actual ); } ͜͜ʹೖΕ͕ͨ A$ISPOPTOPX AʹͳΔ
testίʔυΛॻ͍ͯΈΔ /** * @test */ public function セール期間中() { Chronos::setTestNow('2019-04-01');
$targetPageUrl = '/'; $actual = get($targetPageUrl); $this->assertTitleIs( '太郎君のお弁当箱〜7周年ありがとう!〜', $actual ); } ֘ظؒʹ͓͍ͯ ϖʔδίϯςϯπ͕ ࠩ͠ସΘΔ͜ͱΛظ͢Δ
testίʔυΛॻ͍ͯΈΔ /** * @test */ public function セール終了後() { Chronos::setTestNow('2019-05-01
06:59:59’); $targetPageUrl = '/'; $actual = get($targetPageUrl); $this->assertTitleIs( ‘太郎君のお弁当箱', $actual ); } ࣌ࠁϨϕϧ·ͰݻఆՄೳ
͓ͬͱɺऴྃ ࣌ͷઃఆΛͯ͠ ͳ͔͔ͬͨͶʂ ͪΖΜɺ͙͢ ʹඞཁͳ͍͚ Ͳɺࠓͷ͏ͪʹ ͓͍ͬͯͪΌ ͑҆৺ͩͶʂ པΕΔઌഐ
Θɺ͋Ϳͳ͍ʂ ઌഐ͋Γ͕ͱ ͏͍͟͝·͢ʂ ͬͺΓɺς ετ͕(͔͠ ؆୯ʹ)ॻ͚Δ ͱ҆৺ײ͕͋ Δͳʙ ৽ೖࣾһϫλγ
ͪͳΈʹɺ `setTestNow(null )` ͯ͋͛͠Εɺ ϑΣΠΫ࣌Ͱ ͳ͘ݱ࣮ͷ͕࣌ ฦͬͯ͘ΔͷͰ҆ ৺͞ɻςετͰ ͏࣌ͱ͔ɺ tearDown()ʹڬΜ
Ͱ͓͖͍ͨͶɻ པΕΔઌഐ
ଞʹศརͳ͜ͱ (࣌ؒ͋ΕͶ!)
৭ʑͱϔϧύʔͳͲ • DateTimeInterfaceDateTimeImmutableͷػೳͦͷ··͑Δͷ ͰɺҠߦͦΜͳʹ͠ΜͲ͘ͳ͍ͣ • add/sub/diffͳͲͳͲ • ࣌ૢ࡞ʹɺʮࣗવจͬΆ͍දݱͰಡΈ͍͢ʯAPI͕૿͑Δҹ • ge/gte/lt/lte/between/wasWithinLastͳͲͷൺֱػೳ
• addDays(int $value) / subMonths(int $value)ͳͲͷߋ৽ػೳ • Chronos::yesterday() / Chronos::instance(DatetimeInterface $dt) ͳͲͷϑΝΫτϦ
ΞάϨογϒͳ͍ํ <?php use Cake\Chronos\Chronos; if (!function_exists('now')) { function now() {
return Chronos::now(); } } // usage if (now()->isSunday()) { goto doNidone(); }
(ͪͳΈʹ)cakephpͷ߹ • I18nܥύοέʔδͰܧঝͨ͠ɺTime/FrozenTime ͕ར༻͞Ε͍ͯΔ • timezonelocaleͷใΛ͍࣋ͬͯΔ • https://github.com/cakephp/i18n/blob/master/ FrozenTime.php •
ORMܦ༝ͰRDBMS͔ΒऔΓग़ͨ͠datetimeྻͷ ɺࣗಈతʹίΠπʹϚʔγϟϧ͞ΕΔ
·ͱΊ
·ͱΊ(1/2) • ςετ = ҆৺ײ • ςελϒϧ = ઃܭͷɺςεςΟϯάϑϨʔ ϜϫʔΫ(etc)ଆͷදݱྗͷ
• ࣌Λࢧ͢Δͱͱͬͯศར ಛʹςετɺ͜ΕͰTDDΓ͍ͧ͢ʂ
·ͱΊ(2/2) • cakephpνʔϜͷϝϯς͚ͩͲɺελϯυΞ ϩϯͰ͑ΔͷͰɺͲ͜ʹͰ࿈Ε͍͚ͯΔʂ • ʮਂ0࣌ʙਂ2࣌ͷؒ௨Βͳ͍ʯ͔Βͷ ଔۀɾɾɾʂ
͓͖߹͍͍ ͖ͨͩ ͋Γ͕ͱ͏͝ ͍͟·ͨ͠ʂ