ࣗݾհ
w ʹ͜͠Γ͞ͿΖʙ ຊ໊ࡔ্৴
w ౦ژɾҏ౾େౡग़
w גࣜձࣾ#FBS5BJM
w "OESPJEΤϯδχΞ ,PUMJO+BWB
w 8FCΤϯδχΞ 3BJMT3FBDU
!2
Slide 3
Slide 3 text
ࣄ
w %S8BMMFU
,PUMJOҠߦ࡞ۀதʜ
!3
Slide 4
Slide 4 text
ࣄ
w %Sܦඅਫ਼ࢉ
ϑϧ,PUMJOʂ
.PDL,4QFL
ಋೖࡁΈʂ
!4
Slide 5
Slide 5 text
࣍
͜Ε·Ͱͷ6OJU5FTU
,PUMJOϑϨʔϜϫʔΫϥΠϒϥϦͷհ
w .PDL,ϞοΫϥΠϒϥϦ
w 4QFLςετϑϨʔϜϫʔΫ
,PUMJOϑϨϯυϦʔͳ6OJU5FTUڥͷߏங
w .PDL,ɾ4QFLͷಋೖ
w +B$P$PΛͬͨίʔυΧόϨοδࢉग़
!5
Slide 6
Slide 6 text
ର
w ॳΊͯ"OESPJE։ൃͰ6OJU5FTUΛॻ͜͏ͱ͍ͯ͠Δਓ
w +BWBϥΠϒϥϦͰͷςετʹർΕͨਓ
!6
Slide 7
Slide 7 text
͜Ε·Ͱͷ6OJU5FTU
!7
Slide 8
Slide 8 text
,PUMJOਖ਼ࣜαϙʔτલ
w .PDLJUPϞοΫϥΠϒϥϦ
w WSFMFBTFʙࠒ
w ཉ͍͠ػೳେମἧ͍ͬͯΔ
w ใ͕๛
w ,PUMJO༻ϥούʔϥΠϒϥϦΞϦ
w .PDLJUP,PUMJO ݄ʙ
!8
Slide 9
Slide 9 text
w +6OJUςετϑϨʔϜϫʔΫ
w "OESPJEϓϩδΣΫτͰͷσϑΥϧτͷϑϨʔϜϫʔΫ
w BOOPUBUJPOͰςετϝιουΛࢦఆ
,PUMJOਖ਼ࣜαϙʔτલ
!9
Slide 10
Slide 10 text
,PUMJOਖ਼ࣜαϙʔτલ
w ϞοΫϥΠϒϥϦˠ.PDLJUP
w ϢχοτςετϑϨʔϜϫʔΫˠ+6OJU
w ͲͪΒ+BWB
w ,PUMJOରԠ͕ෆे
w ,PUMJOͷݴޠ༷Λ׆͔͖͠Εͳ͍
!10
Slide 11
Slide 11 text
,PUMJOਖ਼ࣜαϙʔτ
!(PPHMF*0
!11
Slide 12
Slide 12 text
ޙʜ
w ,PUMJOϥΠϒϥϦϑϨʔϜϫʔΫ
w ,PUMJOͷݴޠ༷Λϑϧʹ׆͔ͤΔʂ
w ʮ+BWB͔Βݟͨ࣌͜ͷίʔυͲ͏ͳΔΜ͚ͩͬʯˠগͳ͘ͳΔ
w ςετॻ࣌͘ʹߟ͑Δ͖͜ͱ͕ݮΔˠܧଓੑͷ͋Δςετ
w ҆৺ͯ͑͠Δʂ
w ใ͕૿͖͑ͯͨʂ
,PUMJOϥΠϒϥϦϑϨʔϜϫʔΫ
ಋೖͷػʂ
!12
Slide 13
Slide 13 text
,PUMJO
ϑϨʔϜϫʔΫϥΠϒϥϦͷհ
!13
Slide 14
Slide 14 text
.PDL,
w ϞοΫϥΠϒϥϦ
w ,PUMJOಠࣗͷݴޠ༷Λཏ
w 6OJU5FTU*OTUSVNFOUFE5FTU྆ରԠ
w %SPJE,BJHJެࣜΞϓϦͰར༻
(JUIVCNPDLLNPDLL
!14
Slide 15
Slide 15 text
Ͱ͖Δ͜ͱ
w ελϒ
w ϝιουͷฦΓͷࠩ͠ସ͑
w ϞοΫ
w ϝιουͷҾɺݺΕͨճɺฦΓͷݕূ
w ϝιουͷॲཧಈ࡞͠ͳ͍
w εύΠ
w ϝιουͷҾɺݺΕͨճɺฦΓͷݕূ
w ϝιουͷॲཧ͕࣮ࡍʹಈ࡞͢Δ
ৄ͘͠
"OESPJEςετશॻͰʜ
!15
Slide 16
Slide 16 text
NPDLL5ϝιου
1 val car = mockk()
2
3 every { car.drive(Direction.NORTH) } returns Outcome.OK
4
5 car.drive(Direction.NORTH) // returns OK
6
7 verify(exactly = 1) { car.drive(Direction.NORTH) }
8
9 confirmVerified(car)
!16
Slide 17
Slide 17 text
NPDLL5ϝιου
1 val car = mockk()
2
3 every { car.drive(Direction.NORTH) } returns Outcome.OK
4
5 car.drive(Direction.NORTH) // returns OK
6
7 verify(exactly = 1) { car.drive(Direction.NORTH) }
8
9 confirmVerified(car)
NPDLL5
ϝιου
$BSܕͷϞοΫΠϯελϯεΛ࡞
!17
Slide 18
Slide 18 text
NPDLL5ϝιου
1 val car = mockk()
2
3 every { car.drive(Direction.NORTH) } returns Outcome.OK
4
5 car.drive(Direction.NORTH) // returns OK
6
7 verify(exactly = 1) { car.drive(Direction.NORTH) }
8
9 confirmVerified(car)
FWFSZ\ʜ^ϝιου
ϞοΫʹϝιουͱҾɺฦΓΛڭ͑ࠐΉ
ESJWFϝιουͷ࣮ࡍͷॲཧಈ࡞͠ͳ͍
!18
Slide 19
Slide 19 text
NPDLL5ϝιου
1 val car = mockk()
2
3 every { car.drive(Direction.NORTH) } returns Outcome.OK
4
5 car.drive(Direction.NORTH) // returns OK
6
7 verify(exactly = 1) { car.drive(Direction.NORTH) }
8
9 confirmVerified(car)
DBSʹ
wʮ%JSFDUJPO/035)ʯΛҾʹड͚
wʮ0VUDPNF0,ʯΛฦ͢
wʮESJWFʯϝιου͕͋Δɹ͜ͱΛڭ͑ࠐΉ
!19
Slide 20
Slide 20 text
NPDLL5ϝιου
1 val car = mockk()
2
3 every { car.drive(Direction.NORTH) } returns Outcome.OK
4
5 car.drive(Direction.NORTH) // returns OK
6
7 verify(exactly = 1) { car.drive(Direction.NORTH) }
8
9 confirmVerified(car)
WFSJGZ\ʜ^ϝιου
WFSJGZͷϝιου͕ݺΕͨ͜ͱΛνΣοΫ
ҾFYBDUMZʹݺΕΔճΛࢦఆͰ͖Δ
!20
Slide 21
Slide 21 text
TQZL5ϝιου
1 val car = spyk(Car())
2
3 car.drive(Direction.NORTH)
4
5 verify { car.drive(Direction.NORTH) }
6
7 confirmVerified(car)
!21
.PDLJUPͷ
w 'JOBMͳΫϥεϝιου͕ϞοΫͰ͖ͳ͍ʂ
w ,PUMJOͷΫϥεϝιουσϑΥϧτͰ'JOBM
w ճආࡦLPUMJOBMMPQFOϓϥάΠϯ CZ+FU#SBJOT
w BOOPUBUJPO͚ͭΔͱPQFOʹͯ͘͠ΕΔɹ ڧҾͩͳʜ
w ςετͷͨΊʹຊ൪ίʔυͷ༨ܭͳهड़͕૿͑Δ
!26
Slide 27
Slide 27 text
.PDLJUPͷ
w 4UBUJDͳϝιου͕ϞοΫͰ͖ͳ͍ʂ
w ֦ுؔɹγϯάϧτϯΦϒδΣΫτ
w ճආࡦ1PXFS.PDL
w 4UBUJDϝιουɺQSJWBUFϝιουͷϞοΫ͕Ͱ͖Δ
w Θ͟Θ͟ผϥΠϒϥϦΛಋೖ͢Δ͜ͱ͕ඍົ
!27
Slide 28
Slide 28 text
.PDL,ͷڧΈ
w ,PUMJOͷΫϥεϝιουΛ΄΅ԿͰϞοΫͰ͖ͯ͠·͏ʂ
w 'JOBMͳΫϥεϝιου
w γϯάϧτϯΦϒδΣΫτ
w ֦ுؔ
w QSJWBUFϝιου
w TVTQFOEϝιουFUD
!28
Slide 29
Slide 29 text
γϯάϧτϯΦϒδΣΫτ
1 object MockObj {
2 fun add(a: Int, b: Int) = a + b
3 }
4
5 mockkObject(MockObj)
6
7 assertEquals(3, MockObj.add(1, 2))
8
9 every { MockObj.add(1, 2) } returns 55
10
11 assertEquals(55, MockObj.add(1, 2))
!29
Slide 30
Slide 30 text
γϯάϧτϯΦϒδΣΫτ
1 object MockObj {
2 fun add(a: Int, b: Int) = a + b
3 }
4
5 mockkObject(MockObj)
6
7 assertEquals(3, MockObj.add(1, 2))
8
9 every { MockObj.add(1, 2) } returns 55
10
11 assertEquals(55, MockObj.add(1, 2))
!30
Slide 31
Slide 31 text
γϯάϧτϯΦϒδΣΫτ
1 object MockObj {
2 fun add(a: Int, b: Int) = a + b
3 }
4
5 mockkObject(MockObj)
6
7 assertEquals(3, MockObj.add(1, 2))
8
9 every { MockObj.add(1, 2) } returns 55
10
11 assertEquals(55, MockObj.add(1, 2))
!31
4QFL
w ςετϑϨʔϜϫʔΫ
w 3VCZͷ34QFDͱࣅͨจ๏
w +6OJU্Ͱಈ࡞
w 6OJU5FTUͷΈରԠ
w 3PCPMFDUSJDඇରԠ *TTVFʹ্͕͍ͬͯΔ
w Wਖ਼ࣜϦϦʔε લ
(JUIVCTQFLGSBNFXPSLTQFL
˞3PPNʙͷ
ɹηογϣϯͰհ W
!36
Slide 37
Slide 37 text
4QFL֎؍
w ྫ
+40/Λ%PNBJO0CKFDUʹม͢Δ֦ுؔͷ6OJU5FTU
1 // JSONΛද͢Ϋϥε
2 data class PersonJson(val name: String, val sex: String)
3
4 // Domain Object
5 interface Person
6
7 data class Male(val name: String): Person
8
9 data class Female(val name: String): Person
10
11 // ςετରͷ֦ுؔ
12 fun PersonJson.toPerson(): Person = …
!37
+6OJUͱͷൺֱ
w +6OJU
w BOOPUBUJPOͰςετϝιουΛࢦఆϘΠϥʔϓϨʔτͷ૿Ճ
w 4QFL
w EFTDSJCFDPOUFYUJU༷ॻͱͯ͠ಡΈ͍͢ɺৼΔ͍ۦಈ
w BOOPUBUJPOෆཁ༨ܭͳهड़͕গͳ͘ɺ࡞ۀίετΛݮΒͤΔ
w +6OJUલఏɺ3PCPMFDUSJDະରԠ྆ํͱղܾ͞ΕͨΒ˕
!45
ΧόϨοδϨϙʔτूܭ
w ϞδϡʔϧຖʹΧόϨοδܭଌ͕࣮ߦ͞ΕΔ
w ܭଌ݁ՌͷϑΝΠϧ͕ࢄͯ͠͠·͏ˠूܭλεΫͰ·ͱΊΔ
w Δ͜ͱ
w ΧόϨοδܭଌΛ6OJU5FTUޙʹ࣮ߦ͢ΔΑ͏ࢦఆ Ϟδϡʔϧຖ
w ֤ϞδϡʔϧͷΧόϨοδରϑΝΠϧɺΧόϨοδܭଌ݁ՌΛ·ͱΊɺ
Ϩϙʔτ࡞λεΫʹ͢
!64
Slide 65
Slide 65 text
1 task jacocoMergeReports(type: JacocoMerge) {
2 group = "Reporting"
3 description = "Merge all JaCoCo reports from projects into one."
4
5 gradle.afterProject { p, state ->
6 if (p.rootProject != p && p.plugins.hasPlugin("jacoco")) {
7 dependsOn "${p.path}:testDebugUnitTest"
8 executionData "${p.buildDir}/jacoco/testDebugUnitTest.exec"
9 }
10 }
11 }
!65
Slide 66
Slide 66 text
1 task jacocoMergeReports(type: JacocoMerge) {
2 group = "Reporting"
3 description = "Merge all JaCoCo reports from projects into one."
4
5 gradle.afterProject { p, state ->
6 if (p.rootProject != p && p.plugins.hasPlugin("jacoco")) {
7 dependsOn "${p.path}:testDebugUnitTest"
8 executionData "${p.buildDir}/jacoco/testDebugUnitTest.exec"
9 }
10 }
11 }
UZQFΛʮ+BDPDP.FSHFʯʹࢦఆ͠ɺλεΫΛએݴ
!66
Slide 67
Slide 67 text
1 task jacocoMergeReports(type: JacocoMerge) {
2 group = "Reporting"
3 description = "Merge all JaCoCo reports from projects into one."
4
5 gradle.afterProject { p, state ->
6 if (p.rootProject != p && p.plugins.hasPlugin("jacoco")) {
7 dependsOn "${p.path}:testDebugUnitTest"
8 executionData "${p.buildDir}/jacoco/testDebugUnitTest.exec"
9 }
10 }
11 }
֤Ϟδϡʔϧͷ6OJU5FTUλεΫऴྃޙʹ
ϨϙʔτܭଌλεΫ͕࣮ߦ͞ΕΔΑ͏ʹࢦఆ
!67
Slide 68
Slide 68 text
1 task jacocoMergeReports(type: JacocoMerge) {
2 group = "Reporting"
3 description = "Merge all JaCoCo reports from projects into one."
4
5 gradle.afterProject { p, state ->
6 if (p.rootProject != p && p.plugins.hasPlugin("jacoco")) {
7 dependsOn "${p.path}:testDebugUnitTest"
8 executionData "${p.buildDir}/jacoco/testDebugUnitTest.exec"
9 }
10 }
11 }
֤ϞδϡʔϧͷΧόϨοδܭଌ݁ՌͷύεΛ͢
ˠͨ͠ܭଌ݁Ռ͕࠷ޙʹϚʔδ͞ΕΔ
!68
Slide 69
Slide 69 text
1 task jacocoMergeReports(type: JacocoMerge) {
2 group = "Reporting"
3 description = "Merge all JaCoCo reports from projects into one."
4
5 gradle.afterProject { p, state ->
6 if (p.rootProject != p && p.plugins.hasPlugin("jacoco")) {
7 dependsOn "${p.path}:testDebugUnitTest"
8 executionData "${p.buildDir}/jacoco/testDebugUnitTest.exec"
9 }
10 }
11 }
ʮBQQMZQMVHJOKBDPDPʯ͕༗ޮͳϞδϡʔϧͷΈ࣮ߦ
!69
·ͱΊ
w .PDL,
w ,PUMJOͰඞཁͱ͞ΕΔϞοΫ༻ϝιουΛ͘Χόʔ
w ಋೖ؆୯ɺطଘͷςετίʔυͷதͰؾܰʹѻ͑Δ
w 4QFL
w ༨ܭͳهड़͕ݮΓɺ༷ॻͱͯ͠ݟ͍͢ܗͰॻ͚Δ
w 3PCPMFDUSJDରԠɺ"OESPJEϓϩδΣΫτͰͷ+6OJUରԠ͕ͨΕΔ
!75
એ
גࣜձࣾ#FBS5BJMɹΤϯδχΞืूதʂ
৬छ
w "OESPJEΤϯδχΞ ,PUMJO+BWB
w J04ΤϯδχΞ 4XJGU0CKFDUJWF$
w 8FCΤϯδχΞ 3VCZPO3BJMT3FBDU3FEVY
͝ਗ਼ௌ͋Γ͕ͱ͏͍͟͝·ͨ͠N @@
N
ձࣾհࢿྉIUUQCJUMZ".V"*
!77