SlideShare a Scribd company logo
1 of 24
1
Uma abordagem de testes
instrumentados usando MockK, Koin
e Robot Pattern
Lucas Conceição
© 2019 ThoughtWorks
Lucas Conceição
Senior Android consultant
11 anos codando
4 anos codando para Android
2 anos codando em Kotlin
7 meses na ThoughtWorks
2© 2019 ThoughtWorks
PROGRAMAÇÃO
3
TESTES
INSTRUMENTADOS
ROBOT
PATTERN
MOCKK
© 2019 ThoughtWorks
CODEKOIN
O quê, por quê e como
Testes instrumentados
4© 2019 ThoughtWorks
5© 2019 ThoughtWorks
São feitos com
Espresso
Biblioteca para interação com
interfaces.
@Test
fun checkTheAnswer_toLife_theUniverse_andEverything() {
onView(withText("4")).perform(click())
onView(withText("0")).perform(click())
onView(withText("+")).perform(click())
onView(withText("2")).perform(click())
onView(withText("=")).perform(click())
onView(withId(R.id.result))
.check(matches(withText("42")))
}
6© 2019 ThoughtWorks
Motivação
Testes instrumentados:
-Envolvem código de camadas diferentes do app
E por que falar disso?
7© 2019 ThoughtWorks
Motivação
Testes instrumentados:
-Envolvem código de camadas diferentes do app
-Possuem um custo computacional alto
E por que falar disso?
8© 2019 ThoughtWorks
Motivação
Testes instrumentados:
-Envolvem código de camadas diferentes do app
-Possuem um custo computacional alto
-Podem ser visto/utilizado por pessoas que não necessariamente têm contexto de
Android.
E por que falar disso?
9© 2019 ThoughtWorks
Separe o "o quê" do "como"
Robot Pattern
10© 2019 ThoughtWorks
“We're programmers, we are lazy. We want the
most efficient thing that minimizes the amount of
work that we have to do.”
- Clarice Lispector
11© 2019 ThoughtWorks
“We're programmers, we are lazy. We want the
most efficient thing that minimizes the amount of
work that we have to do.”
- Clarice Lispector Jake Wharton
12© 2019 ThoughtWorks
// O fluxo que precisa ser testado
@Test
fun
checkTheAnswer_toLife_theUniverse_andEverything() {
typeText("40")
sumWith()
typeText("2")
askResult()
checkResultIs("42")
}
// Como testar esse fluxo
fun typeText(amount: String) {
for (index in amount.indices) {
onView(withText(amount[index]))
.perform(click())
}
}
fun sumWith() =
onView(withText("+")).perform(click())
fun askResult() =
onView(withText("=")).perform(click())
fun checkResultIs(result: String) =
onView(withId(R.id.result))
.check(matches(withText(result)))
13© 2019 ThoughtWorks
Dá pra melhorar
// O fluxo que precisa ser testado
@Test
fun checkTheAnswer_toLife_theUniverse_andEverything() {
openCalculator {
typeText("40")
sumWith()
typeText("2")
} askResult {
checkResultIs("42")
}
}
Aproveitando as language features do Kotlin dá pra ficar de um jeito mais legível
14© 2019 ThoughtWorks
Crie mocks com facilidade
MockK
15© 2019 ThoughtWorks
MockK
@Test
fun whenLightIsGreen_driverBehavesAccordingly() {
val trafficLight = TrafficLight().apply { color = Color.RED }
val mockedCar: Car = mockk()
every { mockedCar.honk() } returns Unit
val driver = Driver()
driver.enterCar(mockedCar)
driver.observe(trafficLight)
trafficLight.notify(Color.GREEN)
verify { mockedCar.honk() }
}
Como usar
16© 2019 ThoughtWorks
MockK
@Test
fun suvDrivers_areKindOfJerks() {
// inicializa trafficLight e mockedCar
val honkIntensity = slot<Int>()
every { mockedCar.type } returns CarType.SUV
every { mockedCar.honk(capture(honkIntensity)) } returns Unit
// driver é criado, entra no mockedCar e observa a trafficLight
trafficLight.notify(Color.GREEN)
assertThat(honkIntensity.isCaptured).isTrue()
assertThat(honkIntensity.captured).isAtLeast(92)
}
Teste os argumentos passados utilizando Slots
17© 2019 ThoughtWorks
Injeção de dependência leve e fácil
Koin
18© 2019 ThoughtWorks
Injeção de dependência
// A própria classe cria suas dependências
class CarViewModel : ViewModel() {
private val repository: CarRepository
constructor() {
repository = CarRepository()
}
}
19© 2019 ThoughtWorks
// Quem vai usar o objeto decide
// o que passar para ele
class CarViewModel : ViewModel() {
private val repository: CarRepository
constructor(repository: CarRepository) {
this.repository = repository
}
}
Injeção de dependência
class CarViewModel : ViewModel(), KoinComponent {
private val repository: CarRepository by inject()
fun loremIpsum() {
repository.someMethod()
}
}
Com Koin
20© 2019 ThoughtWorks
class CarViewModel : ViewModel(), KoinComponent {
fun onlyMethodThatNeedsTheRepositoryInstance() {
val repository: CarRepository = get()
repository.someMethod()
}
}
Koin
val storageModule = module {
single {
Room.databaseBuilder(
get(),
AppDatabase::class.java,
"your-database"
).build()
}
}
val appModule = module {
single { CarLocalDataSource(get()) }
factory { CarRepository(get()) }
}
Como configurar
21© 2019 ThoughtWorks
// Na sua classe Application
startKoin {
modules(listOf(
appModule,
storageModule /*, networkModule etc. */
))
}
Show me the code
22© 2019 ThoughtWorks
Dúvidas, sugestões ou feedbacks?
23© 2019 ThoughtWorks
Obrigado a todas
24
LUCAS CONCEIÇÃO
lucas.conceicao@thoughtworks.com | thoughtworks.com
© 2019 ThoughtWorks

More Related Content

Similar to Uma abordagem de testes instrumentados usando MockK, Koin e Robot Pattern

Aula 1 view model livedata e databinding.pptx
Aula 1   view model livedata e databinding.pptxAula 1   view model livedata e databinding.pptx
Aula 1 view model livedata e databinding.pptxRicardo Ogliari
 
Introdução à Programação para iPhone (iOS)
Introdução à Programação para iPhone (iOS)Introdução à Programação para iPhone (iOS)
Introdução à Programação para iPhone (iOS)Jorge Cardoso
 
iBeer #17 - Android: Do Java para Kotlin
iBeer #17 - Android: Do Java para KotliniBeer #17 - Android: Do Java para Kotlin
iBeer #17 - Android: Do Java para KotlinDCX Resource IT
 
Comunidades Baseadas Em Subsites
Comunidades Baseadas Em SubsitesComunidades Baseadas Em Subsites
Comunidades Baseadas Em Subsitesalessandrolandim
 
Usando React Native & Multi Módulos para Escalar App Creditas
Usando React Native & Multi Módulos para Escalar App CreditasUsando React Native & Multi Módulos para Escalar App Creditas
Usando React Native & Multi Módulos para Escalar App CreditasJuliana Chahoud
 
Tchelinux: Go Web!
Tchelinux:  Go Web!Tchelinux:  Go Web!
Tchelinux: Go Web!Lucas L.
 
Desenvolvimento Mobile com Visual Studio 2008, por onde começar?
Desenvolvimento Mobile com Visual Studio 2008, por onde começar?Desenvolvimento Mobile com Visual Studio 2008, por onde começar?
Desenvolvimento Mobile com Visual Studio 2008, por onde começar?Stefanini
 
TDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no AndroidTDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no Androidtdc-globalcode
 
TDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no AndroidTDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no Androidtdc-globalcode
 
TDC2018SP | Trilha Mobile - Flutter: do zero a publicacao
TDC2018SP | Trilha Mobile - Flutter: do zero a publicacaoTDC2018SP | Trilha Mobile - Flutter: do zero a publicacao
TDC2018SP | Trilha Mobile - Flutter: do zero a publicacaotdc-globalcode
 
Apresentação desenvolvimento de plataforma para comandar microcontroladores e...
Apresentação desenvolvimento de plataforma para comandar microcontroladores e...Apresentação desenvolvimento de plataforma para comandar microcontroladores e...
Apresentação desenvolvimento de plataforma para comandar microcontroladores e...Thiago Barros, PSM
 
259 Club ServiceNow LowCode
259 Club ServiceNow LowCode259 Club ServiceNow LowCode
259 Club ServiceNow LowCodeTiago Macul
 
Hexagonal Architecture
Hexagonal ArchitectureHexagonal Architecture
Hexagonal ArchitectureLucas Moura
 
O que você precisa para iniciar no iOS e Objective-C -
O que você precisa para iniciar no iOS e Objective-C - O que você precisa para iniciar no iOS e Objective-C -
O que você precisa para iniciar no iOS e Objective-C - Fábio Pimentel
 
Webinar: Desenvolvimento de Interface Gráfica para Embarcados
Webinar: Desenvolvimento de Interface Gráfica para EmbarcadosWebinar: Desenvolvimento de Interface Gráfica para Embarcados
Webinar: Desenvolvimento de Interface Gráfica para EmbarcadosEmbarcados
 
Apresentando o EcmaScript 6
Apresentando o EcmaScript 6Apresentando o EcmaScript 6
Apresentando o EcmaScript 6Giovanni Bassi
 
Microsoft (TDC 2015 Keynote)
Microsoft (TDC 2015 Keynote)Microsoft (TDC 2015 Keynote)
Microsoft (TDC 2015 Keynote)Fabrício Catae
 

Similar to Uma abordagem de testes instrumentados usando MockK, Koin e Robot Pattern (20)

Aula 1 view model livedata e databinding.pptx
Aula 1   view model livedata e databinding.pptxAula 1   view model livedata e databinding.pptx
Aula 1 view model livedata e databinding.pptx
 
Introdução à Programação para iPhone (iOS)
Introdução à Programação para iPhone (iOS)Introdução à Programação para iPhone (iOS)
Introdução à Programação para iPhone (iOS)
 
iBeer #17 - Android: Do Java para Kotlin
iBeer #17 - Android: Do Java para KotliniBeer #17 - Android: Do Java para Kotlin
iBeer #17 - Android: Do Java para Kotlin
 
Comunidades Baseadas Em Subsites
Comunidades Baseadas Em SubsitesComunidades Baseadas Em Subsites
Comunidades Baseadas Em Subsites
 
Usando React Native & Multi Módulos para Escalar App Creditas
Usando React Native & Multi Módulos para Escalar App CreditasUsando React Native & Multi Módulos para Escalar App Creditas
Usando React Native & Multi Módulos para Escalar App Creditas
 
Tchelinux: Go Web!
Tchelinux:  Go Web!Tchelinux:  Go Web!
Tchelinux: Go Web!
 
Analise Bay Area Bike Sharing
Analise Bay Area Bike SharingAnalise Bay Area Bike Sharing
Analise Bay Area Bike Sharing
 
Flutter do zero a publicacao
Flutter do zero a publicacaoFlutter do zero a publicacao
Flutter do zero a publicacao
 
Desenvolvimento Mobile com Visual Studio 2008, por onde começar?
Desenvolvimento Mobile com Visual Studio 2008, por onde começar?Desenvolvimento Mobile com Visual Studio 2008, por onde começar?
Desenvolvimento Mobile com Visual Studio 2008, por onde começar?
 
TDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no AndroidTDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no Android
 
TDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no AndroidTDC2016POA | Trilha Android - Testes no Android
TDC2016POA | Trilha Android - Testes no Android
 
TDC2018SP | Trilha Mobile - Flutter: do zero a publicacao
TDC2018SP | Trilha Mobile - Flutter: do zero a publicacaoTDC2018SP | Trilha Mobile - Flutter: do zero a publicacao
TDC2018SP | Trilha Mobile - Flutter: do zero a publicacao
 
Flutter do zero a publicacao
Flutter do zero a publicacaoFlutter do zero a publicacao
Flutter do zero a publicacao
 
Apresentação desenvolvimento de plataforma para comandar microcontroladores e...
Apresentação desenvolvimento de plataforma para comandar microcontroladores e...Apresentação desenvolvimento de plataforma para comandar microcontroladores e...
Apresentação desenvolvimento de plataforma para comandar microcontroladores e...
 
259 Club ServiceNow LowCode
259 Club ServiceNow LowCode259 Club ServiceNow LowCode
259 Club ServiceNow LowCode
 
Hexagonal Architecture
Hexagonal ArchitectureHexagonal Architecture
Hexagonal Architecture
 
O que você precisa para iniciar no iOS e Objective-C -
O que você precisa para iniciar no iOS e Objective-C - O que você precisa para iniciar no iOS e Objective-C -
O que você precisa para iniciar no iOS e Objective-C -
 
Webinar: Desenvolvimento de Interface Gráfica para Embarcados
Webinar: Desenvolvimento de Interface Gráfica para EmbarcadosWebinar: Desenvolvimento de Interface Gráfica para Embarcados
Webinar: Desenvolvimento de Interface Gráfica para Embarcados
 
Apresentando o EcmaScript 6
Apresentando o EcmaScript 6Apresentando o EcmaScript 6
Apresentando o EcmaScript 6
 
Microsoft (TDC 2015 Keynote)
Microsoft (TDC 2015 Keynote)Microsoft (TDC 2015 Keynote)
Microsoft (TDC 2015 Keynote)
 

Uma abordagem de testes instrumentados usando MockK, Koin e Robot Pattern

  • 1. 1 Uma abordagem de testes instrumentados usando MockK, Koin e Robot Pattern Lucas Conceição © 2019 ThoughtWorks
  • 2. Lucas Conceição Senior Android consultant 11 anos codando 4 anos codando para Android 2 anos codando em Kotlin 7 meses na ThoughtWorks 2© 2019 ThoughtWorks
  • 4. O quê, por quê e como Testes instrumentados 4© 2019 ThoughtWorks
  • 6. São feitos com Espresso Biblioteca para interação com interfaces. @Test fun checkTheAnswer_toLife_theUniverse_andEverything() { onView(withText("4")).perform(click()) onView(withText("0")).perform(click()) onView(withText("+")).perform(click()) onView(withText("2")).perform(click()) onView(withText("=")).perform(click()) onView(withId(R.id.result)) .check(matches(withText("42"))) } 6© 2019 ThoughtWorks
  • 7. Motivação Testes instrumentados: -Envolvem código de camadas diferentes do app E por que falar disso? 7© 2019 ThoughtWorks
  • 8. Motivação Testes instrumentados: -Envolvem código de camadas diferentes do app -Possuem um custo computacional alto E por que falar disso? 8© 2019 ThoughtWorks
  • 9. Motivação Testes instrumentados: -Envolvem código de camadas diferentes do app -Possuem um custo computacional alto -Podem ser visto/utilizado por pessoas que não necessariamente têm contexto de Android. E por que falar disso? 9© 2019 ThoughtWorks
  • 10. Separe o "o quê" do "como" Robot Pattern 10© 2019 ThoughtWorks
  • 11. “We're programmers, we are lazy. We want the most efficient thing that minimizes the amount of work that we have to do.” - Clarice Lispector 11© 2019 ThoughtWorks
  • 12. “We're programmers, we are lazy. We want the most efficient thing that minimizes the amount of work that we have to do.” - Clarice Lispector Jake Wharton 12© 2019 ThoughtWorks
  • 13. // O fluxo que precisa ser testado @Test fun checkTheAnswer_toLife_theUniverse_andEverything() { typeText("40") sumWith() typeText("2") askResult() checkResultIs("42") } // Como testar esse fluxo fun typeText(amount: String) { for (index in amount.indices) { onView(withText(amount[index])) .perform(click()) } } fun sumWith() = onView(withText("+")).perform(click()) fun askResult() = onView(withText("=")).perform(click()) fun checkResultIs(result: String) = onView(withId(R.id.result)) .check(matches(withText(result))) 13© 2019 ThoughtWorks
  • 14. Dá pra melhorar // O fluxo que precisa ser testado @Test fun checkTheAnswer_toLife_theUniverse_andEverything() { openCalculator { typeText("40") sumWith() typeText("2") } askResult { checkResultIs("42") } } Aproveitando as language features do Kotlin dá pra ficar de um jeito mais legível 14© 2019 ThoughtWorks
  • 15. Crie mocks com facilidade MockK 15© 2019 ThoughtWorks
  • 16. MockK @Test fun whenLightIsGreen_driverBehavesAccordingly() { val trafficLight = TrafficLight().apply { color = Color.RED } val mockedCar: Car = mockk() every { mockedCar.honk() } returns Unit val driver = Driver() driver.enterCar(mockedCar) driver.observe(trafficLight) trafficLight.notify(Color.GREEN) verify { mockedCar.honk() } } Como usar 16© 2019 ThoughtWorks
  • 17. MockK @Test fun suvDrivers_areKindOfJerks() { // inicializa trafficLight e mockedCar val honkIntensity = slot<Int>() every { mockedCar.type } returns CarType.SUV every { mockedCar.honk(capture(honkIntensity)) } returns Unit // driver é criado, entra no mockedCar e observa a trafficLight trafficLight.notify(Color.GREEN) assertThat(honkIntensity.isCaptured).isTrue() assertThat(honkIntensity.captured).isAtLeast(92) } Teste os argumentos passados utilizando Slots 17© 2019 ThoughtWorks
  • 18. Injeção de dependência leve e fácil Koin 18© 2019 ThoughtWorks
  • 19. Injeção de dependência // A própria classe cria suas dependências class CarViewModel : ViewModel() { private val repository: CarRepository constructor() { repository = CarRepository() } } 19© 2019 ThoughtWorks // Quem vai usar o objeto decide // o que passar para ele class CarViewModel : ViewModel() { private val repository: CarRepository constructor(repository: CarRepository) { this.repository = repository } }
  • 20. Injeção de dependência class CarViewModel : ViewModel(), KoinComponent { private val repository: CarRepository by inject() fun loremIpsum() { repository.someMethod() } } Com Koin 20© 2019 ThoughtWorks class CarViewModel : ViewModel(), KoinComponent { fun onlyMethodThatNeedsTheRepositoryInstance() { val repository: CarRepository = get() repository.someMethod() } }
  • 21. Koin val storageModule = module { single { Room.databaseBuilder( get(), AppDatabase::class.java, "your-database" ).build() } } val appModule = module { single { CarLocalDataSource(get()) } factory { CarRepository(get()) } } Como configurar 21© 2019 ThoughtWorks // Na sua classe Application startKoin { modules(listOf( appModule, storageModule /*, networkModule etc. */ )) }
  • 22. Show me the code 22© 2019 ThoughtWorks
  • 23. Dúvidas, sugestões ou feedbacks? 23© 2019 ThoughtWorks
  • 24. Obrigado a todas 24 LUCAS CONCEIÇÃO lucas.conceicao@thoughtworks.com | thoughtworks.com © 2019 ThoughtWorks