Hazem Saleh's Blog
June 3, 2017
MVVM architecture, ViewModel and LiveData (Part 1)
During Google I/O, Google introduced architecture components which includes LiveData and ViewModel which facilitates developing Android app using MVVM pattern. This article discusses how can these components serve an android app that follows MVVM.
Read my full article:
https://medium.com/@hazems/mvvm-architecture-viewmodel-and-livedata-part-1-604f50cda1
April 8, 2017
Mockito 2.x over PowerMock Migration Tips and Tricks (Top Ten)
After so many years of hopeless waiting, Mockito 2.x is released to solve many problems that most of the android developers were having in their tests.
There are great features of Mockito 2.x which includes:
Finally mocking final classes and methods.
Support for Java 8.
Migration from CGLIB to ByteBuddy.
But if you are having today large tests written in Mockito 1.x, will it be an easy task to migrate?
Unfortunately, the migration most probably will be a painful task because Mockito 2.x does not respect the old behavior of Mockito 1.x. Adding to this complexity, If you are having PowerMock in your old tests, then you will have to face another dimension of complexity since most of PowerMock’s versions are having integration issues with Mockito 2.x.
Regarding PowerMock’s early issues with Mockito 2.x, PowerMock team announced that PowerMock 1.6.5 has an experimental support for Mockito 2.x but unfortunately it was not that great. It has some problems with Mockito 2.x.
In the beginning when just changing Mockito version to 2.x in your build.gradle file, you may find more than 50% of your tests were failing due to a lot of issues, Null pointer exceptions, compilation errors, No class definition found, un-expected thrown exception, …etc, and this is how you may look in the beginning of the migration.
Do not panic and do not be sad, this blog post mentions some of the important challenges that you may face during the migration and tips to overcome these challenges to save your time.
1. Use the proper PowerMock’s Mockito API extension
Using powermock-api-mockito extension does not work with Mockito 2.x, you will have the following exception when running your unit tests if you stick to the old extension:
java.lang.NoClassDefFoundError: org/mockito/cglib/proxy/MethodInterceptor
at org.powermock.api.mockito.internal.mockmaker.PowerMockMaker.(PowerMockMaker.java:43)
...
Caused by: java.lang.ClassNotFoundException: org.mockito.cglib.proxy.MethodInterceptor
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
... 40 more
In order to fix this issue, you should use the right Mockito’s API extension which is:
powermock-api-mockito2.
2. Avoid using Incompatible versions of Mockito and PowerMock
Always make sure to use compatible versions of Mockito and PowerMock, for example the following two versions are compatible:
PowerMock version 1.7.0 RC2.
Mockito version 2.1.0.
3. Say Goodbye to Mockito’s Whitebox
Mockito 2.x does not have Whitebox anymore.
So what is the solution then?
Initially, you can use PowerMock’s Whitebox instead of the removed Mockito’s 2.x Whitebox. However, you need to know that this does not come without problems, one of the problem which I reported to PowerMock’s issues is (org.powermock.reflect.exceptions.FieldNotFoundException: No instance field named XXX could be found in the class hierarchy):
https://github.com/powermock/powermock/issues/773
So if the initial solution does not work with you, why not writing your own one, it is not really hard.
4. Using the Right Matchers
Never forget to always use org.mockito.ArgumentMatchers instead of the old org.mockito.Matchers.
For example, replace the old matcher imports:
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyInt;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
With the following ones:
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
And so on with other matchers.
5. anyInt() does not match Long literals anymore
After the upgrade, you may find anyInt() does not work because it cannot match long literals such as 0L for example :).
So in order to fix this issue, just replace anyInt() with anyLong() and you will be fine.
OT note, if you can match with the actual value instead of anyXXX(), this can be much better and will give your test more transparency.
6. anyString() does not now match null anymore
This can fail many tests, anyString() now does not include null anymore in Mockito 2.x. This applies also to any(xxx), for example, any(InputStream.class) does not now match null in Mockito 2.x as well.
Again OT note, if you can match with the actual value instead of anyXXX(), this can be much better and will give your test more transparency.
7. Mockito 2.7.1 is not a real friend to PowerMock
Unfortunately, if you use PowerMock 1.6.5 or even PowerMock 1.7.0RC2 with Mockito 2.7.1 (the latest version at the time of writing this post), you will find the following exception with donothing:
java.lang.IllegalAccessError:
tried to access method
org.mockito.internal.stubbing.answers.DoesNothing.()V from
class org.powermock.api.mockito.PowerMockito
Fortunately, this issue is fixed with PowerMock 1.7.0RC4, and below is the fix issue URL for your information:
https://github.com/powermock/powermock/issues/753
So in summary if you use Mockito 2.7.1, do not forget to use PowerMock 1.7.0RC4.
8. Original test exceptions are wrapped as RuntimeExceptionProxy in Mockito 2.x with PowerMock
Unfortunately as a workaround, you have to modify all the broken @Test(expected=SomeException.class) to @Test(expected=Exception.class) since original exceptions are wrapped as Mockito RuntimeExceptionProxy in Mockito 2.x with PowerMock.
This issue really requires further investigation to know why Mockito 2.x does this wrapping with PowerMock. if you have a better solution for this, feel free to comment to the post.
9. Move away from PowerMock and depend on Mockito 2.x only
Try to create a plan to remove PowerMock by refactoring your app classes to be testable. Mockito 2.x is really enough now.
10. Review old tests
Take this migration as a chance to review the old tests and to improve them in order to have a better maintainable tests. This can help you strengthen your product code and allow easier refactoring for the current code base without surprises.
December 8, 2016
Android Mutation Testing – Back from AnDevCon SFO 2016
I just get back from AnDevCon that was be held from 29 November to 01 December @San Fransisco, USA. The conference organization was good and I had the chance to meet community Android folks.
In AnDevCon 2016, I had the chance to talk about “Mutation Testing for Android” in 01 December.
My session video is uploaded below.
My session slides is uploaded below.
[AnDevCon 2016] Mutation Testing for Android from Hazem Saleh
Back from AnDevCon SFO 2016
I just get back from AnDevCon that was be held from 29 November to 01 December @San Fransisco, USA. The conference organization was good and I had the chance to meet community Android folks.
In AnDevCon 2016, I had the chance to talk about “Mutation Testing for Android” in 01 December.
My session video is uploaded below.
My session slides is uploaded below.
[AnDevCon 2016] Mutation Testing for Android from Hazem Saleh
November 24, 2016
Speaking in AnDevCon SFO 2016
@Thursday, 01 December 2:15 pm – 3:30 pm, I will be speaking in AnDevCon SFO conference (that will be held from 29 November to 01 December @San Francisco, USA) about “Android Mutation Testing”. In my session, I will discuss unit testing frameworks in Android, traditional code coverage techniques and mutation testing using PIT. The session will be a practical one, it will have two demos:
http://www.andevcon.com/sf2016/speakers#HazemSaleh
At the end of the session, there is an award for the one who will solve a quiz.
I really wish to see all of you there in AnDevCon SFO 2016!
October 9, 2016
Some Thoughts about Android apps Stressful Testing
Mobile Apps Performance testing is one of the most important factors which can ensure that apps are really powerful and flexible enough to work on different set of devices. The importance of this topic appears clearly when there are a lot of vendors that produce many devices with many models and capabilities on the platform (which is the case for Android Platform). This article discusses important tips that should be followed for performing stressful Android app testing which are necessary before publishing apps to stores.
Android Monkey Tests
Monkey tests are special type of tests which test the app under certain stressful conditions such as touching screen so many times, they are very useful in detecting issues that does not follow happy path flow (most of the time).
Android monkey tests are really a powerful option for performing stressful testing for Android apps. It sends a pseudo-random stream of user events into the system, which acts as a stress test on the mobile app you are developing.
Using Monkey Tests
Using monkey tests is easy, you can launch the Monkey using a command line on your development machine or from a script. Because the Monkey runs in the emulator/device environment, you must launch it from a shell in that environment. You can do this by prefacing adb shell to each command, or by entering the shell and entering Monkey commands directly.
The following command runs Monkey tests in your app sending 500 pseudo-random events to it:
adb shell monkey -p your.package.name -v 500
More information about the command parameters can be found in:
https://developer.android.com/studio/test/monkey.html
Important Tips for having an efficient monkey test
1. Pin your App screen
Because a monkey test can send random events anywhere even outside the app. Your monkey tests can fail testing your app, so it is really recommended to pin app screen as follows (This procedure works for Android 5.0 Lollipop):
https://www.cnet.com/how-to/ho-to-pin-apps-in-android-5-lollipop/
2. Stress Complex Activities as much as you can
Sometimes, you may need to perform stress testing on specific activities of your app, this is very useful to identify problems as early as possible especially for complex activities.
In order to do this, you need to add the following intent-filter to your activity or activities:
Then from command line specify the category (-c) parameter as follows:
adb shell monkey -p your.package.name -c android.intent.category.LAUNCHER -c android.intent.category.MONKEY 5000
This will run monkey tests on LAUNCHER and MONKEY activities.
3. Have different levels of stress tests until reaching your app limits
Generally, it is recommended to start your monkey tests with small number of events and then increase them a bit by bit until you reach the app limits.
Also it is recommended to use the --throttle (which represents a fixed delay between events) to slow down the monkey.
4. Integrate your monkey tests with your CI
Ideally, monkey tests have to run for many hours on CI night jobs in order to detect app problems under stress as much as possible.
Monkey tests scripts can be easily integrated with CI using Execute shell task.
5. Perform monkey tests on real devices as much as you can
At the end, performing monkey tests on real devices as well as emulators are needed to detect the maximum number of issues as early as possible.
September 24, 2016
Dagger 2, MVP and Unit Testing (PIT Mutation Testing) ��� Part 4
The previous three articles[1] showed an introduction to Dagger, MVP pattern, Espresso and more. This article focuses on introducing a powerful test coverage technique for ensuring that the app unit tests are strong enough.
Introduction to Mutation Testing
One of the golden standard test coverage techniques is mutation testing. The main idea of mutation testing is to perform byte code modifications (mutations) to your original app source code and then run your app unit tests to check if they are strong enough to fail as a result of these mutations.
The byte code changes in Mutation Testing are named as faults (or mutations). After applying the source code changes, if your tests fail then the mutation is killed, and if your tests pass then the mutation is lived.
So in summary, If your tests fail by source code mutations then this means that your tests are really strong, if your tests pass then this means you need to modify your tests to make them strong enough (The quality of your tests can be gauged from the percentage of mutations killed).
Why we need Mutation Testing
Mutation tests have an advantage over Traditional test coverage (i.e line, statement, branch etc) because it does not only measure which code is executed by your tests but also it checks that your tests are actually able to detect faults in the executed code. This gives a strong measurement to your developed unit tests.
PIT
PIT is one of the mutation testing systems for Java. It has several advantages:
Fast to execute.
Integrated with Java build tools (Ant, Maven and Gradle).
Active.
More information about PIT can be found in:
http://pitest.org/
Android Integration
Unfortunately, the official PIT Gradle plugin does not work fine with Android Gradle projects:
https://github.com/szpak/gradle-pitest-plugin
However, thanks to one of the community member, this support is now possible using this fork:
https://github.com/koral–/gradle-pitest-plugin
Application Configuration
In order to configure Android PIT plugin with our Android Dagger app:
1. Add PIT plugin to your top-level build.gradle file:
classpath 'pl.droidsonroids.gradle:gradle-pitest-plugin:0.0.3'
2. Configure PIT plugin in your app build.gradle file:
pitest {
targetClasses = ['com.test.xyz.daggersample1.ui.presenter.*'] /* specify target classes to be mutated */
excludedClasses = ['**Factory*'] /* Exclude Dagger generated classes */
pitestVersion = "1.1.0"
threads = 4 /* specify number of threads */
outputFormats = ['XML', 'HTML'] /* specify output format */
}
Checking Results
After configuration, finally, we can execute PIT tests by running:
./gradlew pitest
You can pick the PIT tests report under build/reports/pitest.
The following figure shows the mutation testing report in our Dagger sample:
[image error]
The following figure shows survived and killed mutants:
[image error]
FYI, in the mutation report, Light green shows line coverage, dark green shows mutation coverage, Light pink show lack of line coverage, and dark pink shows lack of mutation coverage.
Source code
App Source code is available in:
https://github.com/hazems/Dagger-Sample/tree/pit1/app/src/test/java/com/test/xyz/daggersample1/ui/presenter
Top-level Gradle file PIT configuration:
https://github.com/hazems/Dagger-Sample/blob/pit1/build.gradle
Module-level Gradle file PIT configuration:
https://github.com/hazems/Dagger-Sample/blob/pit1/app/build.gradle
In our next article, let’s see how to kill these survived mutants which makes our tests not strong enough!
[1] Previous articles:
http://www.technicaladvices.com/2016/03/05/an-introduction-to-dagger-2-android-di-part-1/
http://www.technicaladvices.com/2016/03/09/an-introduction-to-dagger-2-android-di-part-2/
http://www.technicaladvices.com/2016/04/07/dagger-2-mvp-and-unit-testing-android-di-part-3/
Dagger 2, MVP and Unit Testing (PIT Mutation Testing) – Part 4
The previous three articles[1] showed an introduction to Dagger, MVP pattern, Espresso and more. This article focuses on introducing a powerful test coverage technique for ensuring that the app unit tests are strong enough.
Introduction to Mutation Testing
One of the golden standard test coverage techniques is mutation testing. The main idea of mutation testing is to perform byte code modifications (mutations) to your original app source code and then run your app unit tests to check if they are strong enough to fail as a result of these mutations.
The byte code changes in Mutation Testing are named as faults (or mutations). After applying the source code changes, if your tests fail then the mutation is killed, and if your tests pass then the mutation is lived.
So in summary, If your tests fail by source code mutations then this means that your tests are really strong, if your tests pass then this means you need to modify your tests to make them strong enough (The quality of your tests can be gauged from the percentage of mutations killed).
Why we need Mutation Testing
Mutation tests have an advantage over Traditional test coverage (i.e line, statement, branch etc) because it does not only measure which code is executed by your tests but also it checks that your tests are actually able to detect faults in the executed code. This gives a strong measurement to your developed unit tests.
PIT
PIT is one of the mutation testing systems for Java. It has several advantages:
Fast to execute.
Integrated with Java build tools (Ant, Maven and Gradle).
Active.
More information about PIT can be found in:
http://pitest.org/
Android Integration
Unfortunately, the official PIT Gradle plugin does not work fine with Android Gradle projects:
https://github.com/szpak/gradle-pitest-plugin
However, thanks to one of the community member, this support is now possible using this fork:
https://github.com/koral–/gradle-pitest-plugin
Application Configuration
In order to configure Android PIT plugin with our Android Dagger app:
1. Add PIT plugin to your top-level build.gradle file:
classpath 'pl.droidsonroids.gradle:gradle-pitest-plugin:0.0.3'
2. Configure PIT plugin in your app build.gradle file:
pitest {
targetClasses = ['com.test.xyz.daggersample1.ui.presenter.*'] /* specify target classes to be mutated */
pitestVersion = "1.1.0"
threads = 4 /* specify number of threads */
outputFormats = ['XML', 'HTML'] /* specify output format */
}
Checking Results
After configuration, finally, we can execute PIT tests by running:
./gradlew pitest
You can pick the PIT tests report under build/reports/pitest.
The following figure shows the mutation testing report in our Dagger sample:
The following figure shows survived and killed mutants:
FYI, in the mutation report, Light green shows line coverage, dark green shows mutation coverage, Light pink show lack of line coverage, and dark pink shows lack of mutation coverage.
Source code
App Source code is available in:
https://github.com/hazems/Dagger-Sample/tree/pit1
Top-level Gradle file PIT configuration:
https://github.com/hazems/Dagger-Sample/blob/pit1/build.gradle
Module-level Gradle file PIT configuration:
https://github.com/hazems/Dagger-Sample/blob/pit1/app/build.gradle
[1] Previous articles:
http://www.technicaladvices.com/2016/03/05/an-introduction-to-dagger-2-android-di-part-1/
http://www.technicaladvices.com/2016/03/09/an-introduction-to-dagger-2-android-di-part-2/
http://www.technicaladvices.com/2016/04/07/dagger-2-mvp-and-unit-testing-android-di-part-3/
September 3, 2016
Reverse Engineering Android app binaries (APK) for Legitimate Analysis
Finally, I have some chance to get back to blogging since I was very busy last month. Now, let’s go in the details in our today’s topic.
Sometimes, you may have a situation to reverse engineer your existing APKs for legitimate analysis reasons such as making queries on the app source (including used third party libraries) for getting more inside information.
This post shows you how to revere engineer an existing APK for the purpose of such good reasons (again for purpose of *good* reasons).
Detailed way / Using Mainly Three Tools
In order to reverse engineer an APK file from its source, you need to do the following:
Exploding APK
Extracting Java Classes
Decompiling Java Sources
Inspecting APK Content
Now, let’s go through them quickly.
Exploding APK
First of all, we need to explode the apk file to mainly the apk resources (assets, libraries, and manifest files).
In order to achieve this step, you need to download and use ApkTool which can be found in:
https://ibotpeaches.github.io/Apktool/
After downloading the jar, execute the library jar as follows.
java -jar apktool_2.2.0.jar decode --no-src myApk.apk
Note that if you do not specify the no-src parameter, then the Apk tool will decode sources and generate SMALI code (Not Java).
Extracting Java Classes
The second step is to convert the APK DEX file(s) into Java jar file(s). You will be find the DEX files whose names
are following classes(i).dex pattern under the exploded apk file directory (note that if your apk is multi-dex then beside the main classes.dex file, you can find classes2.dex, (and/or) classes3.dex … and so on).
In order to make this extraction, you can use a very good tool called (dex2jar) which can be found below:
https://sourceforge.net/projects/dex2jar/
Download the zip file and extract it, then run the dex2jar tool from command line as follows (assuming
that the dex2jar directory is directly located in the same level of the DEX file(s)).
sh d2j-dex2jar.sh ../myApk/classes.dex -o ../myApk/src.jar
Decompiling Java Sources
After having the jars, now we can simply decompile these jars into original Java sources. For this, we can use the command line Java Decompiler which is available in:
https://github.com/kwart/jd-cmd
For every jar we have, we can simply decompile it by running jd-cli as follows.
./jd-cli src.jar
Inspecting APK Content
Finally, we can inspect the APK content as much as we wish. For example, we can get all the strings in the content which are following a URL pattern by executing the following grep command on the exploded apk root folder.
grep -Eo '(http|https)://[^/"]+' -R .
This command will output the complete list of files whose contents are matching this grep regular expression.
Fast way / Using Jadx
Jadx is a powerful tool for directly converting an APK to its original sources, it can be found in:
https://github.com/skylot/jadx
So for our myApk.apk, all what we need to get its original source is to use Jadx tool as follows.
./jadx myApk.apk
Executing the previous command will do all the previous explained three steps for you.
Now, we are done, see you in the next post.
May 18, 2016
Back from ApacheCon North America 2016
I just get back from ApacheCon North America that was be held from 11 May to 13 May @Vancouver, Canada. The conference organization was really great and there were a lot of attendees in the conference sessions.
I had the chance to present “Advanced Apache Cordova” in 12 May, the session was interactive, contained three live demos and I was really amazed by the energy, enthusiasm, and responsiveness of the attendees during the session.
My session is uploaded below.
Finally, I would like to thank all the organizers of ApacheCon conference for making the conference looks so great.