Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
モックの泥沼から脱却するために、あえてDBにつないでテストしている話
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Kazuhei Arai
March 27, 2021
Programming
3.5k
4
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
モックの泥沼から脱却するために、あえてDBにつないでテストしている話
PHPerKaigi2021
Kazuhei Arai
March 27, 2021
More Decks by Kazuhei Arai
See All by Kazuhei Arai
CTOがプロダクトを管轄して、変わり始めたスクラム開発
kazuhei0108
0
350
Predefined Interfacesを使って便利な独自クラスを作りましょう
kazuhei0108
0
3.2k
LaravelとAWSで_漸進的なプロダクト開発
kazuhei0108
0
180
Laravelのエラーハンドリングをカスタマイズする
kazuhei0108
0
530
サービスコンテナの実践的な活用
kazuhei0108
1
1.2k
クラスを使ってLaravelのviewをキレイにする
kazuhei0108
1
1.8k
自分のLaravel アプリケーション設計晒す
kazuhei0108
0
110
Composerのstabilityの話
kazuhei0108
0
80
Other Decks in Programming
See All in Programming
技術的負債の返済は、AI時代の複利で効く投資 — 経営としての意思決定とその遂行
curekoshimizu
1
2k
一人だけ、Kiroが静止する日
hideg
0
140
Vue Fes Japan 2026 タイムテーブル徹底解説
448jp
1
560
AI Agent時代のリアーキテクチャ戦略と実践
hokaccha
9
5.2k
Webの地図
yosuke_furukawa
PRO
6
4.9k
[2026-09-26]空論ジェネリックプロセス~テスト資産とAIで紡ぐ、再現可能なパフォーマンスチューニングの話~
tosite
0
230
iOSDC2026登壇資料.pdf
riofujimon
0
200
手動確認はもう限界 〜XCUITestでCustom URL Schemeの遷移を起動種別ごとに自動テストする〜 / Testing Custom URL Schemes with XCUITest
otouto
0
360
すこし踏み込む CancellationToken
htkym
2
1.4k
Agents on Rails - Rails at Scale 2026
irinanazarova
0
290
Findy - エンジニア向け会社紹介/Findy Company Deck
findyinc
6
400k
JPUG勉強会 OSSデータベースの内部構造を理解しよう(第2回)
oga5
0
280
Featured
See All Featured
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
A Tale of Four Properties
chriscoyier
163
24k
How to Ace a Technical Interview
jacobian
280
24k
Bash Introduction
62gerente
615
220k
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
290
My Coaching Mixtape
mlcsv
0
330
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
2.1k
Being A Developer After 40
akosma
91
590k
Designing Powerful Visuals for Engaging Learning
tmiket
1
580
Optimizing for Happiness
mojombo
378
71k
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.6k
Leading Effective Engineering Teams in the AI Era
addyosmani
9
2.7k
Transcript
!LB[VIFJ !LB[VIFJ@@ ϞοΫͷటপ͔Β٫͢ΔͨΊʹɺ ͋͑ͯ%#ʹͭͳ͍Ͱςετ͍ͯ͠Δ 1)1FS,BJHJ
ࣗݾհ ߥҪฏ!LB[VIFJ גࣜձࣾ."Ϋϥυ$50 ৽॓ޚԓελʔτΞοϓ
ς Ϋ ϊ ϩ δ ʔ ͷ ྗ Ͱ M
& A ʹ ྲྀ ௨ ֵ ໋ Λ
."ͷϦΫφϏͷΑ͏ͳαʔϏε ങ͍खاۀ͕ങऩχʔζΛܝࡌ͠ɺ ചΓख͕ͦΕʹରͯ͠ਃ͠ࠐΉͱ͍͏ܗͷ ৽͍͠.ˍ"ϚονϯάϓϥοτϑΥʔϜ
͍ͬͯΔٕज़ɾπʔϧ GSPOUFOE CBDLFOE NJEEMFXBSF JOGSB UPPMT
None
࣍ w ϞοΫΛͬͨϢχοτςετͷ w ͋͑ͯɺ%#ʹͭͳ͍Ͱςετ͢Δ w ·ͱΊ
ϞοΫΛͬͨ Ϣχοτςετͷ
Ϣχοτςετʹ͍ͭͯ ϢχοτςετɺϝιουؔͳͲখ͞ͳϢχοτ୯Ґ ʹߜΓࠐΜͩࣗಈςετɻݱతͳϓϩάϥϛϯάʹ͔ܽͤ ͳ͍
ϞοΫ͠ͳ͍Ϣχοτςετ ୯ҰͷΫϥεʹσʔλͱϩδοΫ͕ด͍ͯ͡Δͷ ؆୯ʹςετग़དྷΔɻ
ϞοΫ͠ͳ͍Ϣχοτςετ class CommonTime { public function __construct(int $timestamp) {
$this->timestamp = $timestamp; } public static function fromString($string) { return new static(strtotime($string)); } public function getHour(): string { return date('H', $this->timestamp); }
ϞοΫ͠ͳ͍Ϣχοτςετ public function testGetHour() { $time = CommonTime::fromString('2017-01-01 10:21:00'); $this->assertEquals('10',
$time->getHour()); } จࣈྻ͔Β$PNNPO5JNFΫϥεΛ࡞ͬͯɺHFU)PVS͕࣌ؒ Λฦ͢͜ͱΛςετ
ϞοΫΛͬͨϢχοτςετ %#ΞΫηε͍ͯ͠ΔɺΫϥεʹσʔλ͕ด͍ͯ͡ ͳ͍߹ͷςετϞοΫΛͬͯςετ͢Δ
ϞοΫΛͬͨϢχοτςετ class MessageDomainService { public function notifyMessage(MessageId $messageId): void
{ $message = $this->messageRepository->get($messageId); if ($message->needsNotification()) { $this->notificationRepository->add($message->notification()); } } ϝοηʔδΛऔಘͯ͠ɺඞཁͳΒ௨Ճ͢Δͱ͍͏Α͏ ͳॲཧ
ϞοΫΛͬͨϢχοτςετ public function testNotifyMessage() { $needsNotifyMessage = new Message(...); $this->mock(MessageRepository::class,
function ($mock) use ($needsNotifyMessage) { $mock->shouldReceive('get') ->andReturn($needsNotifyMessage); }); $this->mock(NotificationRepository::class, function ($mock) use ($needsNotifyMessage) { $mock->shouldReceive('add') ->with($needsNotifyMessage->notification()); }); $domainService = app()->make(MessageDomainService::class); $domainService->notifyMessage($needsNotifyMessage->id()); } ҰͭҰͭͷσʔλΞΫηε෦ΛϞοΫʹͯ͠ɺ͕ؔݺ Ε͍ͯΔ͔Ͳ͏͔Λ֬ೝ͍ͯ͘͠ɻ
ϞοΫΛͬͨϢχοτςετ public function testNotifyMessage() { $needsNotifyMessage = new Message(...); $this->mock(MessageRepository::class,
function ($mock) use ($needsNotifyMessage) { $mock->shouldReceive('get') ->andReturn($needsNotifyMessage); }); $this->mock(NotificationRepository::class, function ($mock) use ($needsNotifyMessage) { $mock->shouldReceive('add') ->with($needsNotifyMessage->notification()); }); $domainService = app()->make(MessageDomainService::class); $domainService->notifyMessage($needsNotifyMessage->id()); } σʔλϕʔε͔Βऔಘͨ͠σʔλΛͬͯɺෳͷςʔϒϧʹॻ͖ ࠐΈΛ͍ͯ͘͠Α͏ͳ߹ɺͨ͘͞ΜͷσʔλϕʔεΞΫηεΛ ϞοΫ͢Δඞཁ͕͋Δɻ
ϞοΫΛͬͨϢχοτςετ ࣮ࡍͷॲཧ͜ΕΑΓԿഒෳࡶʹͳΓɺςετ ίʔυ͜ΕΑΓͣͬͱଟ͘ͳͬͯ͠·͏ɻ ίʔυΛॻ͍͍ͯΔͷ͔ςετΛॻ͍͍ͯΔͷ͔͔ Βͳ͍ঢ়ଶɻ
ϞοΫΛͬͨϢχοτςετ
Կ͕ѱ͍ͷ͔ʁ
ςετͷີ݁߹ ϝιου ଞΫϥεͷݺͼग़͠ ଞΫϥεͷݺͼग़͠ ଞΫϥεͷݺͼग़͠ ˡϞοΫ ˡϞοΫ ˡϞοΫ ςετͷີ݁߹͕ى͖͍ͯΔɻϞοΫΛͬͨςετςετ ͕ϝιουͷத·Ͱৄͬͯ͘͠͠·͍ͬͯΔͱ͍͏͜ͱɻ
ςετͷີ݁߹ ϝιου ଞΫϥεͷݺͼग़͠ ଞΫϥεͷݺͼग़͠ ଞΫϥεͷݺͼग़͠ ˡϞοΫ ˡϞοΫ ˡϞοΫ ςετϓϩμΫτίʔυͱີ݁߹͢Ε͢Δ΄ͲյΕ ͘͢ͳΔɻଞΫϥεͷมߋͰςετ͕յΕͯ͠·͏
ςετͷີ݁߹ ϝιου ଞΫϥεͷݺͼग़͠ ଞΫϥεͷݺͼग़͠ ଞΫϥεͷݺͼग़͠ ˡϞοΫ ˡϞοΫ ˡϞοΫ ϞοΫΛ͗ͯ͢͠ϓϩμΫτίʔυ͕ςετͱͯ͠ มߋग़དྷͳ͍ঢ়ଶΛϞοΫͷటপͱ͍͏
ϞοΫͷటপ
ςετͷີ݁߹ ϝιου "HFU "VQEBUF #VQEBUF ˡςετ ˡςετ ˡςετ ࣮ࡍɺϞοΫ͠·͘Δͱɺϝιου͕ݺΕͯΔॱ൪͘Β͍͔͠ ςετग़དྷͳ͍ͷͰʁͪΌΜͱಈ͍͍ͯΔͱอূͰ͖Δͷ͔ʁ
ςετͷछྨ ϞοΫΛ͑͏΄ͲɺςετϗϫΠτϘοΫε ςετʹ͍͍ۙͮͯ͘ɻ શͯͷ݅Λ௨ͯ͠ɺΧόϨοδΛ্͍͛ͨͷ߹ ʹ༗༻͕ͩɺγϯϓϧʹڍಈΛ֬ೝ͍ͨ͠ͱ͖ʹ ϒϥοΫϘοΫεςετʹ͍ͨ͠ɻ
ϗϫΠτϘοΫεςετ ϝιου "HFU "VQEBUF #VQEBUF ˡςετ ˡςετ ˡςετ ͦΕͧΕͷ͕ؔͪΌΜͱݺΕ͍ͯͯɺਖ਼͍͠ذ ʹೖ͍ͬͯΔ͜ͱΛςετ͢Δ
ϒϥοΫϘοΫεςετ ϝιου தΘ͔Βͳ͍͕ɺΠϯϓοτͱΞτϓοτ͕อ ূ͞Ε͍ͯΔঢ়ଶ ˢ ςετ Πϯϓοτ Ξτϓοτ
ϒϥοΫϘοΫεςετ ϝιου ͜ΕʹΑͬͯɺϓϩμΫτίʔυͱςετ͕ಠཱ͠ɺς ετΛ͍͡ΒͣʹίʔυΛมߋ͢Δ͜ͱ͕ग़དྷΔ ˢ ςετ Πϯϓοτ Ξτϓοτ
ςετͷछྨ ϒϥοΫϘοΫεςετʹ͍ͨ͠ʂ😆
͋͑ͯɺ%#ʹͭͳ͙
͋͑ͯɺ%#ʹͭͳ͙ ϝιου ΠϯϓοτͱΞτϓοτΛ%#͔Βऔಘ͢Εɺϒ ϥοΫϘοΫεςετ͕࣮ݱͰ͖Δ ˢ ςετ %# %#
͋͑ͯɺ%#ʹͭͳ͙ public function testNotifyMessage() { $needsNotifyMessage = new Message(...); $domainService
= app()->make(MessageDomainService::class); $domainService->notifyMessage($needsNotifyMessage->id()); $notification = $this->notificationRepository->first(); $this->assertEquals($needsNotifyMessage->notification(), $notification) } ࣮ࡍͷ%#ʹॻ͖ࠐΜͰɺͦΕΛऔΓग़ͯ͠Ұக͍ͯ͠ Δ͔֬ೝ͢Δ͚ͩɻͱͯγϯϓϧ
%#ʹͭͳ͍Ͱςετ͢Δͱ͖ͷ ɾςετޙͷ෭࡞༻ΛͲ͏ͬͯରॲ͢Δ͔ ɾ࣮ߦ࣌ؒΛͲ͏͢Δ͔
ςετޙͷ෭࡞༻ΛͲ͏ͬͯରॲ͢Δ͔ ςετҰͭҰ͕ͭऴΘΔʹσʔλϕʔεͷঢ়ଶΛ͠ ͍ͨɻ ςετΛ࣮ߦ͢ΔʹσʔλϕʔεʹॳظσʔλΛ༻ҙ ͍ͯͨ͠Βɺςετͷ࣮ߦ࣌ؒͷຆͲ͕σʔλͷ༻ҙ ʹͳͬͯ͠·͏😅
ςετޙͷ෭࡞༻ΛͲ͏ͬͯରॲ͢Δ͔ %#ͷτϥϯβΫγϣϯΛ׆༻͢Δ👏
ςετޙͷ෭࡞༻ΛͲ͏ͬͯରॲ͢Δ͔ αϯϓϧίʔυ-BSBWFMΛͬͨͷɻTFUVQ ࣌ʹ USBOTBDUJPOΛுΓɺUFBS%PXO ࣌ʹSPMMCBDL͍ͯ͠Δ <?php declare(strict_types=1); namespace Tests; use
Illuminate\Foundation\Testing\DatabaseTransactions; abstract class BaseDbIntegrationTest extends TestCase { use DatabaseTransactions; }
࣮ߦ࣌ؒΛͲ͏͢Δ͔ Ϣχοτςετ໋͕͞ɻσʔλϕʔεʹͭͳ͍Ͱ͍ ͨΒςετ͕͘ͳͬͯ͠·͏😅
࣮ߦ࣌ؒΛͲ͏͢Δ͔ %#ʹͭͳ͙ํ͕ܨ͕ͳ͍ΑΓ͍ͷํͳ͍ͱׂΓ Δ😅࣮ߦͷํΛͯ͠ରॲ
࣮ߦ࣌ؒΛͲ͏͢Δ͔ 1)16OJUͷઃఆͰςετΛׂ͠ɺ࣮ߦλΠϛϯάΛௐ͢ Δ͜ͱͰରॲ <testsuites> <testsuite name="Feature"> <directory suffix="Test.php">./tests/Feature</directory> </testsuite> <testsuite
name="DbIntegration"> <directory suffix="Test.php">./tests/DbIntegration</directory> </testsuite> <testsuite name="Unit"> <directory suffix="Test.php">./tests/Unit</directory> </testsuite> </testsuites>
࣮ߦ࣌ؒΛͲ͏͢Δ͔ $*্Ͱଞͷछྨͷςετͱฒྻ࣮ߦͰ͖ΔΑ͏ʹઃఆ͠ɺ શମͰͷ࣮ߦ࣌ؒʹӨڹΛ༩͑ͳ͍Α͏ʹ
·ͱΊ
·ͱΊ ɾϞοΫΛͨ͘͞Μ͏ςετɺϓϩμΫτίʔυͱςετ ͕ີ݁߹ͯ͠ϞοΫͷటপʹϋϚͬͯ͠·͏ɻ ɾ͋͑ͯ%#ʹͭͳ͙͜ͱͰϓϩμΫτίʔυͱςετ͕ಠཱ ͠ɺΠϯϓοτͱΞτϓοτΛ֬ೝ͢Δ͚ͩͷγϯϓϧͳς ετʹͳΔ ɾ%#ʹͭͳ͍Ͱςετ͢ΔͨΊͷػೳҙ֎ͱ༻ҙ͞Εͯ ͓ΓɺΕग़དྷΔ
ҙॻ͖ ϞοΫΛ͏ͷΛৗʹΊͨ΄͏͕ྑ͍ͱ͍͏͜ͱͰ͋Γ ·ͤΜɻ࣮ࡍʹϞοΫΛͬͨํ͕ྑ͍έʔεͱͯଟ͍Ͱ ͢ɻ ͨͩɺϞοΫΛΘͳ͍Ͱςετ͢Δํ๏͋ΔΑɺͱ͍͏ Ͱͨ͠ɻ
ࢀߟॻ੶ ॳΊͯͷࣗಈςετ03FJMMZ+BQBO IUUQTXXXPSFJMMZDPKQCPPLT