How to run unit tests with Android Studio

64,191

Solution 1

Update for AS 1.1+, android gradle plugin 1.1+

Finally it is possible without many tricks. Here is example of project that shows how to setup Robolectric test in Android Studio v1.1+ and android gradle plugin v1.1+: https://github.com/nenick/AndroidStudioAndRobolectric

You can find also there possible issue and workarounds. Yes, Robolectric is complex and not officially supported by Google so it still has some issues. But most of the time it works and brings huge value to your project.

I would also encourage you to start using Robolectric v3+. It is almost released and stable enough.

Old answer for AS 0.x and 1.0x and android gradle plugin version below 1.1

I managed to make it with help of friends.

So basically you need to make next changes to run Robolectric unit tests in Android Studio:

  1. Copy your classpath for test (you can find it as first line in "Run" log)
  2. Open run configuration for your unit tests
  3. Change working dir to folder where AndroidManifest.xml is present
  4. Add VM Option -classpath "<path_to_project_folder>/build/test-classes:<path_to_gradle_cache>/caches/modules-2/files-2.1/junit/junit/4.11/4e031bb61df09069aeb2bffb4019e7a5034a4ee0/junit-4.11.jar:<your old classpath>"

As for me the start of new classpath looks like this:

/Users/emartynov/Development/Projects/work/android.project/build/test-classes:/Users/emartynov/.gradle/caches/modules-2/files-2.1/junit/junit/4.11/4e031bb61df09069aeb2bffb4019e7a5034a4ee0/junit-4.11.jar

Problems:

  1. You can run test only for debug variant
  2. Every new test run configuration requires such manual changes. But this is simply copy/paste of two edit fields

I have Android Studio 0.6 version. Here is again part of my build.gradle file:

buildscript {
  repositories {
    mavenCentral()
    maven { url 'https://github.com/rockerhieu/mvn-repo/raw/master/' }
  }

  dependencies {
    classpath 'com.android.tools.build:gradle:0.11.+'
    classpath 'com.neenbedankt.gradle.plugins:android-apt:1.3'
  //  classpath 'org.robolectric.gradle:gradle-android-test-plugin:0.10.1'
    classpath 'org.robolectric.gradle:gradle-android-test-plugin:0.10.1-SNAPSHOT'
    classpath 'com.jakewharton.sdkmanager:gradle-plugin:0.10.+'
  }
}

apply plugin: 'android-sdk-manager'
apply plugin: 'android'
apply plugin: 'android-apt'
apply plugin: 'android-test'

repositories {
  mavenCentral()
}

android {
  compileSdkVersion 19
  buildToolsVersion "19.1.0"

  packagingOptions {
    exclude 'META-INF/NOTICE'
    exclude 'META-INF/NOTICE.txt'
    exclude 'META-INF/notice.txt'
    exclude 'META-INF/LICENSE'
    exclude 'META-INF/LICENSE.txt'
    exclude 'META-INF/license.txt'
    exclude 'META-INF/ASL2.0'
    exclude 'LICENSE.txt'
  }

  defaultConfig {
    minSdkVersion 14
    targetSdkVersion 19
    versionCode 1
    versionName "0.9.0"
  }

  compileOptions {
    sourceCompatibility JavaVersion.VERSION_1_7
    targetCompatibility JavaVersion.VERSION_1_7
  }

  sourceSets {
    androidTest.setRoot( 'src/test' )
  }
}

dependencies {
  // butter knife
  compile 'com.jakewharton:butterknife:5.0.0'
  // dagger
  compile 'com.squareup.dagger:dagger:1.2.1'

  // apt
  apt 'com.squareup.dagger:dagger-compiler:1.+'

  // AS tests
  androidTestCompile 'junit:junit:4.+'
  androidTestCompile( 'org.robolectric:robolectric:2.3' ) {
    exclude group: 'commons-logging'
    exclude group: 'org.apache.httpcomponents'
  }
  androidTestCompile 'com.squareup:fest-android:1.+'
  androidTestCompile 'org.mockito:mockito-all:1.9.+'
  androidTestCompile 'org.easytesting:fest-assert-core:2.0M10'
  androidTestCompile( 'org.skyscreamer:jsonassert:1.2.+' ) {
    exclude group: 'org.json'
  }

  // tests
  testCompile 'junit:junit:4.+'
  testCompile( 'org.robolectric:robolectric:2.3' ) {
    exclude group: 'commons-logging'
    exclude group: 'org.apache.httpcomponents'
  }
  testCompile 'com.squareup:fest-android:1.+'
  testCompile 'org.mockito:mockito-all:1.9.+'
  testCompile 'org.easytesting:fest-assert-core:2.0M10'
  testCompile 'com.squareup.dagger:dagger-compiler:1.+'
  testCompile( 'org.skyscreamer:jsonassert:1.2.+' ) {
    exclude group: 'org.json'
  }
}

Solution 2

just add folder named instrumentTest under /src it should have /java inside like this

enter image description here

then extend the class ActivityTestCase (or any other android unit-test-class), such as

package com.example.app.test;

import android.test.ActivityTestCase;

import junit.framework.Assert;


public class MainActivityTest extends ActivityTestCase {


public void testHappy(){
    Assert.assertTrue(true);
}

} 

right click on green java directory and select run all tests and you should get this:

enter image description here

good luck

Solution 3

I ran into this problem and found a solution - include the classes.jar from the exploded bundle (.aar) in the build folder. I don't think will help with finding resources in .aar dependencies though.

testCompile fileTree(dir: "$project.buildDir/exploded-bundles", include: "**/classes.jar")

Edit: Since Android Gradle build tools 0.9.0 the dependency has changed to:

androidTestCompile fileTree(dir: "$project.buildDir/exploded-aar", include: "**/classes.jar")

Edit 2: Since Android Gradle build tools 0.10.0 the dependency has changed to:

androidTestCompile fileTree(dir: "$project.buildDir/../../build/exploded-aar", include: "**/classes.jar")

Note: the relative path may be different depending on your project structure.

Share:
64,191
Eugen Martynov
Author by

Eugen Martynov

My biggest challenge is bringing up mobile development to desktop/server side quality and processes level I'm interested in extending my knowledge and skills in writing clean, readable, maintainable code, as well as progress in quick continuous quality automated software releases I'm in love with Scrum, and I'm looking to extended relationship with Kanban Specialties: Android, iOS, BlackBeryy, J2ME, Java Mobile application development, unit testing, design patterns, continuous integration, automated testing, build management

Updated on October 14, 2020

Comments

  • Eugen Martynov
    Eugen Martynov over 3 years

    I'm using Jake's Android unit tests plugin for gradle: https://github.com/JakeWharton/gradle-android-test-plugin

    My build.gradle looks like this:

    dependencies {
    // analytics
    compile('com.crittercism:crittercism-android:3.0.11')
    
    // retrofit
    compile('com.squareup.retrofit:retrofit:1.2.2')
    compile('com.squareup.okhttp:okhttp:1.2.1')
    
    // dagger
    compile('com.squareup.dagger:dagger:1.1.0')
    compile('com.squareup.dagger:dagger-compiler:1.1.0')
    
    // compatibility
    compile('android.compatibility:android-support:v4-r13')
    compile('com.actionbarsherlock:actionbarsherlock:4.4.0@aar')
    
    // Picasso
    compile('com.squareup.picasso:picasso:2.1.1')
    
    // Otto
    compile('com.squareup:otto:1.3.4')
    
    // Tests
    testCompile 'junit:junit:4.10'
    testCompile 'org.robolectric:robolectric:2.2'
    testCompile 'org.powermock:powermock-api-mockito:1.5.1'
    testCompile 'org.easytesting:fest-assert-core:2.0M10'
    }
    

    Unfortunately I'm not able to run all or specific unit test form Android Studio. I'm getting error:

    Exception in thread "main" java.lang.NoClassDefFoundError: junit/textui/ResultPrinter
     at java.lang.Class.forName0(Native Method)
     at java.lang.Class.forName(Class.java:171)
     at com.intellij.rt.execution.application.AppMain.main(AppMain.java:113)
    Caused by: java.lang.ClassNotFoundException: junit.textui.ResultPrinter
     at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
     at java.security.AccessController.doPrivileged(Native Method)
     at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
     at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
     at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
     at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
     ... 3 more
    

    And this is correct because running command line doesn't include my JUnit dependency:

    /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/bin/java -ea -Didea.launcher.port=7533 "-Didea.launcher.bin.path=/Applications/Android Studio.app/bin" -Dfile.encoding=UTF-8 -classpath "/Applications/Android Studio.app/lib/idea_rt.jar:/Applications/Android Studio.app/plugins/junit/lib/junit-rt.jar:/Users/eugen/Development/SDK/android-sdk-macosx/platforms/android-18/android.jar:/Users/eugen/Development/SDK/android-sdk-macosx/platforms/android-18/data/res:/Users/eugen/Development/SDK/android-sdk-macosx/tools/support/annotations.jar:/Users/eugen/Development/Projects/eBuddy/xms/android/xms3-android/build/classes/alpha/debug:/Users/eugen/.gradle/caches/artifacts-26/filestore/com.squareup.retrofit/retrofit/1.2.2/jar/cdf7b60568092fbcc7a254371c345e92f733c03c/retrofit-1.2.2.jar:/Users/eugen/.gradle/caches/artifacts-26/filestore/com.google.code.gson/gson/2.2.4/jar/a60a5e993c98c864010053cb901b7eab25306568/gson-2.2.4.jar:/Users/eugen/.gradle/caches/artifacts-26/filestore/com.squareup.okhttp/okhttp/1.2.1/jar/c3562574496bb4d452d6fc45b817577e98d08afe/okhttp-1.2.1.jar:/Users/eugen/.gradle/caches/artifacts-26/filestore/com.squareup/javawriter/2.1.1/jar/67ff45d9ae02e583d0f9b3432a5ebbe05c30c966/javawriter-2.1.1.jar:/Users/eugen/.gradle/caches/artifacts-26/filestore/com.squareup.dagger/dagger/1.1.0/jar/49f2061c938987c8e56679a731d74fd8448d8742/dagger-1.1.0.jar:/Users/eugen/.gradle/caches/artifacts-26/filestore/com.squareup.picasso/picasso/2.1.1/jar/ab19bfb23f641f189b6dca9a4d393f8dc291103a/picasso-2.1.1.jar:/Users/eugen/.gradle/caches/artifacts-26/filestore/com.squareup/otto/1.3.4/jar/4d72fb811c7b3c0e7f412112020d4430f044e510/otto-1.3.4.jar:/Users/eugen/.gradle/caches/artifacts-26/filestore/com.squareup.dagger/dagger-compiler/1.1.0/jar/ddb38c2be31deeb7a001177f7c358665e350d646/dagger-compiler-1.1.0.jar:/Users/eugen/.gradle/caches/artifacts-26/filestore/javax.inject/javax.inject/1/jar/6975da39a7040257bd51d21a231b76c915872d38/javax.inject-1.jar:/Users/eugen/Development/Projects/eBuddy/xms/android/xms3-android/build/exploded-bundles/ComActionbarsherlockActionbarsherlock440.aar/res:/Users/eugen/Development/Projects/eBuddy/xms/android/xms3-android/build/exploded-bundles/ComActionbarsherlockActionbarsherlock440.aar/classes.jar:/Users/eugen/.gradle/caches/artifacts-26/filestore/com.squareup.okhttp/okhttp-protocols/1.2.1/jar/ec2beaefef3bd4f680c17fad8e72e66f2a006f1/okhttp-protocols-1.2.1.jar:/Users/eugen/.gradle/caches/artifacts-26/filestore/com.crittercism/crittercism-android/3.0.11/jar/e30c21ae491d780622ecaee2752969be98140c3/crittercism-android-3.0.11.jar:/Users/eugen/.gradle/caches/artifacts-26/filestore/android.compatibility/android-support/v4-r13/jar/bd6479f5dd592790607e0504e66e0f31c2b4d308/android-support-v4-r13.jar" com.intellij.rt.execution.application.AppMain com.intellij.rt.execution.junit.JUnitStarter -ideVersion5 @/private/var/folders/wq/knhztnf105v2_p1t580tj8h80000gp/T/idea_junit701450667388095664.tmp @w@/private/var/folders/wq/knhztnf105v2_p1t580tj8h80000gp/T/idea_working_dirs_junit4927192380605663413.tmp -socket63849
    

    I wonder if anyone was able to run unit tests in Android Studio? And if it is possible how make it?