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
組織もソフトウェアも難しく考えない、もっとシンプルな考え方で設計する #phpconfuk
o0h
PRO
10
4.3k
Composerが「依存解決」のためにどんな工夫をしているか #phpcon
o0h
PRO
1
560
Composerの依存解決 #phpstudy
o0h
PRO
0
130
「影響が少ない」を自分の目でみてみる
o0h
PRO
3
1.8k
PHPによる"非"構造化プログラミング入門 -本当に熱いスパゲティコードを求めて- #phperkaigi
o0h
PRO
0
1.7k
もう少しテストを書きたいんじゃ〜 #phpstudy
o0h
PRO
23
5.3k
『テスト書いた方が開発が早いじゃん』を解き明かす #phpcon_nagoya
o0h
PRO
9
4.2k
色んなオートローダーを覗き見る #phpcon_okinawa
o0h
PRO
5
760
ヒューマンエラーの本を読んだ ~報告会~
o0h
PRO
3
390
Other Decks in Programming
See All in Programming
高単価案件で働くための心構え
nullnull
0
140
Module Harmony
petamoriken
2
360
なぜ強調表示できず ** が表示されるのか — Perlで始まったMarkdownの歴史と日本語文書における課題
kwahiro
12
5.9k
Claude Code on the Web を超える!? Codex Cloud の実践テク5選
sunagaku
0
550
Amazon Bedrock Knowledge Bases Hands-on
konny0311
0
150
複数チーム並行開発下でのコード移行アプローチ ~手動 Codemod から「生成AI 活用」への進化
andpad
0
170
Core MIDI を勉強して作曲用の電子ピアノ作ってみた!
hypebeans
0
110
Nitro v3
kazupon
2
310
The Missing Link in Angular's Signal Story: Resource API and httpResource
manfredsteyer
PRO
0
130
Rails Girls Sapporo 2ndの裏側―準備の日々から見えた、私が得たもの / SAPPORO ENGINEER BASE #11
lemonade_37
2
160
「10分以内に機能を消せる状態」 の実現のためにやっていること
togishima
1
430
予防に勝る防御なし(2025年版) - 堅牢なコードを導く様々な設計のヒント / Growing Reliable Code PHP Conference Fukuoka 2025
twada
PRO
37
12k
Featured
See All Featured
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
359
30k
Facilitating Awesome Meetings
lara
57
6.6k
VelocityConf: Rendering Performance Case Studies
addyosmani
333
24k
Imperfection Machines: The Place of Print at Facebook
scottboms
269
13k
Into the Great Unknown - MozCon
thekraken
40
2.2k
Become a Pro
speakerdeck
PRO
29
5.6k
Site-Speed That Sticks
csswizardry
13
960
Rebuilding a faster, lazier Slack
samanthasiow
84
9.3k
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.5k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
48
9.8k
The Cult of Friendly URLs
andyhume
79
6.7k
Building Better People: How to give real-time feedback that sticks.
wjessup
370
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࣌ͷؒ௨Βͳ͍ʯ͔Βͷ ଔۀɾɾɾʂ
͓͖߹͍͍ ͖ͨͩ ͋Γ͕ͱ͏͝ ͍͟·ͨ͠ʂ