2

I have been trying to run simple instrumented tests in Android Studio, without any success. I followed the guide for Unit Tests and it works fine. Now, I would like to tests components which are difficult to mock. When I follow the guide on instrumented tests, I end up with dependency errors.

What I did:

  • Install the Android Testing Support Library (Android Support Repository, rev 17).

  • Create a directory androidTest in src. Add Java folder + package ending with "test".

  • Add a simple Test class
 @RunWith(AndroidJUnit4.class)
    public class ServerRequestInstrumentationTest {
        @Test
        public void test(){
           LogC.d("Here we go testing !");
        }
    }
  • Add a simple TestSuit.
@RunWith(Suite.class)
@Suite.SuiteClasses({ServerRequestInstrumentationTest.class})
public class TestSuit {

    public TestSuit(){}
}
  • Modify my gradle file to add dependencies.
apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"

    defaultConfig {
        applicationId "com.mydomain.app"
        minSdkVersion 9
        targetSdkVersion 22
        versionCode 28
        versionName "2.0.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_7
            targetCompatibility JavaVersion.VERSION_1_7
        }

    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
            lintOptions {
                disable 'MissingTranslation'
            }
        }
    }
    sourceSets { main { java.srcDirs = ['src/main/java'] } }
}

dependencies {
    compile 'com.android.support:support-v4:22.2.0'
    compile 'com.android.support:appcompat-v7:22.2.0'
    wearApp project(':wear')
    compile project(':moreapps')
    compile project(':lib_repair')
    compile project(':bugreport')
    //testCompile 'junit:junit:4.12'
    testCompile 'org.mockito:mockito-core:1.10.19'
    androidTestCompile 'junit:junit:4.12'
    androidTestCompile 'org.hamcrest:hamcrest-library:1.1'
    androidTestCompile 'com.android.support.test:runner:0.3'
    androidTestCompile 'com.android.support.test:rules:0.3'
}

I just added the line androidTestCompile 'junit:junit:4.12', otherwise the annotation @RunWith(AndroidJUnit4.class) wasn't recognized. Now when I launch the test, I get one Gradle build error.

Error:Execution failed for task ':app:dexDebugAndroidTest'.

com.android.ide.common.process.ProcessException: org.gradle.process.internal.ExecException: Process 'command '/usr/lib/jvm/jdkoracle/bin/java'' finished with non-zero exit value 2

Any suggestion ? Did I miss something about the testing library ?

Thank you

Gordak
  • 2,060
  • 22
  • 32

4 Answers4

1

Okay, finally got it working.

After a little search, I found out that the Gradle console output an error :

AGPBI: {"kind":"simple","text":"UNEXPECTED TOP-LEVEL EXCEPTION:","sources":[{}]}
AGPBI: {"kind":"simple","text":"com.android.dex.DexException: Multiple dex files define Lorg/hamcrest/TypeSafeMatcher;","sources":[{}]}

After I changed one line in my gradle build, Gradle built the project successfuly and I was able to run the simple instrumented test.

Line to change:

androidTestCompile 'org.hamcrest:hamcrest-library:1.1'

to

testCompile 'org.hamcrest:hamcrest-library:1.1'

I don't know why Gradle complains in one case and not the other though...

Gordak
  • 2,060
  • 22
  • 32
0

Instrumentation tests are different to Unit Tests. You have to extend your test classes by specific classes. For more information about that take a look at Android Testing Fundamentals. Also you do not need JUnit for Instrumentaion tests.

Furthermore you have to switch your build variants from Unit Tests to Android Instrumentation Tests, as described here Unit testing in android studio

EXAMPLE:

Here an example for an instrumentaion test in android:

public class ExampleITest extends AndroidTestCase {

  @Override
  public void setUp() throws Exception {
    super.setUp();
    InputStream is = getContext().getAssets().open("test.xml");
    XmlParser parser = new XmlParser(getContext());
    parser.parse(is);
    ...
  }

  @MediumTest
  public void testSomething() throws Exception {      
    // test some data your parser extracted from the xml file
    ...
  }
}

As you can see, you can access context, etc. For this test no specific dependencies are necessary in the gradle file.

I haven't heard about Instrumantation tests just with annotions. maybe i should look it up on the web ;)

Community
  • 1
  • 1
Rich
  • 1,015
  • 1
  • 10
  • 22
  • Hi. Yep I set Test Artifact to "Android Instrumentation Tests". Actually, I'm not sure the Android Testing Fundamentals is up-to-date, as I can read "Note that the Android testing API supports JUnit 3 code style, but not JUnit 4.", although Android Testing seems to support JUnit 4. The updated testing framework seems to use annotations and not classes anymore. – Gordak Sep 02 '15 at 09:07
  • yeah, that might be a little bit out dated, but i think the basics are still the same. i updated my post with a small example. – Rich Sep 02 '15 at 09:40
  • I need help with writing an instrumentation test. I did set the Test Artifact as you wrote. My problem is that although running the test reports no errors, Android Studio does not find my test in the test class. I asked a question at http://stackoverflow.com/questions/35426990/no-error-still-android-studio-says-no-tests-were-found – Monica Feb 17 '16 at 00:29
0

Althought @Gordark's answer will not throw any error It's not a proper solution if you want to use Hamcrest in your instrumentation tests, it will work just for your local JVM tests.

I found that using 1.3 version of hamcrest-library actually worked, just replace

androidTestCompile 'org.hamcrest:hamcrest-library:1.1'

with

androidTestCompile 'org.hamcrest:hamcrest-library:1.3'

And it should work. I think it's something about conflicting versions of junit and hamcrest. I guess hamcrest 1.1 depends on a version of junit bellow 4.12, and hamcrest 1.3 depends on junit v4.12

Shyri
  • 400
  • 1
  • 6
  • 15
  • Note that the root of the problem is that one of the other dependencies requires hamcrest. Removing the explicit hamcrest dependency allows the correct version to be used automatically. – Code-Apprentice Feb 10 '16 at 02:37
0

Your answer contains a hint to the problem. You state there that Gradle gives an error. This is because one of the other dependencies for androidTestCompile depends on hamcrest. This is called a transitive dependency. It also means that you can completely remove your explicit requirement for hamcrest. Your change adds hamcrest as a dependency for testCompile which is used for unit tests run locally on your development machine rather than on an Android device or emulator. If you aren't making unit tests you don't need this. Even when you do start writing unit tests, you probably don't need an explicit dependency on hamcrest.

Community
  • 1
  • 1
Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268