47
Android: Testes Automatizados e TDD Ivan de Aguirre @IvAguirre [email protected]

Android: testes automatizados e TDD

  • Upload
    dextra

  • View
    1.687

  • Download
    4

Embed Size (px)

DESCRIPTION

Palestra ministrada por Ivan de Aguirre no AndoidDay 2013.

Citation preview

Page 1: Android: testes automatizados e TDD

Android: Testes Automatizados e TDD

Ivan de Aguirre@IvAguirre

[email protected]

Page 2: Android: testes automatizados e TDD

Agenda

• Conceitos e Terminologia.• Overview do Framework de

testes.• O que testar?• TDD

Page 3: Android: testes automatizados e TDD

Conceitos e Terminologia

Page 4: Android: testes automatizados e TDD

• Teste isolado de uma unidade do software.• Unidade precisa ser testável.• Uso de mocks, stubs e fakes.• Execução rápida.• Teste Unitário Clássico: unidade = classe.• TDD: unidade = comportamento.

Teste Unitário

Page 5: Android: testes automatizados e TDD

• Teste isolado de uma unidade do software.• Unidade precisa ser testável.• Uso de mocks, stubs e fakes.• Execução rápida.• Teste Unitário Clássico: unidade = classe.• TDD: unidade = comportamento.

Teste Unitário

You can't have unit tests if you don't have units.@CompSciFact

Page 6: Android: testes automatizados e TDD

Teste de API• Testes de endpoint.• Sistema integrado.• Asserções são mais difíceis.• Testes mais difíceis de manter.• Execução mais lenta.• Ex.: método de uma classe de

serviço, chamada à um webservice.

Page 7: Android: testes automatizados e TDD

• Black Box.• Execução manual.• É o que o tester faz.

Teste Funcional

Page 8: Android: testes automatizados e TDD

Teste de UI• Simula uma execução de teste

funcional.• Difíceis de manter.• Execução lenta.

Page 9: Android: testes automatizados e TDD

Testes Automatizados

• Integrados à build contínua.• Feedback constante.• Todos os testes devem estar

passando sempre.

Não elimina a necessidade de testes manuais.

Page 10: Android: testes automatizados e TDD

Afinal, o que esperamos ao escrever testes?

Page 11: Android: testes automatizados e TDD

Afinal, o que esperamos ao escrever testes?

Feedback

Page 12: Android: testes automatizados e TDD

Afinal, o que esperamos ao escrever testes?

QualidadeFeedback

Page 13: Android: testes automatizados e TDD

Afinal, o que esperamos ao escrever testes?

QualidadeFeedback

Evitar bugs

Page 14: Android: testes automatizados e TDD

Afinal, o que esperamos ao escrever testes?

QualidadeFeedback

Evitar bugs Agilidade

Page 15: Android: testes automatizados e TDD

Afinal, o que esperamos ao escrever testes?

QualidadeFeedback

Evitar bugs

Confiança

Agilidade

Page 16: Android: testes automatizados e TDD

Framework

Page 17: Android: testes automatizados e TDD

• Classe base: AndroidTestCase• Especializações:o ApplicationTestCaseo LoaderTestCaseo ServiceTestCaseo ProviderTestCase2

Testes Unitários

Page 18: Android: testes automatizados e TDD

public class AppProviderTestCase extends ProviderTestCase2<DataProvider> { private MockContentResolver mMockResolver;

public AppProviderTestCase() { super(DataProvider.class, Question.AUTHORITY); } @Override protected void setUp() throws Exception { super.setUp(); mMockResolver = getMockContentResolver(); }

Page 19: Android: testes automatizados e TDD

public void testInsertAndRetrieveQuestions2() { Question q = new Question(1L, "Concorda ?"); q.addRecord(getMockContext()); Cursor c = mMockResolver.query( Question.CONTENT_URI, null, null, null, null); Question retrieved = new Question(c); assertEquals(1, c.getCount()); assertEquals(q.getId(), retrieved.getId()); assertEquals(q.getQuestionText(), retrieved.getQuestionText());}

Page 20: Android: testes automatizados e TDD

• Classe base: InstrumentationTestCase

• Especializações:o ActivityTestCase

§ ActivityUnitTestCase (onCreate).§ ActivityInstrumentationTestCase2

(ciclo completo).

Testes com Instrumentação

Page 21: Android: testes automatizados e TDD

public class QuestionActivityTestCase extends ActivityUnitTestCase<QuestionActivity> { ... public void testIntent() { Intent intent = new Intent(); String question = "Pergunta !!!"; intent.putExtra(Question.Columns.QUESTIONTEXT, question); Activity activity = startActivity(intent, null, null); TextView view = (TextView) activity.findViewById( R.id.question_text); assertEquals(question, view.getText()); }}

Page 22: Android: testes automatizados e TDD

public class MainActivityTestCase extendsActivityInstrumentationTestCase2<MainActivity> {

public MainActivityTestCase() { super(MainActivity.class); }

public void testMainStarts() { assertNotNull("Activity nao foi criada!", getActivity()); }}

Page 23: Android: testes automatizados e TDD

Instrumentation in = getInstrumentation();

Ao trabalhar com eventos (click, touch, etc..) cuidado com atrasos da Thread de UI.

Page 24: Android: testes automatizados e TDD

• uiautomatorview (android_sdk/tools): detecta Views acessíveis pelo automator e "NAF" nodes.

• uiautomator:o http://developer.android.com/tools/help/uiautomator/

index.htmlo android:contentDescriptor:

ImageButton, ImageView, CheckBox.

o android:hint: EditText.

Testes de UI

Page 25: Android: testes automatizados e TDD

Que testes escrever?

Page 26: Android: testes automatizados e TDD

O que disse Kent Beck?

Page 27: Android: testes automatizados e TDD

I get paid for code that works, not for tests, so my philosophy is to test as little as possible to reach a given level of confidence (I suspect this level of confidence is high compared to industry standards, but that could just be hubris). If I don't typically make a kind of mistake (like setting the wrong variables in a constructor), I don't test for it. I do tend to make sense of test errors, so I'm extra careful when I have logic with complicated conditionals. When coding on a team, I modify my strategy to carefully test code that we, collectively, tend to get wrong.

Page 28: Android: testes automatizados e TDD

Different people will have different testing strategies based on this philosophy, but that seems reasonable to me given the immature state of understanding of how tests can best fit into the inner loop of coding. Ten or twenty years from now we'll likely have a more universal theory of which tests to write, which tests not to write, and how to tell the difference. In the meantime, experimentation seems in order.

Page 29: Android: testes automatizados e TDD

Android Facts

Page 30: Android: testes automatizados e TDD

• Receitas de bolo ("boilerplate code").

• Emulador é uma beleza. Só que não...

• Certas classes do framework são difíceis de mockar.

• Sistema externo pode complicar os testes.

• Asserções “visuais“ são díficeis de automatizar.

• Mesmo testes unitários demoram pra executar.

Android Facts

Page 31: Android: testes automatizados e TDD

• Você não precisa testar a API do Android.• Se necessário crie unidades testáveis fora dos

componentes Android e isole o boilerplate code.• Difícil de testar de forma automatizada: execução

assíncrona, layouts, dependência de sistema remoto, dependência de outras aplicações, boilerplate code, reação à "condições adversas", etc.

Então: que testes escrever?

Page 32: Android: testes automatizados e TDD

• Classes difíceis de mockar: crie um wrapper.

• Content Providers são fáceis de testar.• Testes funcionais automatizados podem ser

difíceis de manter.• Testes difíceis de escrever ou de manter

podem indicar um problema de design.• Instrumentação no lugar de testes de UI

automatizados.

Dicas

Page 33: Android: testes automatizados e TDD

• Testes de sanidade ajudam a evitar erros.Ex.: apenas iniciar uma Activity.

• É possível testar execução "assíncrona" de forma unitária, por ex.: https://android.googlesource.com/platform/frameworks/base/+/master/test-runner/src/android/test/LoaderTestCase.java

• Teste de Stress com Monkey:http://developer.android.com/tools/help/monkey.html

Dicas

Page 34: Android: testes automatizados e TDD

Exemplo: SincronizaçãoAuthenticator.javaAuthenticatorService.javaSyncAdapter.javaSyncService.javaauthenticator.xmlsyncadapter.xml

Page 35: Android: testes automatizados e TDD

public class SyncAdapter extends AbstractThreadedSyncAdapter{ ... @Override public void onPerformSync(...) {

}}

Código que faz a Sincronização

Page 36: Android: testes automatizados e TDD

public class SyncAdapter extends AbstractThreadedSyncAdapter{ ... @Override public void onPerformSync(...) {

}}

Código que faz a Sincronização

SyncAdapter é difícil de testar com testes

unitários!!

Page 37: Android: testes automatizados e TDD

public class SyncAdapter extends AbstractThreadedSyncAdapter{ ... @Override public void onPerformSync(...) {

}}

Page 38: Android: testes automatizados e TDD

public class SyncAdapter extends AbstractThreadedSyncAdapter{ ... @Override public void onPerformSync(...) {

}}

new QuestionSync(getContext()) .doSync();

Page 39: Android: testes automatizados e TDD

public class SyncAdapter extends AbstractThreadedSyncAdapter{ ... @Override public void onPerformSync(...) {

}}

new QuestionSync(getContext()) .doSync();

QuestionSync é uma classe Java comum. É mais fácil testá-la!!

Page 40: Android: testes automatizados e TDD

public class QuestionSyncTest extends ProviderTestCase2<DataProvider> { ... public void testReceiveOneQuestionWhenDataBaseIsEmpty() { Cursor c = mMockResolver.query(Question.CONTENT_URI, null, null, null, null); assertEquals(0, c.getCount()); String json = "[{\"id\":1, \"question\": \"nova pergunta\"}]"; getSyncForWebServicesReturn(json).doSync(); c = mMockResolver.query(Question.CONTENT_URI, null, null, null, null); assertEquals(1, c.getCount()); }}

Page 41: Android: testes automatizados e TDD

private QuestionSync getSyncForWebServicesReturn(final String wsReturn) {

final QuestionRemoteRepository mock = new QuestionRemoteRepository() { @Override protected String fetchAll() { return wsReturn; } }; return new QuestionSync(getMockContext()) { @Override public void doSync() { this.questionsRepository = mock; super.doSync(); } };}

Page 43: Android: testes automatizados e TDD

TDD

Page 44: Android: testes automatizados e TDD

while (true) { Adicione um novo teste. Faça o teste compilar. Execute o teste: vai falhar !! Implemente da forma mais simples possível para o teste passar. Refatore e mantenha os testes verdes. }

Page 45: Android: testes automatizados e TDD

TDD - Sugestão de Workflow• Execução dos testes é muito lenta para

TDD de fato.

• Crie unidades com TDD (ou algo parecido

com isso).

• Depois de alguma iterações adicione

componentes Android.

Page 46: Android: testes automatizados e TDD

Perguntas?

Page 47: Android: testes automatizados e TDD

Muito Obrigado!

Ivan de Aguirre@IvAguirre

[email protected]