Android DevConference - Indo além com automação de testes de apps Android

96 views

Published on

Eduardo Carrara, fala sobre Indo além com automação de testes de apps Android no Android DevConference 2016. Saiba mais em: http://androidconference.com.br/

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
96
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
2
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Android DevConference - Indo além com automação de testes de apps Android

  1. 1. Indo Além com Automação e Testes de Apps Android Eduardo Carrara @DuCarrara
  2. 2. Você já se sentiu assim em seus projetos?
  3. 3. Infelizmente não há bala de prata...
  4. 4. Precisamos de segurança, para Iterações Rápidas.
  5. 5. Testes Automatizados podem ajudar Então o que vamos explorar hoje? Recursos Externos & Test Flakiness Simplificação de Dependências com Mocks UI Tests e as Camadas de Testes
  6. 6. Recursos Externos e Test Flakiness “Non-deterministic tests have two problems, firstly they are useless, secondly they are a virulent infection that can completely ruin your entire test suite.” - Martin Fowler
  7. 7. Test Flakiness Falham e passam aleatoriamente Diminuem a confiança na suite de testes Escondem bugs São difíceis de corrigir
  8. 8. Principais Causas Concorrência Dependência de comportamentos indefinidos ou não determinísticos Código de terceiros que falham e funcionam aleatoriamente Problemas de infraestrutura <adicione sua causa aqui>
  9. 9. O que acontece no Android? Rede Recursos de Hardware do telefone (ex.: sensores) Interação com outros apps Dependências de serviços, apis e sdks externos
  10. 10. Exemplificando Caso comum: chamadas a serviços REST Dependência de recursos de rede, disponibilidade de serviços etc Como resolver o flakiness no teste da chamada de um serviço? Resposta: Desacoplar e Isolar
  11. 11. Desacoplando e Isolando Presentation Domain Data Activity Fragment Views Use Cases Repositories Biz Entities Data Sources Data Entities RestAPI Network Latency Service Errs. etc... Origem do flakiness
  12. 12. Desacoplando e Isolando Data Layer RestAPI Server RestApi Connection RestApi Interface API Calls Retrofit OkHttp etc <<builds>> <<network calls>> Produção App Config Base URL <<provides>> <<injects>>
  13. 13. Desacoplando e Isolando Test Mock Local Server RestApi Connection RestApi Interface Retrofit OkHttp etc <<builds>> <<local calls>> Teste Test URL Test Responses <<provides>> <<injects>> <<creates>>
  14. 14. E o código... Com Retrofit + OkHttp + MockWebServer dependencies { testCompile 'com.squareup.okhttp3:mockwebserver:3.3.0' }
  15. 15. E o código... @Before public void setUp() throws IOException { prepareExpectedTestData(); server = new MockWebServer(); server.enqueue( new MockResponse() .setBody(TestServiceResponseFor20150907.getJson()) ); server.start(); restApi = new RestApi(server.url("/").toString()); } @After public void tearDown() throws IOException { server.shutdown(); } Exemplo em NEOM on Github: ListNearEarthObjectsTest.java
  16. 16. E o código... @Test public void testSuccessfulListNearEarthObjects() throws Exception { List<NearEarthObjectJsonEntity> nearEarthObjectJsonEntityList = restApi.listNearEarthObjectsFor(requestDate); assertThat(nearEarthObjectJsonEntityList, is(expectedNearEarthObjectJsonEntityList)); } Exemplo em NEOM on Github: ListNearEarthObjectsTest.java
  17. 17. Em nosso exemplo... Isolamos a chamada à nossos serviços Substituímos o servidor por um componente sob nosso controle Podemos testar esta camada com testes unitários Tomamos controle sobre um recurso que poderia ser Flaky
  18. 18. Simplificação com Mocks
  19. 19. Dependências + Dependências = + Acoplamento Alto acoplamento dificulta a criação de testes e a automação Sistemas 100% desacoplados são raros
  20. 20. Mocking Objetos dublês Controle sobre o comportamento e estado Isolamento da unidade a ser testada Deve nos ajudar a lidar com as dependências de maneira simples
  21. 21. O que acontece no Android? Dependência de componentes do framework é frequente Ex.: Context, Dados de Sensores, Services, Activities etc Complexidade dos testes aumenta muito
  22. 22. Mockito API fácil de entender Configuração de comportamentos e Stubs Permite a verificação de comportamentos
  23. 23. Mas como funciona? Exemplo em NEOM on Github: NearEarthObjectListPresenterTest.java @RunWith(MockitoJUnitRunner. class) public class NearEarthObjectListPresenterTest { NearEarthObjectListPresenter presenter; @Mock private ObservableInteractor<List<NearEarthObject>> mockInteractor; @Mock private NearEarthObjectsListView mockView; @Captor private ArgumentCaptor<Observer<List<NearEarthObject>>> observerArgumentCaptor; @Before private void setUp() { presenter = new NearEarthObjectListPresenter( mockInteractor); } }
  24. 24. Mas como funciona? Exemplo em NEOM on Github: NearEarthObjectListPresenterTest.java @Test public void testSuccessfulPresenterInitialization() { presenter.attachTo(mockView); verify(mockView).hideRetry(); verify(mockView).showLoading(); // Here we capture the observer registration to mock the update call verify(mockInteractor, times(1)) .addObserver(observerArgumentCaptor.capture()); verify(mockInteractor).execute(); observerArgumentCaptor.getValue() .update(mockInteractor, new ArrayList<NearEarthObject>()); verify(mockView).renderNearEarthObjectsList(any(List.class)); verify(mockView).hideLoading(); }
  25. 25. Robolectric Testes que dependem do Android na JVM Provê mocks e stubs ao Android SDK Execução mais rápida de testes Demora para disponibilizar versões mais recentes do SDK
  26. 26. Mas como funciona? Exemplo em NEOM on Github: NearEarthObjectsListActivityTest.java @RunWith(RobolectricGradleTestRunner.class) @Config(constants = BuildConfig.class, sdk = Build.VERSION_CODES.LOLLIPOP) public class NearEarthObjectsListActivityTest { private NearEarthObjectsListActivity nearEarthObjectsListActivity; @Before public void setup() { nearEarthObjectsListActivity = Robolectric.setupActivity(NearEarthObjectsListActivity.class); } }
  27. 27. Mas como funciona? Exemplo em NEOM on Github: NearEarthObjectsListActivityTest.java @Test public void testErrorMessageDisplay() { final String expectedErrorMessage = "Error message"; nearEarthObjectsListActivity.showError(expectedErrorMessage); View errorView = findById(nearEarthObjectsListActivity, R.id.error_view); TextView errorTextView = findById(nearEarthObjectsListActivity, R.id.error_message_text_view); assertThat(errorView.getVisibility(), is(VISIBLE)); assertThat(errorTextView.getText().toString(), is(expectedErrorMessage)); }
  28. 28. + Combinação Poderosa Testes Rodando na JVM Local = Produtividade Ajuda com dependências indiretas do Android Framework Permite o mocking e uso de classes do Android na JVM Local
  29. 29. Exemplificando Caso: Uso de dados obtidos de um Content Provider O Content Provider nos provê um Cursor Como testar um componente que dependa de um Cursor? Resposta: Mocks* * A classe MockCursor do Android Framework foi Deprecated na API Level 24. Uma das sugestões é usar o Mockito com ATSL.
  30. 30. Mocking Component Content Provider Content Resolver <<creates>><<uses>> Produção <<queries>> Cursor <<queries>>
  31. 31. Mocking Component Content Provider Content Resolver <<creates>><<uses>> Teste <<queries>> Cursor <<queries>> Componente a ser Testado Boilerplate
  32. 32. Mocking Component <<mocks>> <<uses>> Teste Cursor Test <<tests>>
  33. 33. E o código... Com Mockito + Robolectric dependencies { testCompile 'org.robolectric:robolectric:3.0' testCompile 'org.mockito:mockito-core:2.+' }
  34. 34. E o código... @RunWith(RobolectricGradleTestRunner.class) @Config(constants = BuildConfig.class) public class BookBorrowingContentProviderMapperTest { @Before public void prepareTest() { this.bookBorrowingContentProviderMapper = new BookBorrowingContentProviderMapper(); } @Test public void testTransformEmptyCursorToBookBorrowing() throws Exception { Cursor cursor = mock(Cursor.class); when(cursor.moveToFirst()).thenReturn(false); List<BookBorrowing> bookBorrowings = this.bookBorrowingContentProviderMapper.transform(cursor); assertThat(bookBorrowings, is(empty())); } } Exemplo em Vilibra on Github: BookBorrowingContentProviderMapperTest.java
  35. 35. Em nosso exemplo... Isolamos o componente a ser testado de dependências boilerplate Usamos mocks para criar as situações de teste desejadas Podemos rodar nossos testes como testes unitários na JVM
  36. 36. Usando mocks lembre-se... Se você cria mocks para tudo você não testa nada Mocks nos ajudam a isolar o componente a ser testado e a ter controle sobre dependências e comportamentos externos Podem ajudar a reduzir flakiness
  37. 37. UI Tests e as Camadas de Testes
  38. 38. Fonte: Layers of Test Automation by Stuart Ashman Camadas de Testes Estratégia para automação de testes Onde investir nossos recursos para automação? Layers of Test by Mike Cohn
  39. 39. Criação e Manutenção Execução e Criação Custo Tempo $ $$ $$$ Testes Unitários Testes de Integração UI Testes Manuais e Exploratórios $$$$
  40. 40. Testes de Interface do Usuário (UI) Devem focar em funcionalidades, user stories, casos de uso etc Testes do ponto de vista do usuário (UI) Retira o trabalho repetitivo do time QA pode se dedicar a testes mais complexos
  41. 41. ATST Algumas Ferramentas
  42. 42. Android Testing Support Library Execução relativamente rápida Bem próximo da plataforma e exige conhecimentos de dev. Utiliza as mesmas ferramentas que usamos para criar as apps Difícil para não desenvolvedores
  43. 43. Android Testing Support Library Ferramentas específicas para testes de componentes Android AndroidJUnitRunner + JUnit4 Rules + Espresso + UIAutomator Em geral compatível com Api Level 8 ou superior UIAutomator é compatível com Api Level 18 ou superior
  44. 44. UI Tests App External Dependency <<mocks>> Uma abordagem possível External DependencyExternal Dependency External Dependency Test <<instruments>> <<tests>> Espresso UIAutomator <<uses>>
  45. 45. Um exemplo simples... android { defaultConfig{ testInstrumentationRunner ”android.support.test.runner.AndroidJUnitRunner” } } dependencies { androidTestCompile 'com.android.support.test:runner:0.5' androidTestCompile 'com.android.support.test:rules:0.5' androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2' androidTestCompile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2' } Exemplo em Vilibra on Github: TestEmptyLoanedBooksList.java
  46. 46. Um exemplo simples... Exemplo em Vilibra on Github: TestEmptyLoanedBooksList.java @RunWith(AndroidJUnit4.class) public class TestEmptyLoanedBooksList { private Context context; @Rule public ActivityTestRule<BookListActivity> activityRule = new ActivityTestRule<>(BookListActivity.class); @Before public void setUp() { this.context = getTargetContext(); clearTestData(); } @Test public void simpleTestEmptyStateOfLoanedBooksList() { onView(withId(R.id.loaned_book_list_view)).check(matches(not(isDisplayed()))); onView(withId(R.id.empty_book_list_icon)).check(matches(isDisplayed())); } }
  47. 47. Testes de Interface do Usuário (UI) São difíceis de criar e manter Sua execução geralmente é mais lenta, deixe-os para o final Selecione a ferramenta adequada aos conhecimentos do time Quer saber mais? Dê uma olhada em minhas outras apresentações!
  48. 48. Pensamentos Finais Mantenha o Test Flakiness sob controle Mocks podem aumentar sua produtividade e controlar o flakiness Testes de UI são difíceis de criar e manter, use-os sabiamente Cuide de seus códigos de testes assim como você cuida de seus códigos de produção!
  49. 49. “… if you are afraid to change something it is clearly poorly designed.” - Martin Fowler Perguntas? http://goo.gl/oms4Hs Material em:
  50. 50. Eduardo Carrara @DuCarrara Obrigado! github.com/ecarrara-araujo
  51. 51. Referências 1. Building Effective Unit Tests by Android Documentation 2. How to Deal With and Eliminate Flaky Tests 3. Flaky Tests at Google and How We Mitigate Them 4. Eradicating Non-Determinism in Tests by Martin Fowler 5. Retrofit 2 – Mocking HTTP Responses 6. The Difference Between Mocks and Stubs by Martin Fowler 7. Mockito 8. Robolectric 9. Layers of Test Automation 10. Android Test Support Library 11. Espresso Test Recorder Docs

×