Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Fixing Broken Robots - Android Mutation Testing
Search
Panini
July 18, 2019
Programming
220
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Fixing Broken Robots - Android Mutation Testing
Panini
July 18, 2019
More Decks by Panini
See All by Panini
Kotlin 1.5 preview
panini
1
490
Java谷園から逃げ出した話
panini
0
410
Kotlin 1.4-rc
panini
0
250
Kotlin Multiplatform
panini
2
720
build.gradle.kts
panini
2
2.5k
Kotlin Multi-platform(?)
panini
1
790
Convert Java file to Kotlin file ⌥⇧⌘K
panini
0
1.2k
Introducing Android P
panini
2
880
Display Cutout
panini
1
690
Other Decks in Programming
See All in Programming
App Intentsのビルドプロセスを支える技術
kntkymt
0
360
[DroidKaigi 2026] Bring your own phones to Gradle Managed Devices
f2lk
0
120
速く作れる。その次は、速く確かめられる開発へ 〜AIネイティブ開発を支える、Shift Down〜 / Can build fast. Next, moving to development where we can verify fast.
rkaga
2
590
Claude Codeを組織的に動かして月400PRを実現した話
happy_ryo
0
270
AIエージェント時代のコードレビューを設計する
nogu66
6
2.7k
iOSDC Japan 2026 - Swiftで作って学ぼう!データベース自作入門
kaseken
2
160
kubernetes コンポーネント開発入門 / 新卒N年目の勉強会&交流会!〜〇〇への誘い〜 #n_study
mazrean
0
230
Security issues being discussed on Web Platforms
petamoriken
0
910
Heart of Swift Concurrency
koher
0
610
AI × TiDD / 2026.09.05 Redmine 大阪
tokudiro
1
150
Go × SIMDで高速化するベクトル検索 ~ルーフラインモデルでSIMDが効く境界を探れ! ~
po3rin
1
640
型解析で実現する Go の言語内 DSL / Conference に Go! タイムテーブルの歩き方 for Gophers
mazrean
0
150
Featured
See All Featured
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.6k
It's Worth the Effort
3n
188
29k
Designing Dashboards & Data Visualisations in Web Apps
destraynor
232
55k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.8k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
Leveraging LLMs for student feedback in introductory data science courses - posit::conf(2025)
minecr
1
390
Discover your Explorer Soul
emna__ayadi
2
1.3k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
sira's awesome portfolio website redesign presentation
elsirapls
0
410
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
520
End of SEO as We Know It (SMX Advanced Version)
ipullrank
3
4.4k
Darren the Foodie - Storyboard
khoart
PRO
3
3.9k
Transcript
Fixing broken robots - Android Mutation Testing DroidConSG 2019 1/45
About me Matthew Vern Twitter Github Mercari, Inc Software Engineer
(Android) @panini_ja panpanini 2/45
Client Engineer Solving problems for our customers Shipping features Improve
existing functionality My job 3/45
A non-shipped feature doesn't provide benefit Ship features as quick
as possible My job 4/45
A shipped, broken feature doesn't provide benefit Ship quality features
as quick as possible My job 5/45
Maintaining quality 6/45
QA Maintaining quality 6/45
QA Code Review Maintaining quality 6/45
QA Code Review Tests Maintaining quality 6/45
How do we know our tests are providing quality Maintaining
quality 7/45
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
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
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
Who watches the watchmen? 8/45
How do we know that our tests are quality? Maintaining
quality 9/45
What are tests 10/45
asserting that our assumptions about a piece of code are
correct binary assertions of code correctness What are tests 11/45
Lets fail some tests 12/45
Unit tests assert code behaviour change code behaviour tests fail
???? profit Lets fail some tests 13/45
Mutation testing 14/45
proposed by Richard Lipton in 1971 computationally expensive, not a
viable testing solution until recently Mutation testing 15/45
1. Create a mutant 2. Run test suite 3. Confirm
if mutant was detected or not 4. Repeat Mutation testing steps 16/45
A mutant is a biological entity which has undergone a
change in its genetic structure. What is a mutant? 17/45
A mutant is a code block which has undergone a
change in its structure. What is a mutant? 18/45
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
Creating mutations fun setSessions(sessions: List<Session>) { this.sessions.clear() this.sessions.addAll(sessions) requestModelBuild() }
20/45
Creating mutations override fun buildModels() { generateModels(sessions) .forEach { it.addTo(this)
} } 21/45
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
Creating mutations 23/45
Competent Programmer Hypothesis Creating mutations 23/45
Competent Programmer Hypothesis Coupling Effect Creating mutations 23/45
Replaces relational operators with boundary counterpart Original Original Mutated Mutated
< <= <= < > >= >= > Conditionals boundary 24/45
Conditionals boundary original if (currentTime < startTime) { do something
} mutated if (currentTime startTime) { do something } 25/45
Negates conditional checks Original Original Mutated Mutated == != !=
== <= > > <= Negate Conditionals 26/45
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
removes void method calls Remove void calls 28/45
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
So what? 30/45
Code coverage, but better Why mutation testing 31/45
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
That's a lot of work you expect us to do
there bud 33/45
Pitest 34/45
mutation testing system mutants stored in memory outputs pretty reports
Gradle plugin Pitest pitest.org 35/45
apply plugin: pitest generates pitest<Variant> tasks Gradle plugin szpak/gradle-pitest-plugin 36/45
37/45
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
plugins { id("pl.droidsonroids.pitest") } pitest { excludeMockableAndroidJar = false targetClasses
= setOf("jp.co.panpanini.mypackage.*") outputFormats = setOf("XML", "HTML") } Android Gradle plugin 39/45
id("pl.droidsonroids.pitest") plugins { } pitest { excludeMockableAndroidJar = false targetClasses
= setOf("jp.co.panpanini.mypackage.*") outputFormats = setOf("XML", "HTML") } Android Gradle plugin 39/45
pitest { excludeMockableAndroidJar = false targetClasses = setOf("jp.co.panpanini.mypackage.*") outputFormats =
setOf("XML", "HTML") } plugins { id("pl.droidsonroids.pitest") } Android Gradle plugin 39/45
excludeMockableAndroidJar = false plugins { id("pl.droidsonroids.pitest") } pitest { targetClasses
= setOf("jp.co.panpanini.mypackage.*") outputFormats = setOf("XML", "HTML") } Android Gradle plugin 39/45
targetClasses = setOf("jp.co.panpanini.mypackage.*") plugins { id("pl.droidsonroids.pitest") } pitest { excludeMockableAndroidJar
= false outputFormats = setOf("XML", "HTML") } Android Gradle plugin 39/45
outputFormats = setOf("XML", "HTML") plugins { id("pl.droidsonroids.pitest") } pitest {
excludeMockableAndroidJar = false targetClasses = setOf("jp.co.panpanini.mypackage.*") } Android Gradle plugin 39/45
Demo 40/45
Pitest tips & tricks 41/45
MutationInterceptor Removes mutants for Kotlin generated code Pitest kotlin pitest/pitest-kotlin
42/45
Run PITest on Unit tests only 43/45
Run PITest on CI 44/45
Mutation Testing panpanini/mutation_testing Github: panpanini Twitter: panini_ja 45/45