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
サバンナ便り〜自動テストに関する連載で得られた知見のまとめ(2023年5月版)〜 / Auto...
Search
Takuto Wada
PRO
May 17, 2023
Programming
27
22k
サバンナ便り〜自動テストに関する連載で得られた知見のまとめ(2023年5月版)〜 / Automated Test Knowledge from Savanna 202305 edition
2023/05/17(水)
Qiita Conference 2023
Takuto Wada
PRO
May 17, 2023
Tweet
Share
More Decks by Takuto Wada
See All by Takuto Wada
組織に自動テストを書く文化を根付かせる戦略(2024冬版) / Building Automated Test Culture 2024 Winter Edition
twada
PRO
26
7.2k
ピラミッド、アイスクリームコーン、SMURF: 自動テストの最適バランスを求めて / Pyramid Ice-Cream-Cone and SMURF
twada
PRO
10
1.5k
組織に自動テストを書く文化を根付かせる戦略(2024秋版) / Building Automated Test Culture 2024 Autumn Edition
twada
PRO
15
6k
これまでと違う学び方をしたら挫折せずにRustを学べた話 / Programming Rust techramen24conf LT
twada
PRO
26
22k
開発生産性の観点から考える自動テスト(2024/06版) / Automated Test Knowledge from Savanna 202406 Findy dev-prod-con edition
twada
PRO
33
23k
自動テスト実行結果の目的を整理する / Organizing objectives of automated test results
twada
PRO
14
3.2k
変更容易性と理解容易性を支える自動テスト(2024/02版) / Automated Test Knowledge from Savanna 202402 YAPC::Hiroshima edition
twada
PRO
22
13k
実録レガシーコード改善 / Working with Legacy Code: the True Record
twada
PRO
103
47k
Property-based Testing の位置付け / Intro to Property-based Testing
twada
PRO
11
6.4k
Other Decks in Programming
See All in Programming
DevFest - Serverless 101 with Google Cloud Functions
tunmise
0
130
今年一番支援させていただいたのは認証系サービスでした
satoshi256kbyte
1
280
103 Early Hints
sugi_0000
1
330
数十万行のプロジェクトを Scala 2から3に完全移行した
xuwei_k
0
1.1k
Findy Team+ Awardを受賞したかった!ベストプラクティス応募内容をふりかえり、開発生産性向上もふりかえる / Findy Team Plus Award BestPractice and DPE Retrospective 2024
honyanya
0
130
見えないメモリを観測する: PHP 8.4 `pg_result_memory_size()` とSQL結果のメモリ管理
kentaroutakeda
0
900
コンテナをたくさん詰め込んだシステムとランタイムの変化
makihiro
1
180
KubeCon NA 2024の全DB関連セッションを紹介
nnaka2992
0
110
ゆるやかにgolangci-lintのルールを強くする / Kyoto.go #56
utgwkk
2
810
開発者とQAの越境で自動テストが増える開発プロセスを実現する
92thunder
1
230
月刊 競技プログラミングをお仕事に役立てるには
terryu16
1
1.1k
週次リリースを実現するための グローバルアプリ開発
tera_ny
1
860
Featured
See All Featured
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
113
50k
Fireside Chat
paigeccino
34
3.1k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
132
33k
Making the Leap to Tech Lead
cromwellryan
133
9k
Building an army of robots
kneath
302
44k
How STYLIGHT went responsive
nonsquared
96
5.3k
Building Adaptive Systems
keathley
38
2.3k
Keith and Marios Guide to Fast Websites
keithpitt
410
22k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
7
560
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
191
16k
GraphQLとの向き合い方2022年版
quramy
44
13k
4 Signs Your Business is Dying
shpigford
182
21k
Transcript
ాਓʢ!U@XBEBʣ αόϯφศΓ ࣗಈςετʹؔ͢Δ࿈ࡌͰಘΒΕͨݟͷ·ͱΊ ൛ 📷🙆 🙆 2JJUB$POGFSFODF .BZ
ΞοϓσʔτΛॏͶΔߨԋͷ݄൛Ͱ͢ʢ࿈ࡌୈճ·Ͱऩʣ IUUQTTQFBLFSEFDLDPNUXBEB ίϥϜ࿈ࡌͷୈճ·Ͱऩ͍ͯ͠·͢
ߨԋͷจࣈى͜͠ࠓޙެ։༧ఆͰ͢ ެ։͞ΕͨΒTQFBLFSEFDLͷಉҰ63-Ͱ ࢿྉΛΞοϓσʔτ͠·͢
t-wada t_wada twada 📷🙆 📹🙅 🙆 ࣗݾհ #QiitaConference
ٕज़ॻͷग़൛ʹؔΘ͍ͬͯ·͢
αόϯφศΓʜʜʁ
IUUQTUXBEBIBUFOBCMPHKQFOUSZXEQSFTTTBWBOOBDPMVNO 8&# %#13&44ʹίϥϜΛ࿈ࡌ͍ͯ͠·͢
IUUQTUXBEBIBUFOBCMPHKQFOUSZXEQSFTTTBWBOOBDPMVNO 8&# %#13&44ʹίϥϜΛ࿈ࡌ͍ͯ͠·͢
ΑΖ͓͘͠ئ͍͠·͢ 📷🙆 🙆 2JJUB$POGFSFODF
ֶश༻ςετ ِཅੑͱِӄੑ ςεταΠζ ςετμϒϧ ςετϐϥϛου ࣗಈςετͷαΠζμϯઓུ 🦁 "HFOEB࿈ࡌ֤ճͷςʔϚ
ֶͼΛࣗಈςετͱͯ͠ॻ͘ ଈ࣌ੑͱ࠶ݱੑ
ֶशྫ1)1ͷ%BUF5JNFͱ%BUF5JNF*NNVUBCMF IUUQTXXXQIQOFUNBOVBMKBDMBTTEBUFUJNFJNNVUBCMFQIQ
/** * @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λάΛ͚͍ͭͯ·͢ ֶ͕͜͜ͼ ֶ͕͜͜ͼ
ٙΛςετʹ͢Δ
/** * @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); } ٙΛςετʹ͢Δ ςετʹฉ͍ͯΈΕ͍͍
ڻ͖Λςετʹ͢Δ ྫ͑ʜʜ
ί ϯ ε τ ϥ Ϋ λ
Ұ ճ ͠ ͔ ݺ ͳ ͍ ͱ ࡨ ֮ ͠ ͯ ͍ ͨ ʁ ㅟ ㅟ ㅟ ㅟ ㅟ ㅟ ㅟ ㅟ ㅟ ㅟ ㅟ ㅟ ㅟ ㅟ ㅟ Ұ ମ ͍ ͭ ͔ Β
/** * @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
ֶश༻ςετ ِཅੑͱِӄੑ ςεταΠζ ςετμϒϧ ςετϐϥϛου ࣗಈςετͷαΠζμϯઓུ "HFOEB࿈ࡌ֤ճͷςʔϚ 🦁
ࣗಈςετͷ৴པੑΛ Ή͠ΉݱΛཧղ͢Δ
ςετࣗಈԽͱاۀͷۀͷҼՌؔ IUUQTXXXBNB[PODPKQEQ ςετͷࣗಈԽʹ͓͍ͯɺ*5ύϑΥʔϚϯεͷ ༧ଌईͱͳΓ͏Δ͜ͱ͕໌ͨ͠ͷ࣍ͷͭ ৴པੑͷߴ͍ࣗಈςετΛඋ͑Δ͜ͱ ։ൃऀओମͰड͚ೖΕςετΛ࡞ɾཧ͠ɺ
खݩͷ։ൃڥͰ؆୯ʹ࠶ݱɾमਖ਼Ͱ͖Δ͜ͱ ʰ-FBOͱ%FW0QTͷՊֶʱQʢ˞༁ΛҰ෦มߋʣ
IUUQTXXXBNB[PODPKQEQ ςετʹ߹֨ͨ͠ιϑτΣΞͰ͋ΕϦϦʔεՄೳɺෆ߹֨Ͱ͋Εॏେͳ ෆ۩߹͕͋ΔɺͱνʔϜ͕֬৴Ͱ͖ΔΑ͏ͳςετΛ࣮ࢪ͍ͯ͠Δ͜ͱ ޡݕʢِཅੑGBMTFQPTJUJWFʣݟಀ͠ʢِӄੑGBMTFOFHBUJWFʣ͕ଟ ͘ɺ৴པੑʹ͚ܽΔςετεΠʔτ͕͋·Γʹଟ͗͢Δ ৴པͷߴ͍ςετεΠʔτΛ࡞Γ্͛Δܧଓతͳྗͱ ࢿՁ͕͋Δ
ʰ-FBOͱ%FW0QTͷՊֶʱQʢ˞༁ΛҰ෦มߋʣ ৴པੑͷߴ͍ࣗಈςετΛඋ͑Δ͜ͱ
ِཅੑͱِӄੑ IUUQTHJIZPKQEFWTFSJBMTBWBOOBMFUUFS
ِཅੑͱِӄੑͷύλʔϯ w ِཅੑ w ੬͍ςετ CSJUUMFUFTU GSBHJMFUFTU w ৴པෆೳςετ
fl BLZUFTU w ِӄੑ w ۭৼΓ w ΧόϨοδෆ w ςετରϩδοΫͷςετίʔυͷ࿙Εग़͠
// プロダクトコード 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); }); ྫςετରϩδοΫͷςετίʔυͷ࿙Εग़͠ ԁະຬͷ͕ൃੜ͢Δ όά͕͋Δ ςετίʔυͷํಉ͡ϩδοΫͰ ظΛܭࢉ͍ͯ͠ΔͷͰ ςετ͕ޭͯ͠͠·͏
৴པෆೳੑʢ fl BLJOFTTʣ͕ʹۙ͢ΔͱɺςετՁΛࣦ͍࢝ΊΔ IUUQTXXXPSFJMMZDPKQCPPLT ʰ(PPHMFͷιϑτΣΞΤϯδχΞϦϯάʱQ
ֶश༻ςετ ِཅੑͱِӄੑ ςεταΠζ ςετμϒϧ ςετϐϥϛου ࣗಈςετͷαΠζμϯઓུ "HFOEB࿈ࡌ֤ճͷςʔϚ 🦁
ࣗಈςετͱ$*ʹϑΟοτ͢Δ ໌֬ͳςετྨج४
օ͞Μʹ͓͍͠·͢ 🙋🙋🙋 σʔλϕʔεʹΞΫηε͢ΔͷϢχοτςετ :FT/P ωοτϫʔΫʹΞΫηε͢ΔͷϢχοτςετ :FT/P ϑΝΠϧʹΞΫηε͢ΔͷϢχοτςετ :FT/P ݱࡏ࣌ࠁʹΞΫηε͢ΔͷϢχοτςετ :FT/P
ґଘઌͷΫϥεʹຊΛ͏ͷϢχοτςετ :FT/P
IUUQTNBSUJOGPXMFSDPNCMJLJ6OJU5FTUIUNM 6OJU5FTUͷ6OJUͬͯԿʁ
5FTU4J[FΑΓᐆດ͞ͷগͳ͍ྨ
IUUQTUFTUJOHHPPHMFCMPHDPNUFTUTJ[FTIUNM 5FTU4J[F
4NBMM ʢ୯Ұϓϩηεʣ .FEJVN ʢ୯ҰϚγϯʣ -BSHF ʢ੍ͳ͠ʣ 6OJU
ൺ େ͍ʹਪ ආ͚͍͕ͨ ͔ͨ͠ͳ͍ͱ͖ ࠷ѱ͕ͩ Α͘ݟ͔͚Δ *OUFHSBUJPO ൺ ॻ͚ΔͳΒ ίεύྑ͠ ී௨ Ͱ͖Ε ආ͚͍ͨ && ൺ ݪཧ্ෆՄೳʹ͍͕ۙ খ͍͞γεςϜͳΒՄೳʁ খ͍͞γεςϜ ͳΒՄೳ ී௨͔ͭ $6+ʹߜΓ͍ͨ 5FTU4DPQF 5FTU4J[F 5FTU4DPQFͱ5FTU4J[F
4NBMM ʢ୯Ұϓϩηεʣ .FEJVN ʢ୯ҰϚγϯʣ -BSHF ʢ੍ͳ͠ʣ 6OJU
ൺ େ͍ʹਪ ආ͚͍͕ͨ ͔ͨ͠ͳ͍ͱ͖ ࠷ѱ͕ͩ Α͘ݟ͔͚Δ *OUFHSBUJPO ൺ ॻ͚ΔͳΒ ίεύྑ͠ ී௨ Ͱ͖Ε ආ͚͍ͨ && ൺ ݪཧ্ෆՄೳʹ͍͕ۙ খ͍͞γεςϜͳΒՄೳʁ খ͍͞γεςϜ ͳΒՄೳ ී௨͔ͭ $6+ʹߜΓ͍ͨ 5FTU4DPQF 5FTU4J[F 5FTU4DPQFͱ5FTU4J[F ίεύྑ͠ ίεύѱ͠
ֶश༻ςετ ِཅੑͱِӄੑ ςεταΠζ ςετμϒϧ ςετϐϥϛου ࣗಈςετͷαΠζμϯઓུ "HFOEB࿈ࡌ֤ճͷςʔϚ 🦁
࣮ੑͱܾఆੑͷ τϨʔυΦϑΛཧղ͢Δ
IUUQYVOJUQBUUFSOTDPN5FTU%PVCMFIUNM ςετμϒϧࣗಈςετ༻ͷِ
IUUQYVOJUQBUUFSOTDPN5FTU%PVCMFIUNM ςετμϒϧͷྨʢY651ʣ
ςετμϒϧͷརͱҙ IUUQTXXXBNB[PODPKQEQ w ར w ςετ͠ʹ͍͘ͷΛςετՄೳʹ͢Δ w ςετͷͱܾఆੑΛ্ͤ͞Δ w ҙ
w ςετ͕੬͘ͳΓɺมߋΛ͛Δʢརͷཪฦ͠ʣ w ςετͷِӄੑΛট͘ʢࣗ࡞ࣗԋςετʣ
ֶश༻ςετ ِཅੑͱِӄੑ ςεταΠζ ςετμϒϧ ςετϐϥϛου ࣗಈςετͷαΠζμϯઓུ "HFOEB࿈ࡌ֤ճͷςʔϚ 🦁
ࣗಈςετͷ৴པੑΛ தظతʹอͭ ࠷దͳόϥϯε
Ϣχοτ ΠϯςάϨʔγϣϯ && ίετ ࣮ੑ ςετέʔε ߴ
ߴ ܾఆੑ ςετϐϥϛου
ςετϐϥϛουͱΞΠεΫϦʔϜίʔϯΞϯνύλʔϯ IUUQTXBUJSNFMPOCMPHJOUSPEVDJOHUIFTPGUXBSFUFTUJOHJDFDSFBNDPOF
ࠞཚʮϢχοτʯʮΠϯςάϨʔγϣϯʯͷղऍͷϒϨ͔Βੜ͕ͪ͡
Ϣχοτ ΠϯςάϨʔγϣϯ && ίετ ࣮ੑ ςετέʔε ߴ
ߴ ܾఆੑ ϒϨͷগͳ͍ςετͷྨج४ʜʜʁ
ίετ ࣮ੑ ߴ ߴ ܾఆੑ ϒϨͷগͳ͍ςετͷྨج४ˠςεταΠζ 4NBMM
.FEJVN -BSHF ςετέʔε
IUUQTXBUJSNFMPOCMPHJOUSPEVDJOHUIFTPGUXBSFUFTUJOHJDFDSFBNDPOF 4NBMM .FEJVN -BSHF खಈςετ Ͱɺଟ͘ͷݱͰΞΠεΫϦʔϜίʔϯ͔Β࢝·ΔʢͦΕѱ͍͜ͱͰͳ͍ʣ
ֶश༻ςετ ِཅੑͱِӄੑ ςεταΠζ ςετμϒϧ ςετϐϥϛου ࣗಈςετͷαΠζμϯઓུ "HFOEB࿈ࡌ֤ճͷςʔϚ 🦁
Ͳ͏ͬͯΞΠεΫϦʔϜίʔϯΛϐϥϛουʹ͢Δ͔ IUUQTXBUJSNFMPOCMPHJOUSPEVDJOHUIFTPGUXBSFUFTUJOHJDFDSFBNDPOF 4NBMM .FEJVN -BSHF खಈςετ 4NBMM .FEJVN -BSHF
IUUQTXBUJSNFMPOCMPHJOUSPEVDJOHUIFTPGUXBSFUFTUJOHJDFDSFBNDPOF 4NBMM .FEJVN -BSHF खಈςετ -BSHF͔Β.FEJVN
IUUQYVOJUQBUUFSOTDPN5FTU%PVCMFIUNM -BSHF͔Β.FEJVN'BLF0CKFDU 'BLFࣗಈςετ༻ͷସ࣮ɻ %ZOBNP%#ʹର͢Δ%ZOBNP%#MPDBMMPDBLTUBDL͕දྫɻ ίϯςφͰಈ࡞ͤ͞ΒΕΕςεταΠζ͕.FEJVNʹऩ·Δɻ
IUUQTXBUJSNFMPOCMPHJOUSPEVDJOHUIFTPGUXBSFUFTUJOHJDFDSFBNDPOF 4NBMM .FEJVN -BSHF खಈςετ .FEJVN͔Β4NBMM
.FEJVN͔Β4NBMM)VNCMF0CKFDU IUUQTXXXBNB[PODPKQEQ ςετ༰қੑΛԼ͍͛ͯΔཁૉΛബ͘Γग़͠ɺ ςετՄೳൣғΛ͘औΔجຊύλʔϯ
ΞΠεΫϦʔϜίʔϯ͔Βϐϥϛου IUUQTXBUJSNFMPOCMPHJOUSPEVDJOHUIFTPGUXBSFUFTUJOHJDFDSFBNDPOF 4NBMM .FEJVN -BSHF खಈςετ 4NBMM .FEJVN -BSHF
ֶश༻ςετ ِཅੑͱِӄੑ ςεταΠζ ςετμϒϧ ςετϐϥϛου ࣗಈςετͷαΠζμϯઓུ 🦁 🦁 🦁 🦁
🦁 ͜Ε·ͰͷݟΛ·ͱΊΔͱ
4NBMM .FEJVN -BSHF ίετ ࣮ੑ ςετέʔε ߴ
ߴ ܾఆੑ ·ͱΊςετμϒϧͰαΠζμϯͯ͠ɺ֤αΠζΛϐϥϛουܕʹஔ͠ɺςετશମͷ৴པੑΛҡ࣋͢Δ ςετμϒϧ ςετμϒϧ ςετ༰қੑઃܭ υϝΠϯઃܭ
͓ΘΓʹ
ࣦ৬ͷةػྑॻ͗͢Δ IUUQTCPPLNZOBWJKQFDQSPEVDUTEFUBJMJE
ࣦ৬ͷةػ͍͔ʹࢲͷݴ͍ͦ͏ͳ͜ͱΛݴ͏"* IUUQTUXJUUFSDPNLBXBTJNBTUBUVT
IUUQTHJIZPKQNBHB[JOFXEQSFTTTVTQFOEFE ൵͍͓͠Βͤ
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ 📷🙆 🙆 2JJUB$POGFSFODF