Enabling Mutant Generation for Open- and Closed-Source Android Apps
This project was created by the Software Engineering Maintenance and Evolution Research Unit (SEMERU) at the College of William & Mary, in collaboration with The Software Design Lab at the Universidad de los Andes, The University of Sannio, REVEAL at the The University of Lugano, and the Miami University, Oxford, OH. The major goal of the project is to help mobile application developers and testers improve the quality of their test suites. This project empirically derived a set of 38 Android-specific mutation operators which can be automatically seeded into a target application and analyzed on a set of test cases.
Tools
Major Wrapper
Pitest Wrapper
Fault Taxonomy
The black rectangle in the bottom-right part of Figure 1 reports the number of documents tagged as false positive or as un- clear. e other rectangles—marked with the Android and/or with the Java logo—represent the 14 high-level categories that we identified. Categories marked with the Android logo (e.g., Activities and Intents) group together Android-specific bugs while those marked with the Java logo (e.g., Collections and Strings) group bugs that could affect any Java application. Both symbols together indicate categories featuring both Android-specific and Java-related bugs (see e.g., I/O).
Mutant Operators
These operators were implemented in Java (for source code-based mutations in MDroid+) and SMALI (for APK-based mutations in MutAPK). The locations for the mutations are identified by using a Potential Failure Profile (PFP). The PFP lists code locations that could be modified to inject a mutation. The locations of the analyzed apps which can be source code statements, XML tags or locations in other resource files that can be the source of a potential fault, given the faults catalog from the taxonomy.

- Available in MDroid+

- Available in MutAPK
- AST
- Changes are done directly over AST
- Text
- Changes are done over resource files
Text
Description:
Delete an activity < android:name="Activity" /> entry in the Manifest file
How to find a mutant of this kind:
Provide a sequence of events that visits the removed activity
AST
Description:
Replace the Activity.class argument in an Intent instantiation
How to find a mutant of this kind:
Provide a sequence of events that exercises the modified intent
Text
Description:
Randomly insert typos in the path of an activity defined in the Manifest file
How to find a mutant of this kind:
Provide a sequence of events that visits the modified activity
AST
Description:
Randomly generate a different key in an Intent.putExtra(key, value) call
How to find a mutant of this kind:
Provide a sequence of events that exercises the modified intent
Text
Description:
Replace the attribute "android:label" in the Manifest file with a random string
How to find a mutant of this kind:
Provide a sequence of events that visits the modified activity and checks for the activity name
AST
Description:
Replace an Intent instantiation with null
How to find a mutant of this kind:
Provide a sequence of events that exercises the modified intent
AST
Description:
Replace the value argument in an Intent.putExtra(key, value) call with new Parcelable[0]
How to find a mutant of this kind:
Provide a sequence of events that exercises the modified intent
Text
Description:
Randomly replace the main activity definition with a different activity
How to find a mutant of this kind:
Check at app start for content expected to appear on launching
AST
Description:
Replace a BluetoothAdapter.isEnabled() call with "true"
How to find a mutant of this kind:
Call the method that has the bluetooth status validation while the adapter is turned off
AST
Description:
Replace a BluetoothAdapter instance with null
How to find a mutant of this kind:
Exercise the method where the mutation was performed
AST
Description:
Assign null to a listener
How to find a mutant of this kind:
Provide a sequence of events that exercise the GUI component related to the modified "onClickListener"
AST
Description:
Assign a variable (returned by Activity.findViewById) to null
How to find a mutant of this kind:
Execute a sequence of test steps that covers the branch where the nulled variable is used
Text
Description:
Randomly change colors in layout files
How to find a mutant of this kind:
Perform visual regression over GUI for a sequence of events that visits the activity where the modified color is used
AST
Description:
Replace the id argument in an Activitity.findViewById call
How to find a mutant of this kind:
Execute a sequence of test steps that covers the branch where the modified variable value is used
AST
Description:
Randomly focus a GUI component
How to find a mutant of this kind:
TODOs
AST
Description:
Set visible attribute (from a View) to false
How to find a mutant of this kind:
Define a set of steps thar visits the activity where the component should appear, and then check existence of component
AST
Description:
Assign a cursor to null before it is closed
How to find a mutant of this kind:
Call the method where the modification was done, check for correct handling of error
AST
Description:
Randomly modify indexes/order of query parameters
How to find a mutant of this kind:
Call the modified method and checks the correct handling of the error or empty result
AST
Description:
Randomly mutate a SQL query
How to find a mutant of this kind:
Call the modified method, checks for correct handling of error
AST
Description:
Set a random Date to a date object
How to find a mutant of this kind:
Check integrity of data related to the modified date
Description:
Randomly mutate a method call argument of a basic type
How to find a mutant of this kind:
Call the modified method, check the correct handling of the error
AST
Description:
Select a serializable class, remove "implements Serializable"
How to find a mutant of this kind:
Identify an element from the modified class, and try to exercise its serialization
AST
Description:
Set null to a method call argument
How to find a mutant of this kind:
Call the modified method and check for correct handling of the error
AST
Description:
Randomly mutate paths to files
How to find a mutant of this kind:
Call for modified file usage and exercise it. Check for correct handling of the error
AST
Description:
Assign an input stream to null before it is closed
How to find a mutant of this kind:
Call the modified method, checks for the correct handling of the error
AST
Description:
Assign an output stream to null before it is closed
How to find a mutant of this kind:
Call the modified method, checks for the correct handling of the error
AST
Description:
If URIs are used internally, randomly mutate the URIs
How to find a mutant of this kind:
Call for modified URI usage and exercise it. Check for correct handling of the error
AST
Description:
Inject large delay right-after a call to a back-end service. Current implementation add 10 second delay since a 5 second delay produces an ANR
How to find a mutant of this kind:
Check for correct handling of ARN
AST
Description:
Insert a long delay (\ie Thread.sleep(..)) in the creation GUI thread. Current implementation add 10 second delay since a 5 second delay produces an ANR
How to find a mutant of this kind:
Check for correct handling of ARN
AST
Description:
Insert a long delay (\ie Thread.sleep(..)) in a GUI Listener
How to find a mutant of this kind:
Check for correct handling of ARN
AST
Description:
Increase the time-out of connections to back-end services
How to find a mutant of this kind:
Check for correct handling of ARN
AST
Description:
Increase the size of bitmaps by explicitly setting large dimensions. Current implementation modifies dimension into a size no device could fit
How to find a mutant of this kind:
Check for correct handling of oversized image
Text
Description:
Select and remove an <uses-permission /> entry in the Manifest file
How to find a mutant of this kind:
Define a sequence of events that exercise the usage of the removed permission
AST
Description:
Select a parcelable class, remove "implements Parcelable" and the @override annotations
How to find a mutant of this kind:
Identify an element from the modified class, and try to use it inside a intend as parameter
AST
Description:
Inject a Null GPS location in the location services
How to find a mutant of this kind:
Exercise the usage of the modified location variable
Text
Description:
Randomly mutate the integer values in the SdkVersion-related attributes
How to find a mutant of this kind:
Executes the app in a not-previously supported OS version
Text
Description:
Select a <string /> entry in /res/values/strings.xml file and mutate the string value
How to find a mutant of this kind:
Identify a sequence of step that reach the activity where modified string is used and check for the expected value
AST
Description:
Assign null to a response variable from a back-end service
How to find a mutant of this kind:
Check for correct error handling
Empirical Study
Apps used in Studies
| App Name | Category | Package Name | Version | ESEC/FSE'17 | TSE'20 |
|---|---|---|---|---|---|
| A2DP Volume | Transportation | a2dp.Vol | 2.8.11 | ✔ | ✔ |
| AardDictionary | Books & Reference | aarddict.android | 1.4.1 | ✔ | ✔ |
| FTP Server | Tools | be.ppareit.swiftp_free | 2.2 | ✔ | ✔ |
| Bites | Lifestyle | caldwell.ben.bites | 1.3 | ✔ | ✔ |
| Battery Circle | Tools | ch.blinkenlights.battery | 1.81 | ✔ | ✔ |
| KeePassDroid | Tools | com.android.keepass | 1.9.8 | ✔ | ✔ |
| LolcatBuilder | Entertainment | com.android.lolcat | 2 | ✔ | ✔ |
| SpriteMethodTest | Sample | com.android.spritemethodtest | 1 | ✔ | ✔ |
| Alarm Clock | Tools | com.angrydoughnuts.android.alarmclock | 1.7 | ✔ | ✔ |
| Translate | Tools | com.beust.android.translate | 1.6 | ✔ | ✔ |
| Manpages | Productivity | com.chmod0.manpages | 1.51 | ✔ | ✔ |
| BookCatalogue | Productivity | com.eleybourn.bookcatalogue | 3.8 | ✔ | ✔ |
| Mileage | Finance | com.evancharlton.mileage | 3.1.1 | ✔ | ✔ |
| Auto Answer | Tools | com.everysoft.autoanswer | 1.5 | ✔ | ✔ |
| Amazed | Casual | com.example.amazed | 2.0.2 | ✔ | ✔ |
| RandomMusicPlayer | Music | com.example.android.musicplayer | 1 | ✔ | ✔ |
| AnyCut | Productivity | com.example.anycut | 0.5 | ✔ | ✔ |
| HNDroid | News & Magazines | com.gluegadget.hndroid | 0.2.1 | ✔ | ✔ |
| SpriteText | Sample | com.google.android.opengles.spritetext | - | ✔ | ✔ |
| Triangle | Sample | com.google.android.opengles.triangle | - | ✔ | ✔ |
| Photostream | Media & Video | com.google.android.photostream | 1.1 | ✔ | ✔ |
| Multi SMS | Communication | com.hectorone.multismssender | 2.3 | ✔ | ✔ |
| World Clock | Tools | com.irahul.worldclock | 0.6 | ✔ | ✔ |
| SyncMyPix | Media & Video | com.nloko.android.syncmypix | 0.15 | ✔ | ✔ |
| Jamendo | Music | com.teleca.jamendo | 1.0.6-legacy | ✔ | ✔ |
| Yahtzee | Casual | com.tum.yahtzee | 1 | ✔ | ✔ |
| Sanity | Communication | cri.sanity | 2.11 | ✔ | ✔ |
| Mirrored | News & Magazines | de.homac.Mirrored | 0.2.3 | ✔ | ✔ |
| FileExplorer | Productivity | edu.killerud.fileexplorer | 1 | ✔ | ✔ |
| WeightChart | Health & Fitness | es.senselesssolutions.gpl.weightchart | 1.0.4 | ✔ | ✔ |
| SoundBoard | Sample | hiof.enigma.android.soundboard | 1 | ✔ | ✔ |
| ADSdroid | Books & Reference | hu.vsza.adsdroid | 1.2 | ✔ | ✔ |
| myLock | Tools | i4nc4mp.myLock | 42 | ✔ | ✔ |
| LockPatternGenerator | Tools | in.shick.lockpatterngenerator | 2 | ✔ | ✔ |
| MunchLife | Entertainment | info.bpace.munchlife | 1.4.2 | ✔ | ✔ |
| aGrep | Tools | jp.sblo.pandora.aGrep | 0.2.1 | ✔ | ✔ |
| CountdownTimer | Tools | net.everythingandroid.timer | 1.1.0 | ✔ | ✔ |
| LearnMusicNotes | Puzzle | net.fercanet.LNM | 1.2 | ✔ | ✔ |
| NetCounter | Tools | net.jaqpot.netcounter | 0.14.1 | ✔ | ✔ |
| TippyTipper | Finance | net.mandaria.tippytipper | 1.1.3 | ✔ | ✔ |
| BaterryDog | Tools | net.sf.andbatdog.batterydog | 0.1.1 | ✔ | ✔ |
| Bomber | Casual | org.beide.bomber | 1 | ✔ | ✔ |
| Dialer2 | Productivity | org.dnaq.dialer2 | 2.9 | ✔ | ✔ |
| FrozenBubble | Puzzle | org.jfedor.frozenbubble | 1.12 | ✔ | ✔ |
| aLogCat | Tools | org.jtb.alogcat | 2.6.1 | ✔ | ✔ |
| AnyMemo_135 | Education | org.liberty.android.fantastischmemo | 8.3.1 | ✔ | ✔ |
| PasswordMakerPro | Tools | org.passwordmaker.android | 1.1.7 | ✔ | ✔ |
| Blokish | Puzzle | org.scoutant.blokish | 2 | ✔ | ✔ |
| ZooBorns | Entertainment | org.smerty.zooborns | 1.4.4 | ✔ | ✔ |
| Wordpress_394 | Productivity | org.tomdroid | 0.5.0 | ✔ | ✔ |
| MyExpenses | Finance | org.totschnig.myexpenses | 1.6.0 | ✔ | ✔ |
| ImportContacts | Tools | org.waxworlds.edam.importcontacts | 1.1 | ✔ | ✔ |
| Wikipedia | Books & Reference | org.wikipedia | 1.2.1 | ✔ | ✔ |
Operators Across Tools
Enabling Mutant Generation for Open- and Closed-Source Android Apps - TSE 2020
RQ1. Are the mutation operators (available for Java and Android apps) representative of real bugs in Android apps?
MDroid+ and MutAPK outperformed the other six mutation tools by achieving the highest coverage both in terms of bug types and bug instances. However, the results shows that Android- specific mutation operators should be combined with classic operators to generate mutants that are representative of real faults in mobile apps.

Bug Types not Covered by Taxonomy
- Audio codec problem
- Content provider (bulk update)
- Improper implementation of Sensors as Activity
- Improper location for invoking db insertions
- Improper usage of static in Android
- Issue with JNI
- Issues with visibility (modifier)
- Memory leaks
- NegativeArraySizeException
- Performance (large amount of data to insert in content provider)
- Recycled bitmap
- Text encoding error
- Type error
- Unreachable code
- Usage of relative layout as the root container
- Video encoding
RQ2. What is the rate of non-compilable (e.g., those leading to failed compilations), trivial (e.g., those leading to crashes on app launch), equivalent, and redundant mutants produced by the studied tools when used with Android apps?
First figure depicts the achieved results as percentage of Stillborn Mutants, the second figure presents the percentage of Trivial Mutants generated by each tool on each app. Third figure shows that on average, 67, 207, 1.3k+, 904, 2.6k+, and 1.5k+ mutants were generated by MDroid+, MutAPK-Shared, MutAPK, Major, PIT, and muDroid, respectively for each app. The larger number of mutants generated by PIT is due in part to the larger number of mutation operators available for the tool.



As for the generation of mutants, all the analyzed tools (Major, Pit, muDroid, MDroid+, MutAPK) generated a relatively low rate of trivial mutants, with muDroid being the worst with a 11.8% average rate of trivial mutants. Additionally, no equivalent mutants were found for any tool,according to a hash-based comparison between the original APKs and the corresponding mutants. Nevertheless, 4 tools (MutAPK, MutAPK-Shared, PIT and muDroid) generated redundant mutants, with muDroid being the worst with a 6.55% of total redundant mutants.
RQ3. What are the major causes for non-compilable, trivial, equivalent, and redundant mutants produced by the mutation testing tools when applied to Android apps?
The performed analysis indicate that the PIT tool outperforms others in terms of ratio between non-compilable and generated mutants, because it does not generate any non-compilable mutant. However,MDroid+ and MutAPK provide Android-specific mutations, which make the tools (i.e.,Pit, MDroid+, MutAPK) complementary for mutation testing of Android apps. MDroid+ and MutAPK generated the lowest rate of both non-compilable and trivial mutants (when compared to Major and muDroid), illustrating its immediate applicability to Android apps. Major and muDroid generate non-compilable mutants, with the latter having a critical average rate of 58.7% non-compilable mutants per app. Also, even when PIT generates redundant mutants, the number is insignificant when compared to the number of mutants generated; at the same time MutAPK and MutAPK-Shared also generate a low number of redundant mutants; some of them can be fixed by improving the current implementation.
RQ4. What are the benefits and trade-offs of performing mutation testing at APK level vs source code level?
The clear benefit of performing APK-level mutation analysis (MutAPK) as opposed to source code-level mutation analysis (MDroid+) relates primarily to the ease of use of the system, as it only requires a single file (i.e., an APKfile instead of several source files), and generates mutants with higher compilability ratio in less time. Moreover, this makes the mutation tool applicable to apps written with various languages, i.e., Java, Kotlin, and Dart. However, this ease of use comes with as light trade-off in terms of generating a higher number of mutants (which leads to an extensive execution effort from developers), and a higher number of trivial and redundant mutants for certain operators that are likely to be discarded during mutant analysis.
Enabling Mutation Testing for Android Apps - ESEC/FSE 2017
RQ1. Are the mutation operators (available for Java and Android apps) representative of real bugs in Android apps?
MDroid+ outperformed the other six mutation tools by achieving the highest coverage both in terms of bug types and bug instances. However, the results shows that Android- specific mutation operators should be combined with classic operators to generate mutants that are representative of real faults in mobile apps.

Bug Types not Covered by Taxonomy
- Audio codec problem
- Content provider (bulk update)
- Improper implementation of Sensors as Activity
- Improper location for invoking db insertions
- Improper usage of static in Android
- Issue with JNI
- Issues with visibility (modifier)
- Memory leaks
- NegativeArraySizeException
- Performance (large amount of data to insert in content provider)
- Recycled bitmap
- Text encoding error
- Type error
- Unreachable code
- Usage of relative layout as the root container
- Video encoding
RQ2. What is the rate of stillborn mutants (e.g., those leading to failed compilations) and trivial mutants (e.g., those leading to crashes on app launch) produced by the studied tools when used with Android apps?
First figure depicts the achieved results as percentage of Stillborn Mutants, the second figure presents the percentage of Trivial Mutants generated by each tool on each app. Third figure shows that on average, 167, 904, 2.6k+, and 1.5k+ mutants were generated by MDroid+, Major, PIT, and muDroid, respectively for each app. The larger number of mutants generated by PIT is due in part to the larger number of mutation operators available for the tool.



MDroid+ generated the smallest rate of both stillborn and trivial mutants illustrating its immediate applicability to Android apps. Major and muDroid generate stillborn mutants, with the latter having a critical average rate of 58.7% stillborn mutants per app.
RQ3. What is the rate of stillborn mutants (e.g., those leading to failed compilations) and trivial mutants (e.g., those leading to crashes on app launch) produced by the studied tools when used with Android apps?
All four tools generated a relatively low rate of trivial mutants, with muDroid again being the worst with an 11.8% average rate of trivial mutants. Our analysis shows that the PIT tool is most applicable to Android apps when evaluated in terms of the ratio between failed and generated mutants. However, MDroid+ is both practical and based on Android-specific operations implemented according to an empirically derived fault-taxonomy of Android apps.
ESEC/FSE 2017 - Study Data
Please click the button below to obtain a copy of the data generated for each Mutation framework relating to RQ2 & RQ3 outlined above.
Publications
- MutAPK: Source-Codeless Mutant Generation for Android Apps (Tool Demo), Camilo Escobar-Velásquez, Michael Osorio-Riaño, and Mario Linares-Vásquez, The 34th IEEE/ACM International Conference on Automated Software Engineering (ASE'19), Demonstrations Track, San Diego, CA, USA, November 11th - 15th, 2019, to appear 4 pages (53.7% Acceptance Rate) [pdf][bibtex]
- MDroid+: A Mutation Testing Framework for Android (Tool Demo), Kevin Moran, Michele Tufano, Carlos Bernal-Cárdenas, Mario Linares-Vásquez, Gabriele Bavota, Christopher Vendome, Massimiliano DiPenta, and Denys Poshyvanyk, The 40th IEEE/ACM International Conference on Software Engineering (ICSE'18), Formal Research Demonstrations Track, Gothenburg, Sweden, May 27-June 3, 2018, pp. 33-36 (35% Acceptance Rate) [pdf][bibtex]
- Enabling Mutation Testing for Android Apps (Research Paper), Mario Linares-Vásquez, Gabriele Bavota, Michele Tufano, Kevin Moran, Massimiliano DiPenta, Christopher Vendome, Carlos Bernal-Cárdenas and Denys Poshyvanyk, The 11th Joint Meeting of the European Software Engineering Conference and the 25th ACM SIGSOFT Symposium on the Foundations of Software Engineering (ESEC/FSE'17), Paderborn, Germany, September 4-8, 2017, pp. 233-244 (24.4% Acceptance Rate) [pdf][bibtex]