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

サバンナ便り〜自動テストに関する連載で得られた知見のまとめ(2023年5月版)〜 / Automated Test Knowledge from Savanna 202305 edition

サバンナ便り〜自動テストに関する連載で得られた知見のまとめ(2023年5月版)〜 / Automated Test Knowledge from Savanna 202305 edition

2023/05/17(水)
Qiita Conference 2023

Takuto Wada
PRO

May 17, 2023
Tweet

More Decks by Takuto Wada

Other Decks in Programming

Transcript

  1. ࿨ా୎ਓʢ!U@XBEBʣ
    αόϯφศΓ
    ࣗಈςετʹؔ͢Δ࿈ࡌͰಘΒΕͨ஌ݟͷ·ͱΊ


    📷🙆 🙆 2JJUB$POGFSFODF
    .BZ

    View Slide

  2. ΞοϓσʔτΛॏͶΔߨԋͷ೥݄൛Ͱ͢ʢ࿈ࡌୈճ·Ͱऩ࿥ʣ
    IUUQTTQFBLFSEFDLDPNUXBEB
    ίϥϜ࿈ࡌͷୈճ·Ͱऩ࿥͍ͯ͠·͢

    View Slide

  3. ߨԋͷจࣈى͜͠౳΋ࠓޙެ։༧ఆͰ͢
    ެ։͞ΕͨΒTQFBLFSEFDLͷಉҰ63-Ͱ
    ࢿྉΛΞοϓσʔτ͠·͢

    View Slide

  4. t-wada

    t_wada

    twada
    📷🙆 📹🙅
    🙆
    ࣗݾ঺հ
    #QiitaConference

    View Slide

  5. ٕज़ॻͷग़൛ʹؔΘ͍ͬͯ·͢

    View Slide

  6. αόϯφศΓʜʜʁ

    View Slide

  7. IUUQTUXBEBIBUFOBCMPHKQFOUSZXEQSFTTTBWBOOBDPMVNO
    8%#13&44ʹίϥϜΛ࿈ࡌ͍ͯ͠·͢

    View Slide

  8. IUUQTUXBEBIBUFOBCMPHKQFOUSZXEQSFTTTBWBOOBDPMVNO
    8%#13&44ʹίϥϜΛ࿈ࡌ͍ͯ͠·͢

    View Slide

  9. ΑΖ͓͘͠ئ͍͠·͢
    📷🙆 🙆 2JJUB$POGFSFODF

    View Slide

  10. ֶश༻ςετ
    ِཅੑͱِӄੑ
    ςεταΠζ
    ςετμϒϧ
    ςετϐϥϛου
    ࣗಈςετͷαΠζμ΢ϯઓུ
    🦁
    "HFOEB࿈ࡌ֤ճͷςʔϚ

    View Slide

  11. ֶͼΛࣗಈςετͱͯ͠ॻ͘
    ଈ࣌ੑͱ࠶ݱੑ

    View Slide

  12. ֶशྫ1)1ͷ%BUF5JNFͱ%BUF5JNF*NNVUBCMF
    IUUQTXXXQIQOFUNBOVBMKBDMBTTEBUFUJNFJNNVUBCMFQIQ

    View Slide

  13. /**


    * @test


    * @group learning


    */


    public function DateTimeのaddは自身の状態を変更しつつ自身を返す(): void


    {


    $halloween = new \DateTime('2021-10-31');


    $oneYear = \DateInterval::createFromDateString('1 year');


    $halloween2022 = $halloween->add($oneYear);


    $this->assertSame($halloween, $halloween2022);


    $this->assertEquals('2022-10-31', $halloween->format('Y-m-d'));


    $this->assertEquals('2022-10-31', $halloween2022->format('Y-m-d'));


    }


    /**


    * @test


    * @group learning


    */


    public function DateTimeImmutableのaddは自身の状態を変更せず新しい状態を伴う新しいインスタンスを返す(): void


    {


    $halloween = new \DateTimeImmutable('2021-10-31');


    $oneYear = \DateInterval::createFromDateString('1 year');


    $halloween2022 = $halloween->add($oneYear);


    $this->assertNotSame($halloween, $halloween2022);


    $this->assertEquals('2021-10-31', $halloween->format('Y-m-d'));


    $this->assertEquals('2022-10-31', $halloween2022->format('Y-m-d'));


    }
    %BUF5JNFͱ%BUF5JNF*NNVUBCMFͷҧ͍Λֶशςετʹ͢Δ
    ֶशςετʢֶͼ͕໨తͷςετʣΛ
    ݟ෼͚ΔͨΊʹ
    MFBSOJOHλάΛ͚͍ͭͯ·͢
    ֶ͕͜͜ͼ
    ֶ͕͜͜ͼ

    View Slide

  14. ٙ໰Λςετʹ͢Δ

    View Slide

  15. /**


    * @test


    * @group learning


    */


    public function 同じ時刻を指している場合はタイムゾーンが異なっても等価とみなされる(): void


    {


    $utc = new DateTimeImmutable('2021-12-24T15:00:00', new DateTimeZone('UTC'));


    $jst = new DateTimeImmutable('2021-12-25T00:00:00', new DateTimeZone('Asia/Tokyo'));


    $this->assertTrue($utc == $jst);


    }
    ٙ໰Λςετʹ͢Δ
    ςετʹฉ͍ͯΈΕ͹͍͍

    View Slide

  16. ڻ͖Λςετʹ͢Δ
    ྫ͑͹ʜʜ

    View Slide

  17. ί
    ϯ
    ε
    τ
    ϥ
    Ϋ
    λ
    ͸


    Ұ
    ճ
    ͠
    ͔
    ݺ
    ΂
    ͳ
    ͍
    ͱ



    ֮
    ͠
    ͯ
    ͍
    ͨ
    ʁ















    Ұ


    ͍
    ͭ
    ͔
    Β
    ŠŠŠŠŠŠ

    View Slide

  18. /**


    * @test


    * @group learning


    */


    public function コンストラクタをもう一度呼ぶと破壊的変更ができてしまう(): void


    {


    $dt = new \DateTimeImmutable('2021-12-24');


    $this->assertSame('2021-12-24', $dt->format('Y-m-d'));


    $dt->__construct('2022-01-01');


    $this->assertSame('2022-01-01', $dt->format('Y-m-d'));


    }
    ͳΜʜʜͩͱʜʜʂʁ

    ໌ࣔతʹݺ΂ͯ͠·͏
    ༨ஊ͜ͷςετίʔυΛ͖͔͚ͬʹQIQTSDʹJTTVFͱͯ͠ใࠂ͞Εɺٞ࿦͕ߦΘΕ·ͨ͠ɻ
    IUUQTHJUIVCDPNQIQQIQTSDJTTVFT
    ༨ஊ͜ͷςετίʔυΛ͖͔͚ͬʹ੩తղੳπʔϧ1)14UBOͱ1TBMNʹػೳఏҊ͕ߦΘΕɺ
    1)14UBOʹ!NVOP@͞Μ͕࡞੒ͨ͠QVMMSFRVFTU͕࠾༻͞ΕɺϦϦʔε͞Ε·ͨ͠ɻ
    IUUQTHJUIVCDPNQIQTUBOQIQTUBOTSDQVMM

    View Slide

  19. ֶश༻ςετ
    ِཅੑͱِӄੑ
    ςεταΠζ
    ςετμϒϧ
    ςετϐϥϛου
    ࣗಈςετͷαΠζμ΢ϯઓུ
    "HFOEB࿈ࡌ֤ճͷςʔϚ
    🦁

    View Slide

  20. ࣗಈςετͷ৴པੑΛ
    Ή͠͹Ήݱ৅Λཧղ͢Δ

    View Slide

  21. ςετࣗಈԽͱاۀͷۀ੷ͷҼՌؔ܎
    IUUQTXXXBNB[PODPKQEQ
    ςετͷࣗಈԽʹ͓͍ͯɺ*5ύϑΥʔϚϯεͷ

    ༧ଌई౓ͱͳΓ͏Δ͜ͱ͕൑໌ͨ͠ͷ͸࣍ͷͭ
    ৴པੑͷߴ͍ࣗಈςετΛඋ͑Δ͜ͱ
    ։ൃऀओମͰड͚ೖΕςετΛ࡞੒ɾ؅ཧ͠ɺ

    खݩͷ։ൃ؀ڥͰ؆୯ʹ࠶ݱɾमਖ਼Ͱ͖Δ͜ͱ
    ʰ-FBOͱ%FW0QTͷՊֶʱQʢ˞༁ΛҰ෦มߋʣ

    View Slide

  22. IUUQTXXXBNB[PODPKQEQ
    ςετʹ߹֨ͨ͠ιϑτ΢ΣΞͰ͋Ε͹ϦϦʔεՄೳɺෆ߹֨Ͱ͋Ε͹ॏେͳ
    ෆ۩߹͕͋ΔɺͱνʔϜ͕֬৴Ͱ͖ΔΑ͏ͳςετΛ࣮ࢪ͍ͯ͠Δ͜ͱ
    ޡݕ஌ʢِཅੑGBMTFQPTJUJWFʣ΍ݟಀ͠ʢِӄੑGBMTFOFHBUJWFʣ͕ଟ
    ͘ɺ৴པੑʹ͚ܽΔςετεΠʔτ͕͋·Γʹ΋ଟ͗͢Δ
    ৴པ౓ͷߴ͍ςετεΠʔτΛ࡞Γ্͛Δܧଓతͳ౒ྗͱ

    ౤ࢿ͸Ձ஋͕͋Δ
    ʰ-FBOͱ%FW0QTͷՊֶʱQʢ˞༁ΛҰ෦มߋʣ
    ৴པੑͷߴ͍ࣗಈςετΛඋ͑Δ͜ͱ

    View Slide

  23. ِཅੑͱِӄੑ
    IUUQTHJIZPKQEFWTFSJBMTBWBOOBMFUUFS

    View Slide

  24. ِཅੑͱِӄੑͷύλʔϯ
    w ِཅੑ
    w ੬͍ςετ CSJUUMFUFTU GSBHJMFUFTU

    w ৴པෆೳςετ
    fl
    BLZUFTU

    w ِӄੑ
    w ۭৼΓ
    w ΧόϨοδෆ଍
    w ςετର৅ϩδοΫͷςετίʔυ΁ͷ࿙Εग़͠

    View Slide

  25. // プロダクトコード


    class Item {


    // コンストラクタ割愛


    tax_amount() {


    const rate = (this.tax_rate / 100);


    return (this.price / (1 + rate)) * rate;


    }


    }


    // テストコード


    it('税込価格から税額を返す', () => {


    const item = new Item('技評茶', 130, 8);


    const expected = (130 / (1 + (8 / 100))) * (8 / 100);


    assert.equal(item.tax_amount(), expected);


    });
    ྫςετର৅ϩδοΫͷςετίʔυ΁ͷ࿙Εग़͠
    ԁະຬͷ୺਺͕ൃੜ͢Δ
    όά͕͋Δ
    ςετίʔυͷํ΋ಉ͡ϩδοΫͰ
    ظ଴஋Λܭࢉ͍ͯ͠ΔͷͰ
    ςετ͕੒ޭͯ͠͠·͏

    View Slide

  26. ৴པෆೳੑʢ
    fl
    BLJOFTTʣ͕ʹ઀ۙ͢Δͱɺςετ͸Ձ஋Λࣦ͍࢝ΊΔ
    IUUQTXXXPSFJMMZDPKQCPPLT
    ʰ(PPHMFͷιϑτ΢ΣΞΤϯδχΞϦϯάʱQ

    View Slide

  27. ֶश༻ςετ
    ِཅੑͱِӄੑ
    ςεταΠζ
    ςετμϒϧ
    ςετϐϥϛου
    ࣗಈςετͷαΠζμ΢ϯઓུ
    "HFOEB࿈ࡌ֤ճͷςʔϚ
    🦁

    View Slide

  28. ࣗಈςετͱ$*ʹϑΟοτ͢Δ
    ໌֬ͳςετ෼ྨج४

    View Slide

  29. օ͞Μʹ͓࢕͍͠·͢
    🙋🙋🙋
    σʔλϕʔεʹΞΫηε͢Δͷ͸Ϣχοτςετ :FT/P
    ωοτϫʔΫʹΞΫηε͢Δͷ͸Ϣχοτςετ :FT/P
    ϑΝΠϧʹΞΫηε͢Δͷ͸Ϣχοτςετ :FT/P
    ݱࡏ࣌ࠁʹΞΫηε͢Δͷ͸Ϣχοτςετ :FT/P
    ґଘઌͷΫϥεʹຊ෺Λ࢖͏ͷ͸Ϣχοτςετ :FT/P

    View Slide

  30. IUUQTNBSUJOGPXMFSDPNCMJLJ6OJU5FTUIUNM
    6OJU5FTUͷ6OJUͬͯԿʁ

    View Slide

  31. 5FTU4J[FΑΓᐆດ͞ͷগͳ͍෼ྨ

    View Slide

  32. IUUQTUFTUJOHHPPHMFCMPHDPNUFTUTJ[FTIUNM
    5FTU4J[F

    View Slide

  33. 4NBMM

    ʢ୯Ұϓϩηεʣ
    .FEJVN

    ʢ୯ҰϚγϯʣ
    -BSHF

    ʢ੍໿ͳ͠ʣ
    6OJU
    ൺ཰

    େ͍ʹਪ঑
    ආ͚͍͕ͨ
    ͔ͨ͠ͳ͍ͱ͖΋
    ࠷ѱ͕ͩ
    Α͘ݟ͔͚Δ
    *OUFHSBUJPO
    ൺ཰

    ॻ͚ΔͳΒ
    ίεύྑ͠
    ී௨
    Ͱ͖Ε͹
    ආ͚͍ͨ
    &&
    ൺ཰

    ݪཧ্ෆՄೳʹ͍͕ۙ
    খ͍͞γεςϜͳΒՄೳʁ
    খ͍͞γεςϜ
    ͳΒՄೳ
    ී௨͔ͭ
    $6+ʹߜΓ͍ͨ
    5FTU4DPQF
    5FTU4J[F
    5FTU4DPQFͱ5FTU4J[F

    View Slide

  34. 4NBMM

    ʢ୯Ұϓϩηεʣ
    .FEJVN

    ʢ୯ҰϚγϯʣ
    -BSHF

    ʢ੍໿ͳ͠ʣ
    6OJU
    ൺ཰

    େ͍ʹਪ঑
    ආ͚͍͕ͨ
    ͔ͨ͠ͳ͍ͱ͖΋
    ࠷ѱ͕ͩ
    Α͘ݟ͔͚Δ
    *OUFHSBUJPO
    ൺ཰

    ॻ͚ΔͳΒ
    ίεύྑ͠
    ී௨
    Ͱ͖Ε͹
    ආ͚͍ͨ
    &&
    ൺ཰

    ݪཧ্ෆՄೳʹ͍͕ۙ
    খ͍͞γεςϜͳΒՄೳʁ
    খ͍͞γεςϜ
    ͳΒՄೳ
    ී௨͔ͭ
    $6+ʹߜΓ͍ͨ
    5FTU4DPQF
    5FTU4J[F
    5FTU4DPQFͱ5FTU4J[F
    ίεύྑ͠
    ίεύѱ͠

    View Slide

  35. ֶश༻ςετ
    ِཅੑͱِӄੑ
    ςεταΠζ
    ςετμϒϧ
    ςετϐϥϛου
    ࣗಈςετͷαΠζμ΢ϯઓུ
    "HFOEB࿈ࡌ֤ճͷςʔϚ
    🦁

    View Slide

  36. ஧࣮ੑͱܾఆੑͷ
    τϨʔυΦϑΛཧղ͢Δ

    View Slide

  37. IUUQYVOJUQBUUFSOTDPN5FTU%PVCMFIUNM
    ςετμϒϧࣗಈςετ༻ͷِ෺

    View Slide

  38. IUUQYVOJUQBUUFSOTDPN5FTU%PVCMFIUNM
    ςετμϒϧͷ෼ྨʢY651ʣ

    View Slide

  39. ςετμϒϧͷར఺ͱ஫ҙ఺
    IUUQTXXXBNB[PODPKQEQ
    w ར఺
    w ςετ͠ʹ͍͘΋ͷΛςετՄೳʹ͢Δ
    w ςετͷ଎౓ͱܾఆੑΛ޲্ͤ͞Δ
    w ஫ҙ఺
    w ςετ͕੬͘ͳΓɺมߋΛ๦͛Δʢར఺ͷཪฦ͠ʣ
    w ςετͷِӄੑΛট͘ʢࣗ࡞ࣗԋςετʣ

    View Slide

  40. ֶश༻ςετ
    ِཅੑͱِӄੑ
    ςεταΠζ
    ςετμϒϧ
    ςετϐϥϛου
    ࣗಈςετͷαΠζμ΢ϯઓུ
    "HFOEB࿈ࡌ֤ճͷςʔϚ
    🦁

    View Slide

  41. ࣗಈςετͷ৴པੑΛ
    த௕ظతʹอͭ
    ࠷దͳόϥϯε

    View Slide

  42. Ϣχοτ
    ΠϯςάϨʔγϣϯ
    &&
    ίετ
    ஧࣮ੑ
    ଎౓
    ςετέʔε਺
    ߴ
    ௿
    ௿
    ߴ
    ܾఆੑ
    ςετϐϥϛου

    View Slide

  43. ςετϐϥϛουͱΞΠεΫϦʔϜίʔϯΞϯνύλʔϯ
    IUUQTXBUJSNFMPOCMPHJOUSPEVDJOHUIFTPGUXBSFUFTUJOHJDFDSFBNDPOF

    View Slide

  44. ࠞཚ͸ʮϢχοτʯʮΠϯςάϨʔγϣϯʯͷղऍͷϒϨ͔Βੜ͕ͪ͡

    View Slide

  45. Ϣχοτ
    ΠϯςάϨʔγϣϯ
    &&
    ίετ
    ஧࣮ੑ
    ଎౓
    ςετέʔε਺
    ߴ
    ௿
    ௿
    ߴ
    ܾఆੑ
    ϒϨͷগͳ͍ςετͷ෼ྨج४͸ʜʜʁ

    View Slide

  46. ίετ
    ஧࣮ੑ
    ଎౓
    ߴ
    ௿
    ௿
    ߴ
    ܾఆੑ
    ϒϨͷগͳ͍ςετͷ෼ྨج४ˠςεταΠζ
    4NBMM
    .FEJVN
    -BSHF
    ςετέʔε਺

    View Slide

  47. IUUQTXBUJSNFMPOCMPHJOUSPEVDJOHUIFTPGUXBSFUFTUJOHJDFDSFBNDPOF
    4NBMM
    .FEJVN
    -BSHF
    खಈςετ
    Ͱ΋ɺଟ͘ͷݱ৔Ͱ͸ΞΠεΫϦʔϜίʔϯ͔Β࢝·ΔʢͦΕ͸ѱ͍͜ͱͰ͸ͳ͍ʣ

    View Slide

  48. ֶश༻ςετ
    ِཅੑͱِӄੑ
    ςεταΠζ
    ςετμϒϧ
    ςετϐϥϛου
    ࣗಈςετͷαΠζμ΢ϯઓུ
    "HFOEB࿈ࡌ֤ճͷςʔϚ
    🦁

    View Slide

  49. Ͳ͏΍ͬͯΞΠεΫϦʔϜίʔϯΛϐϥϛουʹ͢Δ͔
    IUUQTXBUJSNFMPOCMPHJOUSPEVDJOHUIFTPGUXBSFUFTUJOHJDFDSFBNDPOF
    4NBMM
    .FEJVN
    -BSHF
    खಈςετ
    4NBMM
    .FEJVN
    -BSHF

    View Slide

  50. IUUQTXBUJSNFMPOCMPHJOUSPEVDJOHUIFTPGUXBSFUFTUJOHJDFDSFBNDPOF
    4NBMM
    .FEJVN
    -BSHF
    खಈςετ
    -BSHF͔Β.FEJVN΁

    View Slide

  51. IUUQYVOJUQBUUFSOTDPN5FTU%PVCMFIUNM
    -BSHF͔Β.FEJVN΁'BLF0CKFDU
    'BLF͸ࣗಈςετ༻ͷ୅ସ࣮૷ɻ
    %ZOBNP%#ʹର͢Δ%ZOBNP%#MPDBM΍MPDBLTUBDL͕୅දྫɻ
    ίϯςφͰಈ࡞ͤ͞ΒΕΕ͹ςεταΠζ͕.FEJVNʹऩ·Δɻ

    View Slide

  52. IUUQTXBUJSNFMPOCMPHJOUSPEVDJOHUIFTPGUXBSFUFTUJOHJDFDSFBNDPOF
    4NBMM
    .FEJVN
    -BSHF
    खಈςετ
    .FEJVN͔Β4NBMM΁

    View Slide

  53. .FEJVN͔Β4NBMM΁)VNCMF0CKFDU
    IUUQTXXXBNB[PODPKQEQ
    ςετ༰қੑΛԼ͍͛ͯΔཁૉΛബ͘੾Γग़͠ɺ
    ςετՄೳൣғΛ޿͘औΔجຊύλʔϯ

    View Slide

  54. ΞΠεΫϦʔϜίʔϯ͔Βϐϥϛου΁
    IUUQTXBUJSNFMPOCMPHJOUSPEVDJOHUIFTPGUXBSFUFTUJOHJDFDSFBNDPOF
    4NBMM
    .FEJVN
    -BSHF
    खಈςετ
    4NBMM
    .FEJVN
    -BSHF

    View Slide

  55. ֶश༻ςετ
    ِཅੑͱِӄੑ
    ςεταΠζ
    ςετμϒϧ
    ςετϐϥϛου
    ࣗಈςετͷαΠζμ΢ϯઓུ
    🦁
    🦁
    🦁
    🦁
    🦁
    ͜Ε·Ͱͷ஌ݟΛ·ͱΊΔͱ

    View Slide

  56. 4NBMM
    .FEJVN
    -BSHF
    ίετ
    ஧࣮ੑ
    ଎౓
    ςετέʔε਺
    ߴ
    ௿
    ௿
    ߴ
    ܾఆੑ
    ·ͱΊςετμϒϧͰαΠζμ΢ϯͯ͠ɺ֤αΠζΛϐϥϛουܕʹ഑ஔ͠ɺςετશମͷ৴པੑΛҡ࣋͢Δ
    ςετμϒϧ
    ςετμϒϧ
    ςετ༰қੑઃܭ
    υϝΠϯઃܭ

    View Slide

  57. ͓ΘΓʹ

    View Slide

  58. ࣦ৬ͷةػྑॻ͗͢Δ
    IUUQTCPPLNZOBWJKQFDQSPEVDUTEFUBJMJE

    View Slide

  59. ࣦ৬ͷةػ͍͔ʹ΋ࢲͷݴ͍ͦ͏ͳ͜ͱΛݴ͏"*
    IUUQTUXJUUFSDPNLBXBTJNBTUBUVT

    View Slide

  60. IUUQTHJIZPKQNBHB[JOFXEQSFTTTVTQFOEFE
    ൵͍͓͠஌Βͤ

    View Slide

  61. ͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠
    📷🙆 🙆 2JJUB$POGFSFODF

    View Slide