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
サバンナ便り〜自動テストに関する連載で得られた知見のまとめ〜
Search
Takuto Wada
PRO
March 03, 2023
Programming
19
7.4k
サバンナ便り〜自動テストに関する連載で得られた知見のまとめ〜
2023/03/03(金)
Forkwell エンジニア文化祭 2023
Takuto Wada
PRO
March 03, 2023
Tweet
Share
More Decks by Takuto Wada
See All by Takuto Wada
ピラミッド、アイスクリームコーン、SMURF: 自動テストの最適バランスを求めて / Pyramid Ice-Cream-Cone and SMURF
twada
PRO
6
200
組織に自動テストを書く文化を根付かせる戦略(2024秋版) / Building Automated Test Culture 2024 Autumn Edition
twada
PRO
9
4.2k
これまでと違う学び方をしたら挫折せずに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
38k
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
いかにして不足・不整合なくデータ移行したか
tjmtmmnk
1
1k
Server Driven Compose With Firebase
skydoves
0
320
Importmapを使ったJavaScriptの 読み込みとブラウザアドオンの影響
swamp09
3
1.2k
Workflow automationによるインシデント原因調査の自動化
showwin
1
120
rtcamp 10 (vk-illuminati)
yumcyawiz
1
220
実践サーバーレスパフォーマンスチューニング ~その実力に迫る~ / Practical Serverless Performance Tuning ~A Close Look at its Power~
seike460
PRO
2
250
デプロイを任されたので、教わった通りにデプロイしたら障害になった件 ~俺のやらかしを越えてゆけ~
techouse
48
30k
PagerDuty を軸にした On-Call 構築と運用課題の解決 / PagerDuty Japan Community Meetup 4
horimislime
1
100
OpenTelemetryでRailsのパフォーマンス分析を始めてみよう(KoR2024)
ymtdzzz
3
780
Vue SFCのtemplateでTypeScriptの型を活用しよう
tsukkee
3
1.4k
Kubernetes for Data Engineers: Building Scalable, Reliable Data Pipelines
sucitw
1
170
Universal Linksの実装方法と陥りがちな罠
kaitokudou
1
210
Featured
See All Featured
Rebuilding a faster, lazier Slack
samanthasiow
79
8.6k
BBQ
matthewcrist
85
9.3k
A Tale of Four Properties
chriscoyier
156
23k
Why Our Code Smells
bkeepers
PRO
334
57k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
92
16k
Designing on Purpose - Digital PM Summit 2013
jponch
114
6.9k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
364
22k
Navigating Team Friction
lara
183
14k
Fashionably flexible responsive web design (full day workshop)
malarkey
404
65k
Become a Pro
speakerdeck
PRO
24
4.9k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
504
140k
Building a Modern Day E-commerce SEO Strategy
aleyda
38
6.9k
Transcript
ాਓʢ!U@XBEBʣ αόϯφศΓ ࣗಈςετʹؔ͢Δ࿈ࡌͰಘΒΕͨݟͷ·ͱΊ 📷🙆 🙆 'PSLXFMMจԽࡇ@" .BS
t-wada t_wada twada 📷🙆 📹🙅 🙆 ࣗݾհ #Forkwell文化祭_A
ٕज़ॻͷग़൛ʹؔΘ͍ͬͯ·͢
αόϯφศΓʜʜʁ
IUUQTUXBEBIBUFOBCMPHKQFOUSZXEQSFTTTBWBOOBDPMVNO 8&# %#13&44ʹίϥϜΛ࿈ࡌ͍ͯ͠·͢
IUUQTUXBEBIBUFOBCMPHKQFOUSZXEQSFTTTBWBOOBDPMVNO 8&# %#13&44ʹίϥϜΛ࿈ࡌ͍ͯ͠·͢
ΑΖ͓͘͠ئ͍͠·͢ 📷🙆 🙆 'PSLXFMMจԽࡇ@"
"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ʢ˞༁ΛҰ෦มߋʣ ৴པੑͷߴ͍ࣗಈςετΛඋ͑Δ͜ͱ
ِཅੑͱِӄੑ IUUQTHJIZPKQNBHB[JOFXEQSFTTBSDIJWFWPM
ِཅੑͱِӄੑͷύλʔϯ 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࿈ࡌ֤ճͷςʔϚ ֶश༻ςετ ِཅੑͱِӄੑ ςεταΠζ ςετμϒϧ ςετϐϥϛου 🦁
ࣗಈςετͱ$*ʹϑΟοτ͢Δ ໌֬ͳςετྨج४
օ͞Μʹ͓͍͠·͢ 🙋🙋🙋 wσʔλϕʔεʹΞΫηε͢ΔͷϢχοτςετ :FT/P wωοτϫʔΫʹΞΫηε͢ΔͷϢχοτςετ :FT/P wϑΝΠϧʹΞΫηε͢ΔͷϢχοτςετ :FT/P wݱࡏ࣌ࠁʹΞΫηε͢ΔͷϢχοτςετ :FT/P
wґଘઌͷΫϥεʹຊΛ͏ͷϢχοτςετ :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 5FTU%PVCMFࣗಈςετ༻ͷِ
IUUQYVOJUQBUUFSOTDPN5FTU%PVCMFIUNM 5FTU%PVCMFͷྨʢ࿈ࡌͷϖʔδʹऩ·Βͣʜʜʣ
ςετμϒϧͷརͱҙ IUUQTXXXBNB[PODPKQEQ w ར w ςετ͠ʹ͍͘ͷΛςετՄೳʹ͢Δ w ςετͷͱܾఆੑΛ্ͤ͞Δ w ҙ
w ςετ͕੬͘ͳΓɺมߋΛ͛Δʢརͷཪฦ͠ʣ w ςετͷِӄੑΛট͘ʢࣗ࡞ࣗԋςετʣ
"HFOEB࿈ࡌ֤ճͷςʔϚ ֶश༻ςετ ِཅੑͱِӄੑ ςεταΠζ ςετμϒϧ ςετϐϥϛου 🦁
ࣗಈςετͷ৴པੑΛ தظతʹอͭ ࠷దͳόϥϯε
Ϣχοτ ΠϯςάϨʔγϣϯ && ίετ ࣮ੑ ςετέʔε ߴ
ߴ ܾఆੑ ςετϐϥϛου
ςετϐϥϛουͱΞΠεΫϦʔϜίʔϯΞϯνύλʔϯ IUUQTXBUJSNFMPOCMPHJOUSPEVDJOHUIFTPGUXBSFUFTUJOHJDFDSFBNDPOF
ࠞཚղऍͷϒϨ͔Βੜ͕ͪ͡
͜Ε·ͰͷݟΛ·ͱΊΔͱ ֶश༻ςετ ِཅੑͱِӄੑ ςεταΠζ ςετμϒϧ ςετϐϥϛου 🦁 🦁 🦁 🦁
4NBMM .FEJVN -BSHF ίετ ࣮ੑ ςετέʔε ߴ
ߴ ܾఆੑ ·ͱΊςετμϒϧͰαΠζμϯͯ͠ɺ֤αΠζΛϐϥϛουܕʹஔ͠ɺςετશମͷ৴པੑΛҡ࣋͢Δ ςετμϒϧ ςετμϒϧ ςετ༰қੑઃܭ υϝΠϯઃܭ
͓ΘΓʹ
ࣦ৬ͷةػྑॻ͗͢Δ IUUQTCPPLNZOBWJKQFDQSPEVDUTEFUBJMJE
ࣦ৬ͷةػ͍͔ʹࢲͷݴ͍ͦ͏ͳ͜ͱΛݴ͏"* IUUQTUXJUUFSDPNLBXBTJNBTUBUVT
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠ 📷🙆 🙆 'PSLXFMMจԽࡇ@"