Slide 1

Slide 1 text

Start Kotlin with Test ςετ͔Β࢝ΊΔKotlinಋೖ

Slide 2

Slide 2 text

2 About me 4FOJPS&OHJOFFS4DSVN.BTUFSBUFVSFLB *OD +BWB ,PUMJO (PMBOH 5ZQF4DSJQU "OHVMBS+4 'BOUBTZ&BSUI;FSP T$3:FE GVUBCPPP ɹɹɹೋ઒ ོߒʢTakahiro Futagawaʣ

Slide 3

Slide 3 text

3 About eureka ैۀһ਺ ໊ʢฏۉ೥ྸࡀʣ ࣄۀ಺༰ ࣗࣾαʔϏεاըɾ։ൃɾӡӦ 1BJST $PVQMFT ձࣾ֓ཁ

Slide 4

Slide 4 text

'BDFCPPLΛར༻ͨ͠ ࿀Ѫɾࠗ׆ϚονϯάαʔϏε ྦྷܭձһ਺ 500ສ ਓ ಥഁ͠·ͨ͠

Slide 5

Slide 5 text

ΧοϓϧͷͨΊͷΞϓϦ ࠃ಺࠷େڃ 400ສ μ΢ϯϩʔυ

Slide 6

Slide 6 text

6 Pairs +BWB ,PUMJO %BHHFS 0SNB 0L)UUQ 3FUSPpU #VUUFS,OJGF %BUB#JOEJOH 3Y+BWB 3Y,PUMJO FUD Android JP

Slide 7

Slide 7 text

7 Couples +BWB "DUJWF"OESPJE 7PMMFZ 0L)UUQ 3FUSPpU 4PDLFU*0 3Y+BWB FUD Android

Slide 8

Slide 8 text

Pairs Androidͷྺ࢙ 8

Slide 9

Slide 9 text

9 େੲͷPairsAndroid

Slide 10

Slide 10 text

10 ݱࡏͷPairsAndroid

Slide 11

Slide 11 text

11 ࠷ۙϦχϡʔΞϧͨ͠Global൛

Slide 12

Slide 12 text

12 –R. Kulawiec “े෼ʹൃୡͨ͠όά͸ͲΕ΋ɺػೳͱݟ෼͚͕͔ͭͳ͍”

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

ʊਓਓਓਓਓਓਓਓਓਓਓਓਓਓʊ ʼɹॏཁͳػೳ͕࢖͑ͳ͍όάɹʻ ʉ̮̮̮̮̮̮̮̮̮̮̮̮̮̮ʉ

Slide 15

Slide 15 text

ςετ͕ॻ͍ͯ͋Ε͹๷͛ͨ

Slide 16

Slide 16 text

ςετ͕ॻ͚Δঢ়ଶͰ͸ͳ͔ͬͨ

Slide 17

Slide 17 text

ςετ͕ॻ͖΍͍͢ߏ੒ʹมߋ͢Δ 17

Slide 18

Slide 18 text

18 ͍͔ͭͷPairsAndroid

Slide 19

Slide 19 text

19 Before &OUJUZ%BP %BUBCBTF "1* $MJFOU "DUJWJUZ'SBHNFOU

Slide 20

Slide 20 text

20 After Dao %BUBCBTF API Client Repository UseCase Presenter Activity / Fragment Service

Slide 21

Slide 21 text

21 ৄࡉ https://speakerdeck.com/lvla/activitywogai-shan-sitahua

Slide 22

Slide 22 text

Kotlinಋೖ 22

Slide 23

Slide 23 text

23 AndroidStudio Preferences > Plugins > Browse Repositories

Slide 24

Slide 24 text

24 build.gradle buildscript { dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.3-2" } } allprojects { repositories { maven { url 'http://dl.bintray.com/ngsw-taro/maven' } maven { url 'https://jitpack.io' } } }

Slide 25

Slide 25 text

25 app/build.gradle apply plugin: 'kotlin-android' dependencies { testCompile 'junit:junit:4.12' testCompile 'org.jetbrains.kotlin:kotlin-stdlib:1.1.3-2' testCompile 'com.taroid.knit:knit:0.1.2' testCompile 'com.github.sys1yagi:kmockito:0.1.2' }

Slide 26

Slide 26 text

KotlinͰςετΛॻ͍͍ͯ͘ 26

Slide 27

Slide 27 text

27 Client Dao %BUBCBTF API Client Repository UseCase Presenter Activity / Fragment Service 3FUSPpUͷ*OUFSGBDFΛར༻ͯ͠"1*௨৴ Λߦ͏ "1*ͷϨεϙϯεΛΞϓϦ಺Ͱར༻͠΍ ͍͢ܗʹม׵͢Δ

Slide 28

Slide 28 text

28 Client class UserClient (private val service: UserService) {
 
 fun fetchSearchUsers(): Observable> {
 return service.fetchSearchUsers()
 .map { response -> UserConverter.convert(response) }
 }
 }

Slide 29

Slide 29 text

29 Client val userService = mock()
 val client = UserClient(userService)
 
 @Test fun testFetchSearchUsers() {
 val expected = Array(10) { MockUser.newInstance(it) }.toList()
 userService.getUsers().invoked.thenReturn(expected.toObservable()) 
 client.fetchUsers().test().run {
 assertNoErrors()
 assertValue(expected)
 assertCompleted()
 }
 }

Slide 30

Slide 30 text

30 Client val userService = mock()
 val client = UserClient(userService)
 
 @Test fun testFetchSearchUsers() {
 val expected = Array(10) { MockUser.newInstance(it) }.toList()
 userService.getUsers().invoked.thenReturn(expected.toObservable()) 
 client.fetchUsers().test().run {
 assertNoErrors()
 assertValue(expected)
 assertCompleted()
 }
 }

Slide 31

Slide 31 text

31 Client val userService = mock()
 val client = UserClient(userService)
 
 @Test fun testFetchSearchUsers() {
 val expected = Array(10) { MockUser.newInstance(it) }.toList()
 userService.getUsers().invoked.thenReturn(expected.toObservable()) 
 client.fetchUsers().test().run {
 assertNoErrors()
 assertValue(expected)
 assertCompleted()
 }
 }

Slide 32

Slide 32 text

32 Client val userService = mock()
 val client = UserClient(userService)
 
 @Test fun testFetchSearchUsers() {
 val expected = Array(10) { MockUser.newInstance(it) }.toList()
 userService.getUsers().invoked.thenReturn(expected.toObservable()) 
 client.fetchUsers().test().run {
 assertNoErrors()
 assertValue(expected)
 assertCompleted()
 }
 }

Slide 33

Slide 33 text

33 Client val userService = mock()
 val client = UserClient(userService)
 
 @Test fun testFetchSearchUsers() {
 val expected = Array(10) { MockUser.newInstance(it) }.toList()
 userService.getUsers().invoked.thenReturn(expected.toObservable()) 
 client.fetchUsers().test().run {
 assertNoErrors()
 assertValue(expected)
 assertCompleted()
 }
 }

Slide 34

Slide 34 text

34 Client val userService = mock()
 val client = UserClient(userService)
 
 @Test fun testFetchSearchUsers() {
 val expected = Array(10) { MockUser.newInstance(it) }.toList()
 userService.getUsers().invoked.thenReturn(expected.toObservable()) 
 client.fetchUsers().test().run {
 assertNoErrors()
 assertValue(expected)
 assertCompleted()
 }
 }

Slide 35

Slide 35 text

35 Client val userService = mock()
 val client = UserClient(userService)
 
 @Test fun testFetchSearchUsers() {
 val expected = Array(10) { MockUser.newInstance(it) }.toList()
 userService.getUsers().invoked.thenReturn(expected.toObservable()) 
 client.fetchUsers().test().run {
 assertNoErrors()
 assertValue(expected)
 assertCompleted()
 }
 }

Slide 36

Slide 36 text

36 Dao Dao %BUBCBTF API Client Repository UseCase Presenter Activity / Fragment Service %BUBCBTFͷ$36%ॲཧΛߦ͏

Slide 37

Slide 37 text

37 Dao class UserDao (private val orma: OrmaDatabase) {
 fun save(users: List) {
 orma.transactionSync {
 orma.prepareInsertIntoUser(OnConflict.REPLACE)
 .executeAll(users)
 }
 }
 
 fun findAll(): Observable> {
 return orma.selectFromUser()
 .executeAsObservable().toList()
 }
 }

Slide 38

Slide 38 text

38 Dao val orma = OrmaDatabase.builder(context).name(null).build() val dao = UserDao(orma) @Test fun testSave() {
 val dummyUsers = Array(10) { MockUser.newInstance(it) }
 dao.transactionSync { dummyUsers.forEach { dao.save(it) } }
 
 dummyUsers.forEach {
 val found = orma.selectFromUser().userRandIdEq(it.userId).get(0)
 found.rshould be it
 }
 }

Slide 39

Slide 39 text

39 Dao val orma = OrmaDatabase.builder(context).name(null).build() val dao = UserDao(orma) @Test fun testSave() {
 val dummyUsers = Array(10) { MockUser.newInstance(it) }
 dao.transactionSync { dummyUsers.forEach { dao.save(it) } }
 
 dummyUsers.forEach {
 val found = orma.selectFromUser().userRandIdEq(it.userId).get(0)
 found.rshould be it
 }
 }

Slide 40

Slide 40 text

40 Dao val orma = OrmaDatabase.builder(context).name(null).build() val dao = UserDao(orma) @Test fun testSave() {
 val dummyUsers = Array(10) { MockUser.newInstance(it) }
 dao.transactionSync { dummyUsers.forEach { dao.save(it) } }
 
 dummyUsers.forEach {
 val found = orma.selectFromUser().userRandIdEq(it.userId).get(0)
 found.rshould be it
 }
 }

Slide 41

Slide 41 text

41 Dao val orma = OrmaDatabase.builder(context).name(null).build() val dao = UserDao(orma) @Test fun testSave() {
 val dummyUsers = Array(10) { MockUser.newInstance(it) }
 dao.transactionSync { dummyUsers.forEach { dao.save(it) } }
 
 dummyUsers.forEach {
 val found = orma.selectFromUser().userRandIdEq(it.userId).get(0)
 found.rshould be it
 }
 }

Slide 42

Slide 42 text

42 Dao val orma = OrmaDatabase.builder(context).name(null).build() val dao = UserDao(orma) @Test fun testSave() {
 val dummyUsers = Array(10) { MockUser.newInstance(it) }
 dao.transactionSync { dummyUsers.forEach { dao.save(it) } }
 
 dummyUsers.forEach {
 val found = orma.selectFromUser().userRandIdEq(it.userId).get(0)
 found.rshould be it
 }
 }

Slide 43

Slide 43 text

43 Dao val orma = OrmaDatabase.builder(context).name(null).build() val dao = UserDao(orma) @Test fun testSave() {
 val dummyUsers = Array(10) { MockUser.newInstance(it) }
 dao.transactionSync { dummyUsers.forEach { dao.save(it) } }
 
 dummyUsers.forEach {
 val found = orma.selectFromUser().userRandIdEq(it.userId).get(0)
 found.rshould be it
 }
 }

Slide 44

Slide 44 text

44 Repository Dao %BUBCBTF API Client Repository UseCase Presenter Activity / Fragment Service σʔλͷऔಘɾอଘΛߦ͏

Slide 45

Slide 45 text

45 Repository class UserRepository ( private val dao: UserDao, private val client: UserClient) { 
 fun searchUsers(): Observable> {
 return client.searchUsers() .doOnNext { users -> dao.save(users) } .onErrorResumeNext { dao.findAll() }
 }
 }

Slide 46

Slide 46 text

46 Repository val dao = mock(); val client = mock() val repository = UserRepository(dao, client) 
 fun testSearchUsers() { val expected = Array(10) { MockUser.newInstance(it) }.toList() client.fetchUsers().invoked.thenReturn(expected.toObservable()) val subscriber = TestSubscriver() repository.searchUsers().subscribe(subscriber) with(subscriber){ assertNoErrors() onNextEvents.size.should be 1 assertCompleted() } }

Slide 47

Slide 47 text

47 Repository val dao = mock(); val client = mock() val repository = UserRepository(dao, client) 
 fun testSearchUsers() { val expected = Array(10) { MockUser.newInstance(it) }.toList() client.fetchUsers().invoked.thenReturn(expected.toObservable()) val subscriber = TestSubscriver() repository.searchUsers().subscribe(subscriber) with(subscriber){ assertNoErrors() onNextEvents.size.should be 1 assertCompleted() } }

Slide 48

Slide 48 text

48 Repository val dao = mock(); val client = mock() val repository = UserRepository(dao, client) 
 fun testSearchUsers() { val expected = Array(10) { MockUser.newInstance(it) }.toList() client.fetchUsers().invoked.thenReturn(expected.toObservable()) val subscriber = TestSubscriver() repository.searchUsers().subscribe(subscriber) with(subscriber){ assertNoErrors() onNextEvents.size.should be 1 assertCompleted() } }

Slide 49

Slide 49 text

49 Repository val dao = mock(); val client = mock() val repository = UserRepository(dao, client) 
 fun testSearchUsers() { val expected = Array(10) { MockUser.newInstance(it) }.toList() client.fetchUsers().invoked.thenReturn(expected.toObservable()) val subscriber = TestSubscriver() repository.searchUsers().subscribe(subscriber) with(subscriber){ assertNoErrors() onNextEvents.size.should be 1 assertCompleted() } }

Slide 50

Slide 50 text

50 Repository val dao = mock(); val client = mock() val repository = UserRepository(dao, client) 
 fun testSearchUsers() { val expected = Array(10) { MockUser.newInstance(it) }.toList() client.fetchUsers().invoked.thenReturn(expected.toObservable()) val subscriber = TestSubscriver() repository.searchUsers().subscribe(subscriber) with(subscriber){ assertNoErrors() onNextEvents.size.should be 1 assertCompleted() } }

Slide 51

Slide 51 text

51 Repository val dao = mock(); val client = mock() val repository = UserRepository(dao, client) 
 fun testSearchUsers() { val expected = Array(10) { MockUser.newInstance(it) }.toList() client.fetchUsers().invoked.thenReturn(expected.toObservable()) val subscriber = TestSubscriver() repository.searchUsers().subscribe(subscriber) with(subscriber){ assertNoErrors() onNextEvents.size.should be 1 assertCompleted() } }

Slide 52

Slide 52 text

52 Repository val dao = mock(); val client = mock() val repository = UserRepository(dao, client) 
 fun testSearchUsers() { val expected = Array(10) { MockUser.newInstance(it) }.toList() client.fetchUsers().invoked.thenReturn(expected.toObservable()) val subscriber = TestSubscriver() repository.searchUsers().subscribe(subscriber) with(subscriber){ assertNoErrors() onNextEvents.size.should be 1 assertCompleted() } }

Slide 53

Slide 53 text

53 Repository val dao = mock(); val client = mock() val repository = UserRepository(dao, client) 
 fun testSearchUsers() { val expected = Array(10) { MockUser.newInstance(it) }.toList() client.fetchUsers().invoked.thenReturn(expected.toObservable()) val subscriber = TestSubscriver() repository.searchUsers().subscribe(subscriber) with(subscriber){ assertNoErrors() onNextEvents.size.should be 1 assertCompleted() } }

Slide 54

Slide 54 text

54 UseCase Dao %BUBCBTF API Client Repository UseCase Presenter Activity / Fragment Service ϏδωεϩδοΫΛදݱ͢Δ

Slide 55

Slide 55 text

55 UseCase class UserUseCase (private val repository: UserRepository) { public Observable> searchUsers() {
 return repository.searchUsers();
 } public Observable> fetchRecommendLikeUsers() {
 return repository.fetchRecommendLikeUsers();
 } }

Slide 56

Slide 56 text

56 UseCase val repository = mock val useCase = UserUseCase(repository) @Test fun fetchStatus() {
 val expected = Array(10) { MockUser.newInstance(it) }.toList()
 repository.fetchUsers().invoked.thenReturn(expected.toObservable())
 
 useCase.searchUsers().test().run {
 assertNoErrors()
 assertValues(expected)
 assertCompleted()
 }
 }

Slide 57

Slide 57 text

57 UseCase val repository = mock val useCase = UserUseCase(repository) @Test fun fetchStatus() {
 val expected = Array(10) { MockUser.newInstance(it) }.toList()
 repository.fetchUsers().invoked.thenReturn(expected.toObservable())
 
 useCase.searchUsers().test().run {
 assertNoErrors()
 assertValues(expected)
 assertCompleted()
 }
 }

Slide 58

Slide 58 text

58 UseCase val repository = mock val useCase = UserUseCase(repository) @Test fun fetchStatus() {
 val expected = Array(10) { MockUser.newInstance(it) }.toList()
 repository.fetchUsers().invoked.thenReturn(expected.toObservable())
 
 useCase.searchUsers().test().run {
 assertNoErrors()
 assertValues(expected)
 assertCompleted()
 }
 }

Slide 59

Slide 59 text

59 UseCase val repository = mock val useCase = UserUseCase(repository) @Test fun fetchStatus() {
 val expected = Array(10) { MockUser.newInstance(it) }.toList()
 repository.fetchUsers().invoked.thenReturn(expected.toObservable())
 
 useCase.searchUsers().test().run {
 assertNoErrors()
 assertValues(expected)
 assertCompleted()
 }
 }

Slide 60

Slide 60 text

60 UseCase val repository = mock val useCase = UserUseCase(repository) @Test fun fetchStatus() {
 val expected = Array(10) { MockUser.newInstance(it) }.toList()
 repository.fetchUsers().invoked.thenReturn(expected.toObservable())
 
 useCase.searchUsers().test().run {
 assertNoErrors()
 assertValues(expected)
 assertCompleted()
 }
 }

Slide 61

Slide 61 text

61 UseCase val repository = mock val useCase = UserUseCase(repository) @Test fun fetchStatus() {
 val expected = Array(10) { MockUser.newInstance(it) }.toList()
 repository.fetchUsers().invoked.thenReturn(expected.toObservable())
 
 useCase.searchUsers().test().run {
 assertNoErrors()
 assertValues(expected)
 assertCompleted()
 }
 }

Slide 62

Slide 62 text

·ͱΊ 62

Slide 63

Slide 63 text

63 ·ͱΊ Τ΢ϨΧ͸ώτΛͭͳ͙αʔϏεΛఏڙ͍ͯ͠Δ ςετ͕ແ͍ঢ়ଶ͸ࣄނ͕ى͜Γ΍͍͢ঢ়ଶͰ͋Δ ,PUMJOಋೖͷલʹมߋɾ௥Ճʹڧ͍ίʔυϕʔεͷํ͕ΠϯύΫτେ͖͍ ϓϩμΫγϣϯίʔυʹ,PUMJOΛೖΕΔͷ͕ා͍࣌͸ςετίʔυ͔Βೖ ΕͯΈΔͱΑ͍

Slide 64

Slide 64 text

Credit: NASA Earth Observatory/NOAA NGDC Thank you :)