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
『アジャイルソフトウェア開発の奥義』から学ぶテスト駆動開発
Search
yonetty
February 16, 2021
Programming
490
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
『アジャイルソフトウェア開発の奥義』から学ぶテスト駆動開発
社内の勉強会で使用した資料。
yonetty
February 16, 2021
More Decks by yonetty
See All by yonetty
技術書を読む技術(JJUG CCC 2023 Fall)
yonetty
5
1.5k
Spockで学ぶテスト駆動開発のコツ
yonetty
1
1.3k
Testing Java With Spock
yonetty
0
120
Other Decks in Programming
See All in Programming
GraphRAGのKnowledge Graphを 直接!見る/View-GraphRAG's-KnowledgeGraph-directly!
tyumugi1113
1
310
Java 27新機能 / Java 27 new features
kishida
2
130
kubernetes コンポーネント開発入門 / 新卒N年目の勉強会&交流会!〜〇〇への誘い〜 #n_study
mazrean
0
230
AIエージェント時代のコードレビューを設計する
nogu66
6
2.7k
From 6 People Classroom Meetup to 100 People Regional Conference / FOSS4G Hiroshima 2026
furukawayasuto
0
200
WebRTC映像をAirPlayに対応させる挑戦.pdf
monolithic_adam
0
150
Security issues being discussed on Web Platforms
petamoriken
0
910
『寄り添うラジオ』をAIで作る 体験価値から逆算した、会話しないUXと品質設計
theoriatec2024
3
180
[GoCon2026] When Goroutines Are Not Enough: Runtime Locality in High-Throughput Go
takehaya
6
2.2k
iOSDC2026登壇資料.pdf
riofujimon
0
150
仕様駆動開発による爆速プロダクト開発 / Bakusoku Spec Driven Development
kobakei
0
110
XHTMLが残したもの
yosuke_furukawa
PRO
2
790
Featured
See All Featured
Become a Pro
speakerdeck
PRO
31
6.3k
How GitHub (no longer) Works
holman
316
150k
Navigating Team Friction
lara
192
16k
The Illustrated Children's Guide to Kubernetes
chrisshort
51
53k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.6k
Optimizing for Happiness
mojombo
378
71k
Git: the NoSQL Database
bkeepers
PRO
432
67k
How to Align SEO within the Product Triangle To Get Buy-In & Support - #RIMC
aleyda
2
1.8k
GitHub's CSS Performance
jonrohan
1033
470k
Crafting Experiences
bethany
1
330
Speed Design
sergeychernyshev
33
2.1k
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
500
Transcript
ʰΞδϟΠϧιϑτΣΞ։ൃͷ Ԟٛʱ͔ΒֶͿςετۦಈ։ൃ +BOVBSZUI 5BLFTIJ:POFLVCP !UZPOFLVCP
ςετϑΝʔετ ͱ ςετۦಈ։ൃ
ςετϑΝʔετ ϓϩμΫτίʔυΑΓઌʹ ςετίʔυΛॻ͘͜ͱ
ςετۦಈ։ൃ 5FTU%SJWFO%FWFMPQNFOU ςετίʔυΛಓ۩ʹ ͯ͠ɺ։ൃΛճ͢͜ͱ
ϨουάϦʔϯϦϑΝΫλϦϯά ᶃࣦഊ͢ΔςετΛॻ͘ ᶄςετ͕௨Δγϯϓϧ ͳίʔυΛॻ͘ ᶅϦϑΝΫλϦϯά͠ ͯίʔυΛ៉ྷʹ͢Δ
ςετϑΝʔετ͕ͩ ςετۦಈ։ൃͰͳ͍ྫ ઌʹͯ͢ͷςετίʔυΛॻ͘ class FooTest { def testFoo1() {
} def testFoo2() { } def testFoo3() { } def testFoo4() { } … } class Foo { // ͜Ε͔Β࣮ }
ςετϑΝʔετ͕ͩ ςετۦಈ։ൃͰͳ͍ྫ ᶃࣦഊ͢ΔςετΛॻ͘ ᶄςετ͕௨Δγϯϓϧ ͳίʔυΛॻ͘ ᶅϦϑΝΫλϦϯά͠ ͯίʔυΛ៉ྷʹ͢Δ ϑΟʔυόοΫͷܽ
ςετϑΝʔετ͕ͩ ςετۦಈ։ൃͰͳ͍ྫ ࣄલʹઃܭ͠ա͗Δ class FooTest { def testDoFoo() {
} } class BarTest { def testDoBar() { } }
ςετϑΝʔετ͕ͩ ςετۦಈ։ൃͰͳ͍ྫ ᶃࣦഊ͢ΔςετΛॻ͘ ᶄςετ͕௨Δγϯϓϧ ͳίʔυΛॻ͘ ᶅϦϑΝΫλϦϯά͠ ͯίʔυΛ៉ྷʹ͢Δ ϧʔϓճΔ͕ޮՌ͕ݮΔ
#%6' ࣄલͷઃܭΛΓա͗Δͱ ޡͬͨઃܭաઃܭΛੜΉ #JH%FTJHO6Q'SPOU
αϯΫίετ ઌʹίετΛͬͯߦͬͨઃܭ ࣺͯͮΒ͍ʢଛΓͰ͖ͳ͍ʣ 4VOL$PTU
2 5%%Ͱࣄલઃܭ͠ͳ͍ͷʁ
" ඞཁͳΒɺखॻ͖ͷϥϑεέον $3$ͳͲखܰʹ࡞Ͱ͖ࣺͯͯ ͍͢πʔϧΛ͏
ʮͳΜͱͳ͘ཧղͰ͖͚ͨͲ ۩ମతʹͲ͏ͬͯ5%%Λ ਐΊ͍͍͔ͯΘ͔Βͳ͍ʯ
ͱͯྑ͍ྫ͕͋Γ·ͨ͠ʂ
ʲୈষʳ ϓϩάϥϛϯά Τϐιʔυ
ϘϦϯάͷείΞूܭ ΞϓϦέʔγϣϯΛ5%% Ͱ։ൃ͢Δαϯϓϧ 4 5 1 5 14 4 29
6 6 133 2 49 5 60 1 61 0 77 7 97 6 117
w ٿॱʹͨ͠ϐϯΛه͢Δ w ࢦఆͨ͠ϑϨʔϜʹ͓͚ΔείΞΛܭࢉ Ͱ͖Δ w ࠷৽ͷείΞΛܭࢉͰ͖Δʢશͯͷٿ ͕͍ྃͯ͠Εɺ࠷ऴతͳείΞʣ 4 5
1 5 14 4 29 6 6 133 2 49 5 60 1 61 0 77 7 97 6 117 ৼΔ͍ʢΞϓϦέʔγϣϯ༷ʣ
ࣄલઃܭʢϥϑεέονʣ
Ϙϒ͓͡͞Μͱಉ྅͕ ϖΞϓϩͰḷͬͨಓے
w ςετ͖͢5ISPXͷৼ͍͕ݟ͍ͩͤͣɺ 'SBNFͷςετ͔Βॻ͖࢝Ίͨɻ w ࠷୯७ͳςετέʔε͔Β࢝Ίɺ࠷୯७ͳ ࣮ͰςετΛ௨͢ɻ ࠷ॳͷςετέʔε public class Frame
{ public int getScore() { return 0 ; } } class FrameSpec extends Specification { def "ະٿͷͱ͖ͷείΞ0Ͱ͋Δ"() { given : def f = new Frame( ) when : def score = f.getScore( ) then : score == 0 } } ˞ॻ੶Ͱ+6OJUΛ͍ͬͯΔ ͕ɺຊࢿྉͰ4QPDLΛ༻
w ࣍ʹ୯७ͳςετέʔεΛՃ͠ɺςετ͕௨ ΔΑ͏ʹίʔυΛमਖ਼͢Δ ࣍ͷςετέʔε class FrameSpec extends Specification { ..
def "1ճٿͨ͠ͱ͖ʹείΞ͕ਖ਼͍͠"() { given : def f = new Frame( ) when : f.add(5 ) then : f.getScore() == 5 } } public class Frame { private int itsScore = 0 ; public int getScore() { return itsScore ; } public void add(int pins) { itsScore += pins ; } }
ग़ͩ͠ॱௐʂ
w εϖΞετϥΠΫΛग़ͨ͠߹ɺϑϨʔϜͷ είΞܭࢉʹޙଓͷϑϨʔϜͷใ͕ඞཁɻ w (BNFΦϒδΣΫτ'SBNFΛϦϯΫϦετͰ ཧ͖͢ʁ w 'SBNFͷ࡞ۀΛதஅͯ͠ɺ(BNFͷ࡞ۀʹΓ ସ͑Δɻ ෳճٿͨ͠߹ʁ
(BNFͷ࣮Λগͣͭ͠ਐΊΔ class GameSpec extends Specification { when : g.add(5 )
g.add(4 ) g.add(7 ) g.add(2 ) then : g.score() == 1 8 g.scoreForFrame(1) == 9 g.scoreForFrame(2) == 1 8 } public class Game { private int itsScore = 0 ; private int[] itsThrows = new int[21] ; private int itsCurrentThrow = 0 ; public int score() { return itsScore ; } public void add(int pins) { itsThrows[itsCurrentThrow++] = pins ; itsScore += pins ; } public int scoreForFrame(int frame) { int score = 0 ; for (int ball = 0; frame > 0 && (ball < itsCurrentThrow) ; ball += 2, frame--) { score += itsThrows[ball] + itsThrows[ball + 1] ; } return score ; } }
lίʔυ͕ͦΕΛඞཁͩͱ ओு͠ͳ͍ݶΓɺϦϯΫϦετ ༻ҙͨ͘͠ͳ͍Μͩz
w ୯ͳΔྻͰ༻Λ͢ͳΒɺͦΕͰ0, w ઃܭ্ͷஅΛΒͤΔ γϯϓϧͳઃܭΛબ͠Α͏ public class Game { private
int itsScore = 0 ; private int[] itsThrows = new int[21] ; private int itsCurrentThrow = 0 ;
w ςετ͕͋Δ͔Β҆৺ϦϑΝΫλϦϯά ৗʹϦϑΝΫλϦϯά͠Α͏ public int scoreForFrame(int frame) { int score
= 0 ; for (int ball = 0; frame > 0 && (ball < itsCurrentThrow) ; ball += 2, frame--) { score += itsThrows[ball] + itsThrows[ball + 1] ; } return score ; } public int scoreForFrame(int theFrame) { int ball = 0 ; int score = 0 ; for (int currentFrame = 0; currentFrame < theFrame ; currentFrame++) { int firstThrow = itsThrows[ball++] ; int secondThrow = itsThrows[ball++] ; score += firstThrow + secondThrow ; } return score ; }
w εϖΞΛग़ͨ͠ͱ͖ w ετϥΠΫΛग़ͨ͠ͱ͖ w ύʔϑΣΫτήʔϜ w ϦΞϧͳαϯϓϧ w ΤοδέʔεʢύʔϑΣΫτήʔϜະͳͲʣ
ਐతʹ(BNFͷ࣮ΛਐΊΔ 4 5 1 5 14 4 29 6 6 133 2 49 5 60 1 61 0 77 7 97 6 117
w શͯͷςετέʔε͕௨ΓɺΞϓϦέʔγϣϯ ͷৼΔ͍͕͕ͨ͠ɺϦϑΝΫλϦϯά ଓ͍͍ͯ͘ɻ w 4DPSFSΦϒδΣΫτͷඞཁੑΛΘͤͳ͕ Βɺͪ͝Ό͍ͭͨίʔυΛ͖Ε͍ʹ͍ͯ͘͠ɻ ͞ΒͳΔϦϑΝΫλϦϯά
if (strike()) { score += 10 + nextTwoBallsForStrike() ; ball++
; } else if (spare()) { score += 10 + nextBallForSpare() ; ball+=2 ; } else { score += handleSecondThrow() ; } l͜ͷTDPSF'PS'SBNFؔΛݟͯ͝ΒΜΑʂ ͜Εͦ͜ϘϦϯάͷϧʔϧΛ͖ΘΊͯ؆ܿ ʹهड़ͨ࢟ͩ͠Αʂz
ܗ l͜ΕͰɺ(BNFϑϨʔϜͷཧ͚ͩΛͯ͠ɺ 4DPSFSείΞͷܭࢉ͚ͩΛ୲͢Δਤࣜʹͳͬ ͨͶɻ͜Εͧɺ୯Ұͷݪଇʢ431ʣͩʂz
ͲͪΒͷઃܭ͕͙͢Ε͍ͯΔ͔ʁ if (strike()) { score += 10 + nextTwoBallsForStrike() ;
ball++ ; } else if (spare()) { score += 10 + nextBallForSpare() ; ball+=2 ; } else { score += handleSecondThrow() ; } ࣄલͷઃܭ 5%%ʹΑΔઃܭ
దͳϞσϦϯά ࣮ੈքͷ֓೦ߏΛ࣮ʹղܾྖ Ҭʹ࠶ݱ͢Δ͜ͱ͕͍ͭਖ਼͍͠ ͱݶΒͳ͍
ٙ 4DPSFSςετ͠ͳ͍ͷʁ
ϢχοτςετͷʮϢχοτʯ lϢχοτͱ;Δ·͍ͷ୯ Ґɺͭ·Γಠཱͨ͠ݕূՄ ೳͳ;Δ·͍ͷ͜ͱͩz
ৼ͍ͷू߹ମΛςετ͢Δ l͋ΒΏΔ؍Մೳͳ;Δ· ͍͕ɺͦΕʹඥͮ͘ςετ Λ͖࣋ͭͰ͋Δ͜ͱΛҙ ຯ͢Δɻz
ৼΔ͍ͷू߹ମͷϑΝαʔυͰ ͋Δ(BNFΛςετ͢Ε0,
࣮ࡍɺΧόϨοδͳ͔ͬͨ
w 5%%ͷαΠΫϧͰ(BNFͷৼ͍Λશ࣮ͯ͠ ͨޙɺϦϑΝΫλϦϯάͰ4DPSFSΛநग़ɻ w (BNF4QFDͰৼ͍Λݻఆ͢Δ͜ͱͰɺϦ ϑΝΫλϦϯάΛߦ͏͜ͱ͕Ͱ͖ͨɻ Ϙϒ͓͡͞Μୡ͕ḷͬͨ࿏
w ॻ੶ͷதͰϘϒ͓͡͞Μୡ͕ḷͬͨ࿏ΛɺԾʹ ηΠόʔϧʔτͱݺͿʢ࣭ड͚͚ͳ͍ʣ 5%%ͷϧʔτҰͭͱݶΒͳ͍
w 4DPSFSͷඞཁੑ͕ݟ͑ͨஈ֊Ͱ4DPSFS4QFD Λ࡞͠ɺ5%%Ͱ4DPSFSΛઌʹ্͛Δɻ w ΠϯαΠυΞτʢϘτϜΞοϓʣɻ ႒ϧʔτ
w 4DPSFSͷඞཁੑ͕ݟ͑ͨΒɺ4DPSFSͷϞοΫ Λͬͯ(BNFͷ࣮ΛਐΊ͍ͯ͘ɻ w ΞταΠυΠϯʢτοϓμϯʣɻ ࡩϧʔτ
ϞοΫΛͬͨςετ private Game g private Scorer s def setup() {
s = Mock() // ScorerͷϞοΫ g = new Game(s ) } def "2ճٿͨ͠ͱ͖ͷείΞ͕ਖ਼͍͠"() { when : g.add(5 ) g.add(4 ) def score = g.score( ) then : score == 9 1 * s.addThrow(5 ) 1 * s.addThrow(4 ) 1 * s.scoreForFrame(2) >> 9 } ؒೖྗ ؒग़ྗ ʨ ૬ޓ࡞༻ͷݕূ
w (BNFΛपΓ͔Βಠཱͯ͠ςετͰ͖Δɻ w 4DPSFSͷ࣮͕ͳ͍࣌Ͱɺઌʹ(BNFΛςε τͰ͖Δɻ w ϞοΫΛܦ༝͠ɺؒೖྗؒग़ྗΛͬͯ (BNFͷৼ͍ঢ়ଶΛνΣοΫͰ͖Δɻ w (BNFͱ4DPSFSͷ૬ޓ࡞༻ΛδϟετΠϯλΠ
ϜͰઃܭͰ͖Δɻ ϞοΫΞϓϩʔνͷϝϦοτ
w ࣮ͷৄࡉʹґଘ͢ΔͨΊɺ੬͍ςετͱͳΓ ͍͢ɻ w ॻ͘ͷʹख͕͔͔ؒΔɻ w (BNF 4DPSFSʢৼ͍ͷू߹ମʣʹର͢Δ ςετผ్ॻ͘ඞཁ͕͋Δɻ ϞοΫΞϓϩʔνͷσϝϦοτ
w ϞοΫΛͬͯॻ͍ͨ(BNF4QFD͋͘·Ͱ ઃܭΛਐΊΔҰ࣌తͳಓ۩ͱߟ͑ɺࣺͯͯΑ͠ ʢৼ͍ͷू߹ମʹର͢Δςετ͕ΕՄʣ ઃܭͷͨΊ͚ͩͷςετίʔυ
·ͱΊ
5%%ͷຊ࣭ɺ ϨουάϦʔϯϦϑΝΫλϦϯά ͷαΠΫϧͰߦ͏ δϟετΠϯλΠϜͷઃܭͰ͋Δ
Ϣχοτςετͷ୯Ґ ৼ͍ͷू߹ମͱ͠Α͏
ʰΞδϟΠϧιϑτΣΞ։ൃͷ ԞٛʱষΛࣸܦͯ͠Έ·͠ΐ͏
ʰΞδϟΠϧιϑτΣΞ։ൃͷԞٛୈ̎൛ʱ ϩόʔτɾ$ɾϚʔνϯஶ4#ΫϦΤΠςΟϒץ ʰϨΨγʔίʔυ͔Βͷ٫ʱ %BWJE4DPUU#FSOTUFJOஶΦϥΠϦʔɾδϟύϯץ ࢀߟจݙ