Datetime tests with cakephp/chronos

Datetime tests with cakephp/chronos

#phperkaigi 2019でのLT内容です。
cakephp/chronosを利用して強いテスタビリティを手に入れる話

C90bac78c0fb61105cfd8239767f903d?s=128

hideki kinjyo

March 31, 2019
Tweet

Transcript

  1. ࣌Λࢧ഑͢ΔPHP #phperkaigi 2019.03.31 Hideki Kinjyo twitter: @o0h_ / github: o0h

  2. ౜ಥͰ͕͢

  3. Έͳ͞Μ΋ࢥ͍·ͤΜ͔

  4. ͋ʙɺ͕࣌ؒͱ·Ε͹͍͍ͷʹɻ

  5. Ͱ͢ΑͶʁ

  6. ͦΕɺPHPͰͰ͖ΔΑʂ

  7. ຊ೔ͷ͝঺հ

  8. cakephp/chronos

  9. ࣗݾ঺հ • ίωώτגࣜձࣾ • αʔόʔαΠυΤϯδχΞ • ओʹCakePHPͳͲ • ࠷ۙɺ{ॳ}ॻ੶Λࣥච͠·ͨ͠ ͸͡Ί·ͯ͠ʂ

  10. TL;DR • cakephp/chronos
 A standalone DateTime library originally based off

    of Carbon • Date(calendar) / DateTimeͷศརͳॲཧΛఏڙ ͢Δ • ೔࣌ॲཧΛҕৡ͢Δ͜ͱͰɺ
 γεςϜ೔࣌ʹґଘ͠ͳ͍ʮݱࡏ೔࣌ʯΛॲཧ͕ Մೳʹ
  11. Α͋͘Γͦ͏ͳ࿩

  12. དྷ݄͸ɺզ͕ࣾ ͕ECαΠτʮଠ ࿠܅ͷ͓ห౰ശʯ Λ࢝Ίͯɺ7प೥ ͩɻ ײँͷؾ࣋ͪΛ ͜Ίͨɺεϖγϟ ϧηʔϧΛ΍Ζ ͏Α ࣾ௕ͷਓ

  13. ࣾ௕͕ɺϫλ γʹͱͬͯ΋ ΤϞ͍࢓ࣄΛ ೚ͤͯ͘Εͨ ͧɻ͜Ε͸ઈ ରʹࣦഊͰ͖ ͳ͍ɺ͕Μ͹ Δ͔͠ͳ͍ʂ ৽ೖࣾһϫλγ

  14. ͋ʙΒΑͬʂͱɻ $template = 'itsumono_hanbai_page'; if (time() >= strtotime(START_SALE_DATETIME_STR)) { $template

    = 'special_taro_sale'; } render($template);
  15. ͜ΕͰɺ౰೔ ʹͳͬͨΒϖʔ δ͕੾ΓସΘ Δɻྑ͔ͬͨɺ ྑ͍ײ͡ʹ࢓ ࣄ͕Ͱ͖ͨͧɻ ৽ೖࣾһϫλγ

  16. ΍͊ɺ͕Μ͹ͬ ͨͶʂ΋͏Ұ ਓલ΋͍͔ۙ ͳʁ(স)͜Εͳ Β౰೔ɺΈΜ ͳେتͼʹҧ ͍ͳ͍ɻ๩͠ ͘ͳΔͧʙʙʂ པΕΔઌഐ

  17. ͱ͜ΖͰ͞ʂ ͜Εͬͯɺ΋ ͏CI͸௨ͨ͠ ͔ͳʁͲ͏ͩͬ ͨʁ པΕΔઌഐ

  18. ͋ɺઌഐʂς ετͬͯ͜ͱ Ͱ͔͢ʁϩʔ ΧϧͰ͸ɺγ εςϜλΠϜ Λมߋͯ͠ಈ ࡞֬ೝ͸͠· ͨ͠ɻ ৽ೖࣾһϫλγ

  19. Ͱ΋ɺΉΉΉɺ ͔֬ʹςετ ίʔυ͸ɾɾɾ runkitͱ͔ೖ ΕͪΌ͍ͬͯ ͍Ͱ͔͢Ͷʁ ৽ೖࣾһϫλγ

  20. ͏Μ͏Μɺͦ ͏ͩΑͶɻͦ Μͳ࣌ʹɺͱͬ ͯ΋ศརͳ΋ Μͷ͕͋ΔΜ ͩɻ པΕΔઌഐ

  21. cakephp/chronos͞ʂ

  22. ৭ʑͱػೳ͕ ͋ΔΑ པΕΔઌഐ

  23. ໨Լͷ๻Βͷ ؔ৺ͱͯ͠͸ɺ ʮtesting aidʯػೳ͕໾ ʹཱͪͦ͏ͩ ͔Βɺ঺հ͢ ΔͶɻ པΕΔઌഐ

  24. setTestNow()

  25. before $template = 'itsumono_hanbai_page'; if (time() >= strtotime(START_SALE_DATETIME_STR)) { $template

    = 'special_taro_sale'; } render($template);
  26. ·ͣ͸ɺʮݱࡏʯʹ͍ͭͯ
 ͢΂ͯChronosܦ༝ͰऔΓग़͢Α͏ʹॻ͖׵͑ΔΑ use Cake\Chronos\Chronos; $template = 'itsumono_hanbai_page'; if (Chronos::now() >=

    strtotime(START_SALE_DATETIME_STR)) { $template = 'special_taro_sale'; } render($template);
  27. ͍ͭͰʹɺ
 ૬खํ΋ॻ͖׵͑ͯ͠·͓͏ use Cake\Chronos\Chronos; $template = 'itsumono_hanbai_page'; if (Chronos::now() >=

    new Chronos(START_SALE_DATETIME_STR) ) { $template = 'special_taro_sale'; } render($template);
  28. ൺֱϝιουΛ࢖͏ͱ
 ܕνΣοΫ΋Ͱ͖ΔͷͰɺ͓޷ΈͰɻ use Cake\Chronos\Chronos; $template = 'itsumono_hanbai_page'; if (Chronos::now()->gte(new Chronos(START_SALE_DATETIME_STR))

    ) { $template = 'special_taro_sale'; } render($template);
  29. ϓϩμΫτίʔ υͷ४උ͸Ͱ ͖ͨɻͯ͞ɺ ͜ΕͰςετ ͕ॻ͚ΔΜͩ Αʂ པΕΔઌഐ

  30. testίʔυΛॻ͍ͯΈΔ /** * @test */ public function セール開始前() { Chronos::setTestNow('2019-03-10');

    $targetPageUrl = '/'; $actual = get($targetPageUrl); $this->assertTitleIs( '太郎君のお弁当箱', $actual ); }
  31. testίʔυΛॻ͍ͯΈΔ /** * @test */ public function セール開始前() { Chronos::setTestNow('2019-03-10');

    $targetPageUrl = '/'; $actual = get($targetPageUrl); $this->assertTitleIs( '太郎君のお弁当箱', $actual ); } ͜͜ʹೖΕͨ஋͕
 A$ISPOPTOPX AʹͳΔ
  32. testίʔυΛॻ͍ͯΈΔ /** * @test */ public function セール期間中() { Chronos::setTestNow('2019-04-01');

    $targetPageUrl = '/'; $actual = get($targetPageUrl); $this->assertTitleIs( '太郎君のお弁当箱〜7周年ありがとう!〜', $actual ); } ֘౰ظؒʹ͓͍ͯ͸
 ϖʔδ಺ίϯςϯπ͕
 ࠩ͠ସΘΔ͜ͱΛظ଴͢Δ
  33. testίʔυΛॻ͍ͯΈΔ /** * @test */ public function セール終了後() { Chronos::setTestNow('2019-05-01

    06:59:59’); $targetPageUrl = '/'; $actual = get($targetPageUrl); $this->assertTitleIs( ‘太郎君のお弁当箱', $actual ); } ࣌ࠁϨϕϧ·ͰݻఆՄೳ
  34. ͓ͬͱɺऴྃ೔ ࣌ͷઃఆΛͯ͠ ͳ͔͔ͬͨ΋Ͷʂ ΋ͪΖΜɺ͙͢ ʹ͸ඞཁͳ͍͚ Ͳɺࠓͷ͏ͪʹ ΍͓͍ͬͯͪΌ ͑͹҆৺ͩͶʂ པΕΔઌഐ

  35. Θɺ͋Ϳͳ͍ʂ ઌഐ͋Γ͕ͱ ͏͍͟͝·͢ʂ ΍ͬͺΓɺς ετ͕(͔͠΋ ؆୯ʹ)ॻ͚Δ ͱ҆৺ײ͕͋ Δͳʙ ৽ೖࣾһϫλγ

  36. ͪͳΈʹɺ `setTestNow(null )` ͯ͋͛͠Ε͹ɺ ϑΣΠΫ೔࣌Ͱ͸ ͳ͘ݱ࣮ͷ೔͕࣌ ฦͬͯ͘ΔͷͰ҆ ৺͞ɻςετͰ࢖ ͏࣌ͱ͔͸ɺ tearDown()ʹڬΜ

    Ͱ͓͖͍ͨͶɻ པΕΔઌഐ
  37. ଞʹ΋ศརͳ͜ͱ (࣌ؒ͋Ε͹Ͷ!)

  38. ৭ʑͱϔϧύʔͳͲ • DateTimeInterface΍DateTimeImmutableͷػೳ͸ͦͷ··࢖͑Δͷ ͰɺҠߦ΋ͦΜͳʹ͠ΜͲ͘ͳ͍͸ͣ • add/sub/diffͳͲͳͲ • ೔࣌ૢ࡞ʹɺʮࣗવจͬΆ͍දݱͰಡΈ΍͍͢ʯAPI͕૿͑Δҹ৅ • ge/gte/lt/lte/between/wasWithinLastͳͲͷൺֱػೳ

    • addDays(int $value) / subMonths(int $value)ͳͲͷߋ৽ػೳ • Chronos::yesterday() / Chronos::instance(DatetimeInterface $dt) ͳͲͷϑΝΫτϦ
  39. ΞάϨογϒͳ࢖͍ํ <?php use Cake\Chronos\Chronos; if (!function_exists('now')) { function now() {

    return Chronos::now(); } } // usage if (now()->isSunday()) { goto doNidone(); }
  40. (ͪͳΈʹ)cakephpͷ৔߹ • I18nܥύοέʔδͰܧঝͨ͠ɺTime/FrozenTime ͕ར༻͞Ε͍ͯΔ • timezone΍localeͷ৘ใΛ͍࣋ͬͯΔ • https://github.com/cakephp/i18n/blob/master/ FrozenTime.php •

    ORMܦ༝ͰRDBMS͔ΒऔΓग़ͨ͠datetimeྻͷ ஋͸ɺࣗಈతʹίΠπʹϚʔγϟϧ͞ΕΔ
  41. ·ͱΊ

  42. ·ͱΊ(1/2) • ςετ = ҆৺ײ • ςελϒϧ = ઃܭͷ࿩ɺςεςΟϯάϑϨʔ ϜϫʔΫ(etc)ଆͷදݱྗͷ࿩

    • ࣌Λࢧ഑͢Δͱͱͬͯ΋ศར
 ಛʹςετɺ͜ΕͰTDD΋΍Γ΍͍ͧ͢ʂ
  43. ·ͱΊ(2/2) • cakephpνʔϜͷϝϯς͚ͩͲɺελϯυΞ ϩϯͰ࢖͑ΔͷͰɺͲ͜ʹͰ΋࿈Ε͍͚ͯΔʂ • ʮਂ໷0࣌ʙਂ໷2࣌ͷؒ͸௨Βͳ͍ʯ͔Βͷ ଔۀɾɾɾʂ

  44. ͓෇͖߹͍͍ ͖ͨͩ
 ͋Γ͕ͱ͏͝ ͍͟·ͨ͠ʂ