Testes de ponta a ponta

Post on 22-Jan-2018

381 views 1 download

Transcript of Testes de ponta a ponta

Testes de Ponta a Ponta

Eduardo Carrara - @DuCarrara

Android Developer

Elias Nogueira - @eliasnogueira

Agile Coach @ Sicredi

Introdução

Unit Test

IntegrationTest

UITest

Pirâmide de Automação de Teste

Pipeline ideal para execução dos testes

Análise Estática

Testes Unitários

Testes de Integração

Testes de Serviços

Testes de Aceitação

Testes Funcionais

Mock

Execução Paralela

Smoke Test

Unidades de TrabalhoIsoláveis de dependências Externas

Possibilitam testes rápidos

Pequenas como métodos ou grandes como conjuntos de classes

Lembrete: Arrange, Act, Assert

Tipos de Testes Unitários (by The Art of Unit Testing)

Value Based Testing

Interaction Based Testing

State Based Testing

MockingDeve ajudar a lidar com as dependências de maneira simples

Prover objetos dublês (mocks, stubs etc)

Isolar a unidade a ser testada

Fornecer controle sobre comportamento e estado

Code Time!

Value Based Unit Test

@Test fun searchForBookBy_whenCalled_withValidISBN_returnsBookSuccessfully() {

// Arrange

val fakeISBN = "8575224123"

val (bookCollectionToBeReturned, expectedBook)

= getInputAndExpectedDataFrom(inputResource)

val googleBooksRestApi: GoogleBooksRestApi = mock {

on { searchVolumeData(any(), any()) }

.doReturn( Single.just(bookCollectionToBeReturned))

}

// Act and Assert

GoogleBooksRestDataSource(googleBooksRestApi)

.searchForBookBy(fakeISBN)

.test().assertValue(expectedBook).assertComplete()

}

State Based Unit Test

@Test fun getByIsbn_whenCalled_withoutIsbnInCache_cachesBook() {

// Arrange

val fakeBook = getFakeBook()

whenever(bookRemoteDataSource.searchForBookBy(fakeBook.isbn10))

.thenReturn(Maybe.just(fakeBook))

// Act

bookCachedRepository.getByIsbn(fakeBook.isbn10).test().assertComplete()

// Assert

bookContentProviderCache[fakeBook.isbn10].test().assertComplete()

.assertValue{ returnedBook ->

assertSame(expected = fakeBook, real = returnedBook) }

}

Interaction Based Unit Test

@Test fun getByIsbn_whenCalled_withExistingIsbnInCache_neverCallsRemoteDataSource() {

// Arrange

val cachedFakeBook = insertFakeBookIntoCache()

var remoteDataSourceWasTriggered = false

onBookRemoteDataSourceSearchForBookByCompletedTriggers {

remoteDataSourceWasTriggered = true }

// Act

bookCachedRepository.getByIsbn(cachedFakeBook.isbn10)

.test().assertComplete()

// Assert No Interaction

assertThat(remoteDataSourceWasTriggered, `is`(false))

}

Robolectric + Mockito Tip of the Day@RunWith(RobolectricTestRunner::class)

@Config(constants = BuildConfig::class)

class BookCachedRepositoryTest {

@get:Rule

val mockitoRule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS)

@get:Rule

val robolectricVilibraProviderRule = RobolectricVilibraProviderRule()

@Mock

lateinit var bookRemoteDataSource: BookRemoteDataSource

private val bookContentProviderCache =

BookContentProviderCache(RuntimeEnvironment.application)

private lateinit var bookCachedRepository: BookCachedRepository

}

Testes Integrados

Photo by Brady Holt on Wikimedia

Mock Driver

Android Instrumentation TestsQuando não conseguimos nos livrar das dependências

Não são tão rápidos nem tão simples como testes unitários

Geralmente focados em testes funcionais baseados na UI

Como seu usuário interage com o app?

Android Testing Support LibraryAndroidJUnitRunner + JUnit4 Rules + Espresso + UIAutomator

Muito focado em testes de Interface do Usuário

Instrumentation Testing RobotsUm Pattern com foco na organização dos testes

Melhorar a legibilidade e manutenção dos testes

Separar "o como testar" do "o que testar"

Muito similar aos Page Objects

Test(O que)

Robot(O como)

View

Presenter(O como)

Fake Model(O que)

Code Time!

Simple Espresso Test @Test fun whenOpened_withOneBookLending_displayBookLendingCorrectly_pureEspresso() {

val fakeBook = testDataRule.fakeBook

Espresso.onView(

Matchers.allOf<View>(

ViewMatchers.withId(R.id.book_name_text_view),

ViewMatchers.hasSibling(ViewMatchers.withText(fakeBook.title))

))

.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))

Espresso.onView(

Matchers.allOf<View>(

ViewMatchers.withId(R.id.book_author_text_view),

ViewMatchers.hasSibling(ViewMatchers

.withText(fakeBook.authors.joinToString(",")))))

.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))

}

Instrumentation Testing Robot (ITR)

@Test

fun whenOpened_withOneBookLending_displayBookLendingCorrectly() {

val fakeBook = testDataRule.fakeBook

lentBooks {

checkForBookTitle(fakeBook.title)

checkForBookAuthors(fakeBook.authors.joinToString(","))

}

}

ITR - Internals

fun lentBooks(func: LentBooksRobot.() -> Unit) = LentBooksRobot().apply { func() }

class LentBooksRobot {

fun checkForBookTitle(expectedTitle: String): LentBooksRobot {

Espresso.onView(

Matchers.allOf<View>(

ViewMatchers.withId(R.id.book_name_text_view),

ViewMatchers.hasSibling(ViewMatchers.withText(expectedTitle))

))

.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))

return this

}

}

ITR - Outro Exemplo

@Test

fun lendBookToContact() {

val expectedIsbn = "8575224123"

val expectedBookTitle

= "Dominando o Android"

lentBooks {

addBookLending()

}

searchBook {

fillIsbn(expectedIsbn)

confirm()

}

bookDetails {

checkForBookTitle(expectedBookTitle)

checkForBookIsbn10("ISBN-10: $expectedIsbn")

lend()

}

contacts {

pickContact("Meu Irmao")

}

lentBooks {

checkForBookTitle(expectedBookTitle)

}

...

Testes de Aceitação

Photo by TireRack.com

Page ObjectsUm Pattern com foco na organização dos testes

Melhorar a legibilidade e manutenção dos testes

Separar "o como testar" do "o que testar"

public void fillISBN(String isbnText) {

isbn.sendKeys(isbnText);

driver.hideKeyboard();

}

public void clickInConfirm() {

confirm.click();

}

Transformar ações do usuário em código

Page Objects

Scan Livro Preencher ISBN Emprestar Livro Selecionar contato Ver Detalhes Livro

Teste de Aceitação (E2E) - Emprestar um livro a um contato

@Test

public void leandABook() {

MainPage mainPage = new MainPage(driver);

mainPage.clickAddLeaging();

BookScanPage scan = new BookScanPage(driver);

scan.fillISBN("8575224638");

BookDetailsPage details = new BookDetailsPage(driver);

assertEquals("Dominando o Android 2ª edição", details.getBookTitle());

details.clickLeandThisBook();

ContactPage contactPage = new ContactPage(driver);

contactPage.clickMenuSearchIcon();

mainPage = new MainPage(driver);

assertEquals("Dominando o Android 2ª edição", mainPage.getBookName());

}

Photo by Rian MacGuire on PixelBay

Testes Além do app

Testar os serviços (REST | WebService)Testar se endpoint está ativo

Teste Funcional

Teste de Contrato

Teste de Aceitação (fluxo da API sem UI)

Pensamentos FinaisTeste as engrenagens de forma isoladaTestes as engrenagens em conjunto

Foco nas interações dos usuários na aplicação

Não esqueça de testar os seus serviços

Perguntas?

Eduardo Carrara

@DuCarrara

Obrigado!

github.com/ecarrara-araujo

Elias Nogueira

@eliasnogueira

github.com/eliasnogueira

Referências1. Testing on Android Documentation by Android Developers2. Android Testing Patterns Youtube Playlist3. The Art of Unit Testing by Roy Osherove4. Instrumentation Testing Robots by Jake Warthon5. Page Objects by Martin Fowler6. Test Pyramid7. Page Objects8. Android Tests by Goggle Samples9. Android Testing Templates by Google Samples

10. Espresso Cheat Sheet

Códigohttps://github.com/ecarrara-araujo/vilibrahttps://github.com/eliasnogueira/vilibra-testing