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
26
20k
サバンナ便り〜自動テストに関する連載で得られた知見のまとめ(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
ピラミッド、アイスクリームコーン、SMURF: 自動テストの最適バランスを求めて / Pyramid Ice-Cream-Cone and SMURF
twada
PRO
7
550
組織に自動テストを書く文化を根付かせる戦略(2024秋版) / Building Automated Test Culture 2024 Autumn Edition
twada
PRO
10
4.3k
これまでと違う学び方をしたら挫折せずにRustを学べた話 / Programming Rust techramen24conf LT
twada
PRO
20
12k
開発生産性の観点から考える自動テスト(2024/06版) / Automated Test Knowledge from Savanna 202406 Findy dev-prod-con edition
twada
PRO
30
20k
自動テスト実行結果の目的を整理する / Organizing objectives of automated test results
twada
PRO
14
3k
変更容易性と理解容易性を支える自動テスト(2024/02版) / Automated Test Knowledge from Savanna 202402 YAPC::Hiroshima edition
twada
PRO
21
12k
実録レガシーコード改善 / Working with Legacy Code: the True Record
twada
PRO
95
39k
Property-based Testing の位置付け / Intro to Property-based Testing
twada
PRO
11
6.1k
Second-System Syndrome: A tale of power-assert
twada
PRO
10
4.7k
Other Decks in Programming
See All in Programming
Tuning GraphQL on Rails
pyama86
2
730
現場で役立つモデリング 超入門
masuda220
PRO
10
2.4k
Googleのテストサイズを活用したテスト環境の構築
toms74209200
0
230
EventSourcingの理想と現実
wenas
5
1.9k
外部システム連携先が10を超えるシステムでのアーキテクチャ設計・実装事例
kiwasaki
1
160
C#/.NETのこれまでのふりかえり
tomokusaba
1
140
CPython 인터프리터 구조 파헤치기 - PyCon Korea 24
kennethanceyer
0
200
Re:proS_案内資料
rect
0
250
Vue3の一歩踏み込んだパフォーマンスチューニング2024
hal_spidernight
3
2.8k
詳細解説! ArrayListの仕組みと実装
yujisoftware
0
410
From Subtype Polymorphism To Typeclass-based Ad hoc Polymorphism- An Example
philipschwarz
PRO
0
100
OpenTelemetryでRailsのパフォーマンス分析を始めてみよう(KoR2024)
ymtdzzz
3
850
Featured
See All Featured
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
31
2.6k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
92
16k
Stop Working from a Prison Cell
hatefulcrawdad
267
20k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
5
140
[RailsConf 2023] Rails as a piece of cake
palkan
50
4.8k
Designing for humans not robots
tammielis
249
25k
Writing Fast Ruby
sferik
626
60k
What's in a price? How to price your products and services
michaelherold
243
11k
The Power of CSS Pseudo Elements
geoffreycrofte
72
5.3k
Fashionably flexible responsive web design (full day workshop)
malarkey
404
65k
Rebuilding a faster, lazier Slack
samanthasiow
79
8.6k
RailsConf 2023
tenderlove
29
870
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