<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Pranay Airan</title>
    <description>The latest articles on DEV Community by Pranay Airan (@pranayairan).</description>
    <link>https://dev.to/pranayairan</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F9823%2F907a8755-21e8-427d-9dd3-453805787476.jpg</url>
      <title>DEV Community: Pranay Airan</title>
      <link>https://dev.to/pranayairan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pranayairan"/>
    <language>en</language>
    <item>
      <title>Parallel Unit Tests in Android</title>
      <dc:creator>Pranay Airan</dc:creator>
      <pubDate>Wed, 02 Oct 2019 18:13:29 +0000</pubDate>
      <link>https://dev.to/pranayairan/parallel-unit-tests-in-android-4oe5</link>
      <guid>https://dev.to/pranayairan/parallel-unit-tests-in-android-4oe5</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;**TL;DR&lt;/em&gt;* Our unit tests were taking a lot of time to run and there was no way to shard them and run in parallel. We found a way to use &lt;strong&gt;JUnit Categories&lt;/strong&gt; and custom gradle command to shard our tests and reduce test execution time by half.*&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Unit tests are the fundamental tests in our app testing strategy. But the more tests we write, the more time it takes to execute them and for a code to merge. &lt;/p&gt;

&lt;p&gt;Android apps have various layers and we can test each layer using different tools. But we can categorize these tests into 3 buckets. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Unit Test (fast, runs on JVM)&lt;/li&gt;
&lt;li&gt;UI test (slow, runs using an emulator)&lt;/li&gt;
&lt;li&gt;Robolectric test (moderate, runs on JVM with simulated android env)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;JVM tests usually run super fast but on android, all unit test runs &lt;strong&gt;Sequentially&lt;/strong&gt;, the more tests we write, the longer it will take to execute them. &lt;/p&gt;

&lt;p&gt;With project &lt;a href="https://medium.com/androiddevelopers/write-once-run-everywhere-tests-on-android-88adb2ba20c5"&gt;Nitrogen&lt;/a&gt;, Robolectric tests are now supported in the Android X testing library. Robolectric tests run on JVM and are faster then espresso tests. But since they depend on simulated android env they are slower than vanilla JUnit tests.&lt;/p&gt;

&lt;p&gt;Combining Robolectric and JUnit tests makes test execution slow and can impact build time and developer productivity. Gradle has support for executing tests in parallel using a custom setting like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Test&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;maxParallelForks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;runtime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;availableProcessors&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;But this option is rigid and can cause a crash in our build machine.&lt;/p&gt;

&lt;p&gt;Modern CI systems come with support for parallel builds. To get most out of our CI, we need a way to &lt;strong&gt;Shard&lt;/strong&gt; our tests and execute them in parallel. For ex: we can divide our unit tests into 2 parts (&lt;strong&gt;Robolectric and pure JVM&lt;/strong&gt;) and run them in parallel cutting test execution time in half. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Sharding&lt;/strong&gt; is splitting the test suite into multiple threads, so they run as a group. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Unfortunately Android and Gradle don't have an easy way to shard or break tests. In this post, we will discuss 2 different approaches we can use to achieve this. &lt;/p&gt;

&lt;h2&gt;
  
  
  Command line
&lt;/h2&gt;

&lt;p&gt;Command-line parameters are the most simple option available with &lt;strong&gt;gradle&lt;/strong&gt;, when it comes to executing 1 test, all tests in a class or a package. &lt;/p&gt;

&lt;p&gt;Let's take an example test class&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="nn"&gt;com.dexterapps.testsharding&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ConverterUtilTest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;testConvertFahrenheitToCelsius&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;actual&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ConverterUtil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;convertCelsiusToFahrenheit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100F&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;expected&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;212f&lt;/span&gt;

        &lt;span class="nf"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Conversion from celsius to fahrenheit failed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDouble&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDouble&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="m"&gt;0.001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nd"&gt;@Test&lt;/span&gt;
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;testConvertCelsiusToFahrenheit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// test code here&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Executing Single Test
&lt;/h3&gt;

&lt;p&gt;We can execute single test like &lt;strong&gt;testConvertFahrenheitToCelsius&lt;/strong&gt;  with this command&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt; ./gradlew :ProjectName:testVariantNameUnitTest &lt;span class="nt"&gt;--tests&lt;/span&gt; com.dexterapps.testsharding.ConverterUtilTest.testConvertFahrenheitToCelsius
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Relpace &lt;code&gt;:ProjectName:testVariantNameUnitTest&lt;/code&gt; with yours. Like  &lt;code&gt;:app:testDebugUnitTest&lt;/code&gt; or the variant you will like to test. &lt;/p&gt;

&lt;h3&gt;
  
  
  Executing all tests in class
&lt;/h3&gt;

&lt;p&gt;To run all tests in a class &lt;strong&gt;ConverterUtilTest&lt;/strong&gt; we can run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;./gradlew :ProjectName:testVariantNameUnitTest &lt;span class="nt"&gt;--tests&lt;/span&gt; com.dexterapps.testsharding.ConverterUtilTest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Executing all tests in a package
&lt;/h3&gt;

&lt;p&gt;To run all tests in a package &lt;strong&gt;com.dexterapps.testsharding&lt;/strong&gt; we can&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;./gradlew :ProjectName:testVariantNameUnitTest &lt;span class="nt"&gt;--tests&lt;/span&gt; com.dexterapps.testsharding.&lt;span class="k"&gt;*&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Command line options work for a lot of cases but as a downside, each engineer would need to set up there own Android Studio run config or shell script. &lt;/p&gt;

&lt;p&gt;This approach doesn't &lt;strong&gt;Shard&lt;/strong&gt; the tests. Let's say if we want to separate &lt;strong&gt;Robolectric&lt;/strong&gt; and &lt;strong&gt;JVM&lt;/strong&gt; tests, we need to use specific packages, forcing everyone to put tests in diff package from where they belong canonically. &lt;/p&gt;

&lt;p&gt;Can we do better? Yes, we can, Let's look at another approach that gives us the flexibility we need. &lt;/p&gt;

&lt;h2&gt;
  
  
  JUnit Categories
&lt;/h2&gt;

&lt;p&gt;JUnit 4.12 introduced a nifty feature &lt;strong&gt;Categories&lt;/strong&gt;. Categories provide us with a mechanism to label and group tests and run these tests either by including or excluding the categories. &lt;/p&gt;

&lt;p&gt;JUnit categories are simple but there is no direct support for it in Gradle or Gradle Android. We need to write a custom Gradle code to make it work. Let's look at the code. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You can download all the code discussed in this post from&lt;br&gt;
&lt;a href="https://github.com/pranayairan/android-unit-test-sharding"&gt;https://github.com/pranayairan/android-unit-test-sharding&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Marker Interface
&lt;/h3&gt;

&lt;p&gt;To represent the categories or label tests, we need to create marker interfaces. This simple interfaces will be will use to classify our tests and run them in parallel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;RobolectricTests&lt;/span&gt;

&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;UnitTests&lt;/span&gt;

&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;FastTests&lt;/span&gt;

&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;SlowTests&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: JUnit categories can take any class name as a category, it is&lt;br&gt;
not required to create custom interfaces. We can use any predefine&lt;br&gt;
classes as well to categorize tests.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Category Example
&lt;/h3&gt;

&lt;p&gt;Once we have marker interfaces, it is trivial to add them as categories. To categorize a test annotate it with &lt;code&gt;@Category&lt;/code&gt; annotation and add interface name. Let's look at some code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt; &lt;span class="nd"&gt;@Test&lt;/span&gt;
 &lt;span class="nd"&gt;@Category&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;UnitTests&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;testConvertFahrenheitToCelsius&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;actual&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ConverterUtil&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;convertCelsiusToFahrenheit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100F&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
     &lt;span class="kd"&gt;val&lt;/span&gt; &lt;span class="py"&gt;expected&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;212f&lt;/span&gt;

     &lt;span class="nf"&gt;assertEquals&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Conversion from celsius to fahrenheit failed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="n"&gt;expected&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDouble&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;actual&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDouble&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="m"&gt;0.001&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can add many categories to single method or add categories at class level.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight kotlin"&gt;&lt;code&gt; &lt;span class="nd"&gt;@Category&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;FastTests&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
 &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ConverterUtilTest&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nd"&gt;@Test&lt;/span&gt;  
    &lt;span class="nd"&gt;@Category&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;FastTests&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nc"&gt;UnitTests&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  
    &lt;span class="k"&gt;fun&lt;/span&gt; &lt;span class="nf"&gt;testConvertCelsiusToFahrenheit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;@Category&lt;/code&gt; annotation is part of JUnit experiemental package&lt;br&gt;
&lt;code&gt;org.junit.experimental.categories.Category&lt;/code&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Running the category tests
&lt;/h3&gt;

&lt;p&gt;There is no easy way to run category tests on Android. We can add support for Categories in the Android gradle plugin by writing custom gradle code.&lt;/p&gt;

&lt;p&gt;Let's look at the code to execute tests with category &lt;code&gt;robolectric&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight groovy"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;gradle&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;startParameter&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;taskRequests&lt;/span&gt;&lt;span class="o"&gt;?.&lt;/span&gt;&lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;]?.&lt;/span&gt;&lt;span class="na"&gt;remove&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"--robolectric"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Project&lt;/span&gt; &lt;span class="n"&gt;project&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;subprojects&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;project&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;tasks&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;withType&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Test&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;configureEach&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;useJUnit&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
                        &lt;span class="n"&gt;includeCategories&lt;/span&gt; &lt;span class="s1"&gt;'com.dexterapps.testsharding.RobolectricTests'&lt;/span&gt;
                        &lt;span class="c1"&gt;//excludeCategories if we want to exclude any test&lt;/span&gt;
                    &lt;span class="o"&gt;}&lt;/span&gt;
                &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We need to add this code to root &lt;code&gt;build.gradle&lt;/code&gt; file to make it work for &lt;code&gt;all&lt;/code&gt; modules. We can also enable it for specific module. To enable for specific module check &lt;a href="https://github.com/pranayairan/android-unit-test-sharding/blob/master/build.gradle#L72"&gt;this code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's walk through this code line by line. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;First, we check if a gradle command is executed with the &lt;code&gt;--robolectric&lt;/code&gt; parameter. If yes we remove the parameter and proceed. We need to call remove because &lt;code&gt;--robolectric&lt;/code&gt; is a custom parameter and gradle doesn't understand it. &lt;/li&gt;
&lt;li&gt;If we find this parameter we will instruct JUnit to &lt;em&gt;include&lt;/em&gt; all tests with Category  &lt;code&gt;com.dexterapps.testsharding.RobolectricTests&lt;/code&gt; and ignore other tests. We can also use &lt;code&gt;excludeCategories&lt;/code&gt; to do the reverse. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To run Unit tests with &lt;code&gt;@Category(RobolectricTests::class)&lt;/code&gt; using following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;./gradlew :app:testDebugUnitTest &lt;span class="nt"&gt;--robolectric&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Similarly we can run other &lt;em&gt;category tests&lt;/em&gt; with&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;./gradlew :app:testDebugUnitTest &lt;span class="nt"&gt;--unit&lt;/span&gt;
or
./gradlew :app:testDebugUnitTest &lt;span class="nt"&gt;--fasttest&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Results
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;JUnit Categories&lt;/strong&gt; enabled us to divide and run multiple test jobs in parallel. Before &lt;code&gt;Categories&lt;/code&gt; our test execution time was &lt;strong&gt;5 min&lt;/strong&gt;. With &lt;code&gt;Categories&lt;/code&gt; and parallel jobs, it takes only &lt;strong&gt;3 min&lt;/strong&gt; (Unit Test 2 min, Robolectric 3 min) giving us &lt;strong&gt;~40%&lt;/strong&gt; savings in test execution time. &lt;/p&gt;

&lt;h3&gt;
  
  
  Wrap up
&lt;/h3&gt;

&lt;p&gt;The concept of test &lt;strong&gt;sharding&lt;/strong&gt; is not new in android. UI testing frameworks like &lt;a href="https://square.github.io/spoon/"&gt;Spoon&lt;/a&gt; or &lt;a href="https://github.com/TestArmada/flank"&gt;Flank&lt;/a&gt; supported it for a long time. But sharding for a unit testing is non-existing. &lt;/p&gt;

&lt;p&gt;This post covered the use of  &lt;strong&gt;JUnit Categories&lt;/strong&gt; and custom gradle code to break unit tests into different categories and run them in parallel. We achieved &lt;strong&gt;~40%&lt;/strong&gt; improvement in test execution time and improved developer productivity. &lt;/p&gt;

&lt;p&gt;I created a sample android app that shard unit tests into 3 different categories. You can find the complete source code at &lt;strong&gt;&lt;a href="https://github.com/pranayairan/android-unit-test-sharding"&gt;https://github.com/pranayairan/android-unit-test-sharding&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I would like to give shot out to my Colleague &lt;a href="https://github.com/martofeld"&gt;Martin Feldsztejn&lt;/a&gt; who wrote the custom gradle command to get categories to work in android. I would also like to thanks &lt;a href="https://github.com/sriramsantosh"&gt;Sriram Santosh&lt;/a&gt; for proofreading this and providing his feedback&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Post originally published on  &lt;a href="https://prandroid.dev/Parallel-unit-tests-in-android/"&gt;https://prandroid.dev/Parallel-unit-tests-in-android/&lt;/a&gt; &lt;/p&gt;

</description>
      <category>testing</category>
      <category>android</category>
      <category>robolectric</category>
      <category>testsharding</category>
    </item>
  </channel>
</rss>
