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

Fixing Broken Robots - Android Mutation Testing

Panini
July 18, 2019

Fixing Broken Robots - Android Mutation Testing

Panini

July 18, 2019
Tweet

More Decks by Panini

Other Decks in Programming

Transcript

  1. How do we know our tests are providing quality Use

    coverage to make sure that our tests are calling production code Maintaining quality 7/45
  2. How do we know our tests are providing quality Use

    coverage to make sure that our tests are calling production code changes introduced will not break existing code Maintaining quality 7/45
  3. How do we know our tests are providing quality Use

    coverage to make sure that our tests are calling production code changes introduced will not break existing code new code does what it says on the tin Maintaining quality 7/45
  4. asserting that our assumptions about a piece of code are

    correct binary assertions of code correctness What are tests 11/45
  5. proposed by Richard Lipton in 1971 computationally expensive, not a

    viable testing solution until recently Mutation testing 15/45
  6. 1. Create a mutant 2. Run test suite 3. Confirm

    if mutant was detected or not 4. Repeat Mutation testing steps 16/45
  7. A mutant is a biological entity which has undergone a

    change in its genetic structure. What is a mutant? 17/45
  8. A mutant is a code block which has undergone a

    change in its structure. What is a mutant? 18/45
  9. class SessionController( private val sessions: MutableList<Session> ) : EpoxyController() {

    fun setSessions(sessions: List<Session>) {} override fun buildModels() {} fun generateModels(sessions: List<Session>): List<SessionModel> {} } Creating mutations 19/45
  10. Creating mutations fun generateModels(sessions: List<Session>): List<SessionModel> { return sessions .map

    { session SessionModel_() .title(session.title) .imageUrl( if (session.speaker.profileImage "") { session.speaker.profileImage } else { null } ) } } 22/45
  11. Conditionals boundary original if (currentTime < startTime) { do something

    } mutated if (currentTime startTime) { do something } 25/45
  12. Negate Conditionals original fun buildModels() { SessionModel_() .title(session.title) .imageUrl( if

    (session.speaker.profileImage "") { session.speaker.profileImage } else { null } ) } mutated fun buildModels() { SessionModel_() .title(session.title) .imageUrl( if (session.speaker.profileImage "") { session.speaker.profileImage } else { null } ) } 27/45
  13. Remove void calls original fun setSessions(sessions: List<Session>) { this.sessions.clear() this.sessions.addAll(sessions)

    requestModelBuild() } mutated fun setSessions(sessions: List<Session>) { this.sessions.clear() this.sessions.addAll(sessions) } 29/45
  14. 1. Introduce a fault into production code 2. Use code

    coverage to determine which tests to run 3. Run tests 4. Confirm if fault was detected or not 5. Repeat Mutation testing The better way 32/45
  15. written by Karol Wrótniak, forked from szpak/gradle-pitest-plugin works with Android

    projects has some Android specific helpers (eg: generating mockable Android jar) Android Gradle plugin koral--/gradle-pitest-plugin 38/45
  16. plugins { id("pl.droidsonroids.pitest") } pitest { excludeMockableAndroidJar = false targetClasses

    = setOf("jp.co.panpanini.mypackage.*") outputFormats = setOf("XML", "HTML") } Android Gradle plugin 39/45
  17. id("pl.droidsonroids.pitest") plugins { } pitest { excludeMockableAndroidJar = false targetClasses

    = setOf("jp.co.panpanini.mypackage.*") outputFormats = setOf("XML", "HTML") } Android Gradle plugin 39/45
  18. pitest { excludeMockableAndroidJar = false targetClasses = setOf("jp.co.panpanini.mypackage.*") outputFormats =

    setOf("XML", "HTML") } plugins { id("pl.droidsonroids.pitest") } Android Gradle plugin 39/45
  19. excludeMockableAndroidJar = false plugins { id("pl.droidsonroids.pitest") } pitest { targetClasses

    = setOf("jp.co.panpanini.mypackage.*") outputFormats = setOf("XML", "HTML") } Android Gradle plugin 39/45
  20. outputFormats = setOf("XML", "HTML") plugins { id("pl.droidsonroids.pitest") } pitest {

    excludeMockableAndroidJar = false targetClasses = setOf("jp.co.panpanini.mypackage.*") } Android Gradle plugin 39/45