Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Unit Testing Android Apps

felipecsl
August 23, 2014

Unit Testing Android Apps

felipecsl

August 23, 2014
Tweet

More Decks by felipecsl

Other Decks in Programming

Transcript

  1. Unit Testing
    Android Apps

    View Slide

  2. @felipecsl
    Unit Testing
    Android Apps

    View Slide

  3. View Slide

  4. 8MM+ downloads
    210k reviews
    4.5 ★ average rating

    View Slide

  5. Android app
    2 developers

    View Slide

  6. Android não foi desenhado
    com testabilidade em
    mente.

    View Slide

  7. View Slide

  8. 2. Técnicas
    3. Ferramentas
    1. Motivação

    View Slide

  9. 1. Motivação

    View Slide

  10. Você ainda não está
    convencido do valor de
    escrever testes
    automatizados.
    Premissa

    View Slide

  11. Tranquilidade:
    Consigo dormir à noite?

    View Slide

  12. Maintainability:
    Consigo alterar o código
    facilmente?

    View Slide

  13. O que causa
    Débito Técnico?
    The three sins of software development: http://blog.ionelmc.ro/2014/08/14/the-three-sins-of-software-development/

    View Slide

  14. Medo
    “Melhor não mexer nesse código…"

    View Slide

  15. Arrogância
    “Eu sei o que estou fazendo!”

    View Slide

  16. Estimativas irreais
    “Isso é barbada.”

    View Slide

  17. Não se trata de
    encontrar bugs

    View Slide

  18. TDD é um
    processo de design

    View Slide

  19. Código bem desenhado é
    facilmente testável

    View Slide

  20. S.O.L.I.D.

    View Slide

  21. http://www.agileapps.co.uk/methodology/continuous.html
    Red, Green, Refactor

    View Slide

  22. #isTDDdead
    http://martinfowler.com/articles/is-tdd-dead/
    http://david.heinemeierhansson.com/2014/tdd-is-dead-long-live-testing.html
    http://blog.8thlight.com/uncle-bob/2014/04/25/MonogamousTDD.html

    View Slide

  23. 2. Técnicas

    View Slide

  24. http://martinfowler.com/bliki/TestPyramid.html

    View Slide

  25. http://blog.stevensanderson.com/2009/08/24/writing-great-unit-tests-best-and-worst-practises/

    View Slide

  26. 3. Ferramentas

    View Slide

  27. Testes Unitários

    View Slide

  28. View Slide

  29. build.gradle
    http://gradleplease.appspot.com/
    Gradle, please

    View Slide

  30. build.gradle
    buildscript {
    repositories {
    mavenCentral()
    }
    dependencies {
    classpath 'org.robolectric:robolectric-gradle-plugin:0.12.0'
    }
    }
    apply plugin: 'robolectric'

    View Slide

  31. build.gradle
    android {
    defaultConfig {
    // optional
    testInstrumentationRunner "com.example.MyAppTestRunner"
    }
    robolectric {
    include '**/*Test.class'
    }
    // optional
    sourceSets {
    androidTest {
    setRoot('src/test')
    }
    }
    }

    View Slide

  32. build.gradle
    dependencies {
    compile 'com.android.support:appcompat-v7:20.0.0'
    // other dev dependencies...
    androidTestCompile 'junit:junit:4.10'
    androidTestCompile 'org.robolectric:robolectric:2.4-SNAPSHOT'
    androidTestCompile 'org.mockito:mockito-core:1.9.5'
    androidTestCompile 'org.hamcrest:hamcrest-library:1.3'
    }

    View Slide

  33. JUnit + Hamcrest
    @Config(emulateSdk = 18)
    @RunWith(MyTestRunner.class)
    public class UserTest {
    private User user;
    @Before
    public void setUp() {
    user = new User();
    user.setId(3);
    }
    @Test
    public void userShouldPersistFields() {
    assertFalse(user.isPublicAccount());
    assertThat(user.getId(), equalTo(3));
    }
    }

    View Slide

  34. Robolectric
    Shadow Objects

    View Slide

  35. Robolectric
    @RunWith(RobolectricTestRunner.class)
    @Test
    public void shouldHaveALogo() throws Exception {
    ImageView pivotalLogo = (ImageView) activity.findViewById(R.id.pivotal_logo);
    ShadowImageView shadowPivotalLogo = Robolectric.shadowOf(pivotalLogo);
    assertThat(shadowPivotalLogo.resourceId, equalTo(R.drawable.pivotallabs_logo));
    }

    View Slide

  36. Mockito
    @Before
    public void setUp() {
    HttpClient httpClient = mock(httpClient.class);
    ApiEndpoint endpoint = new ApiEndpoint(httpClient);
    }
    @Test
    public void userShouldPersistFields() {
    when(httpClient.get("/users/2")).thenReturn(new User());
    endpoint.getUser(2);
    verify(httpClient).get("/users/2");
    }

    View Slide

  37. http://www.confreaks.com/videos/659-rubyconf2011-why-you-don-t-get-mock-objects
    Assert on messages,
    not state.
    Mocks

    View Slide

  38. Rodando testes
    ./gradlew test

    View Slide

  39. Rodando uma classe de teste
    apenas
    ./gradlew test --tests \
    com.example.test.SomeClassTests

    View Slide

  40. Bonus points: AssertJ Android
    assertThat(view).isGone();
    assertThat(layout).isVisible()
    .isVertical()
    .hasChildCount(4)
    .hasShowDividers(SHOW_DIVIDERS_MIDDLE);
    https://github.com/square/assertj-android

    View Slide

  41. Testes Funcionais

    View Slide

  42. Ferramentas

    View Slide

  43. Feature: Rating a stand
    Scenario: Find and rate a stand from the list
    Given I am on the foodstand list
    Then I should see a "rating" button
    Then I should not see "Dixie Burger & Gumbo Soup"
    When I touch the "rating" button
    Then I should see "Dixie Burger & Gumbo Soup"
    When I touch "Dixie Burger & Gumbo Soup"
    Then I should see details for "Dixie Burger & Gumbo Soup"
    When I touch the "rate_it" button
    Then I should see the rating panel
    When I touch "star5"
    And I touch "rate"
    Then "Dixie Burger & Gumbo Soup" should be rated 5 stars

    View Slide

  44. Espresso
    Ferramentas

    View Slide

  45. Integração Contínua

    View Slide

  46. View Slide

  47. View Slide

  48. Test Cloud

    View Slide

  49. Obrigado!
    @felipecsl
    http://felipecsl.com

    View Slide