$30 off During Our Annual Pro Sale. View Details »

Datetime tests with cakephp/chronos

Datetime tests with cakephp/chronos

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

hideki kinjyo
PRO

March 31, 2019
Tweet

More Decks by hideki kinjyo

Other Decks in Programming

Transcript

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

    View Slide

  2. ౜ಥͰ͕͢

    View Slide

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

    View Slide

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

    View Slide

  5. Ͱ͢ΑͶʁ

    View Slide

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

    View Slide

  7. ຊ೔ͷ͝঺հ

    View Slide

  8. cakephp/chronos

    View Slide

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

    View Slide

  10. TL;DR
    • cakephp/chronos

    A standalone DateTime library originally based off of Carbon
    • Date(calendar) / DateTimeͷศརͳॲཧΛఏڙ
    ͢Δ
    • ೔࣌ॲཧΛҕৡ͢Δ͜ͱͰɺ

    γεςϜ೔࣌ʹґଘ͠ͳ͍ʮݱࡏ೔࣌ʯΛॲཧ͕
    Մೳʹ

    View Slide

  11. Α͋͘Γͦ͏ͳ࿩

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  15. ͜ΕͰɺ౰೔
    ʹͳͬͨΒϖʔ
    δ͕੾ΓସΘ
    Δɻྑ͔ͬͨɺ
    ྑ͍ײ͡ʹ࢓
    ࣄ͕Ͱ͖ͨͧɻ
    ৽ೖࣾһϫλγ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  21. cakephp/chronos͞ʂ

    View Slide

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

    View Slide

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

    View Slide

  24. setTestNow()

    View Slide

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

    View Slide

  26. ·ͣ͸ɺʮݱࡏʯʹ͍ͭͯ

    ͢΂ͯChronosܦ༝ͰऔΓग़͢Α͏ʹॻ͖׵͑ΔΑ
    use Cake\Chronos\Chronos;
    $template = 'itsumono_hanbai_page';
    if (Chronos::now()
    >= strtotime(START_SALE_DATETIME_STR)) {
    $template = 'special_taro_sale';
    }
    render($template);

    View Slide

  27. ͍ͭͰʹɺ

    ૬खํ΋ॻ͖׵͑ͯ͠·͓͏
    use Cake\Chronos\Chronos;
    $template = 'itsumono_hanbai_page';
    if (Chronos::now()
    >= new Chronos(START_SALE_DATETIME_STR)
    ) {
    $template = 'special_taro_sale';
    }
    render($template);

    View Slide

  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);

    View Slide

  29. ϓϩμΫτίʔ
    υͷ४උ͸Ͱ
    ͖ͨɻͯ͞ɺ
    ͜ΕͰςετ
    ͕ॻ͚ΔΜͩ
    Αʂ
    པΕΔઌഐ

    View Slide

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

    View Slide

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

    A$ISPOPTOPX
    AʹͳΔ

    View Slide

  32. testίʔυΛॻ͍ͯΈΔ
    /**
    * @test
    */
    public function セール期間中()
    {
    Chronos::setTestNow('2019-04-01');
    $targetPageUrl = '/';
    $actual = get($targetPageUrl);
    $this->assertTitleIs(
    '太郎君のお弁当箱〜7周年ありがとう!〜',
    $actual
    );
    }
    ֘౰ظؒʹ͓͍ͯ͸

    ϖʔδ಺ίϯςϯπ͕

    ࠩ͠ସΘΔ͜ͱΛظ଴͢Δ

    View Slide

  33. testίʔυΛॻ͍ͯΈΔ
    /**
    * @test
    */
    public function セール終了後()
    {
    Chronos::setTestNow('2019-05-01 06:59:59’);
    $targetPageUrl = '/';
    $actual = get($targetPageUrl);
    $this->assertTitleIs(
    ‘太郎君のお弁当箱',
    $actual
    );
    }
    ࣌ࠁϨϕϧ·ͰݻఆՄೳ

    View Slide

  34. ͓ͬͱɺऴྃ೔
    ࣌ͷઃఆΛͯ͠
    ͳ͔͔ͬͨ΋Ͷʂ
    ΋ͪΖΜɺ͙͢
    ʹ͸ඞཁͳ͍͚
    Ͳɺࠓͷ͏ͪʹ
    ΍͓͍ͬͯͪΌ
    ͑͹҆৺ͩͶʂ
    པΕΔઌഐ

    View Slide

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

    View Slide

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

    View Slide

  37. ଞʹ΋ศརͳ͜ͱ
    (࣌ؒ͋Ε͹Ͷ!)

    View Slide

  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)
    ͳͲͷϑΝΫτϦ

    View Slide

  39. ΞάϨογϒͳ࢖͍ํ
    use Cake\Chronos\Chronos;
    if (!function_exists('now')) {
    function now() {
    return Chronos::now();
    }
    }
    // usage
    if (now()->isSunday()) {
    goto doNidone();
    }

    View Slide

  40. (ͪͳΈʹ)cakephpͷ৔߹
    • I18nܥύοέʔδͰܧঝͨ͠ɺTime/FrozenTime
    ͕ར༻͞Ε͍ͯΔ
    • timezone΍localeͷ৘ใΛ͍࣋ͬͯΔ
    • https://github.com/cakephp/i18n/blob/master/
    FrozenTime.php
    • ORMܦ༝ͰRDBMS͔ΒऔΓग़ͨ͠datetimeྻͷ
    ஋͸ɺࣗಈతʹίΠπʹϚʔγϟϧ͞ΕΔ

    View Slide

  41. ·ͱΊ

    View Slide

  42. ·ͱΊ(1/2)
    • ςετ = ҆৺ײ
    • ςελϒϧ = ઃܭͷ࿩ɺςεςΟϯάϑϨʔ
    ϜϫʔΫ(etc)ଆͷදݱྗͷ࿩
    • ࣌Λࢧ഑͢Δͱͱͬͯ΋ศར

    ಛʹςετɺ͜ΕͰTDD΋΍Γ΍͍ͧ͢ʂ

    View Slide

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

    View Slide

  44. ͓෇͖߹͍͍
    ͖ͨͩ

    ͋Γ͕ͱ͏͝
    ͍͟·ͨ͠ʂ

    View Slide