Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android instrumentation tests - "Unable to find instrumentation info for: ComponentInfo"

Tags:

I'm trying to run instrumentation tests on Android ( or Espresso tests for that matter ). The error that I'm getting both from Android Studio and console is:

Tests on Nexus_5X_API_23_2(AVD) - 6.0 failed: Unable to find instrumentation info for:



ComponentInfo{com.android.example.country1.demo.debug.test/android.support.test.runner.AndroidJUnitRunner}

com.android.builder.testing.ConnectedDevice > No tests found.[Nexus_5X_API_23_2(AVD) - 6.0] FAILED
No tests found. This usually means that your test classes are not in the form that your test runner expects (e.g. don't inherit from TestCase or lack @Test annotations).

Here is my build.gradle:

buildscript {
    repositories {
        jcenter()
    }

}

apply plugin: 'com.android.application'


android {
    signingConfigs {
        release
    }

    compileSdkVersion 23
    buildToolsVersion '24.0.0rc3'

    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }

    defaultConfig {
        versionName "1"
        versionCode 1
        minSdkVersion 14
        targetSdkVersion 23
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        testProguardFile 'proguard-test-rules.pro'
    }

    buildTypes {
        debug {
            debuggable true
            minifyEnabled true
            applicationIdSuffix ".debug"
            versionNameSuffix ".debug"
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules-debug.pro'
        }

        release {
           minifyEnabled true // this is a default setting
           useProguard true
           proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
           signingConfig signingConfigs.release
        }
    }

    flavorDimensions "version", "country"

    productFlavors {
        country1 {
            dimension "country1"
            applicationId "com.android.example.country1"
            proguardFile 'src/country1/proguard-country1.pro'
        }
        country2 {
            dimension "country2"
            applicationId "com.android.example.country2"
            proguardFile 'src/country2/proguard-country2.pro'
        }
        demo {
            dimension "version"
        }
        prod {
            dimension "version"
        }
    }

    applicationVariants.all { variant ->
        def flavorString = variant.getVariantData().getVariantConfiguration().getFlavorName()
        def mergedFlavour = variant.getVariantData().getVariantConfiguration().getMergedFlavor();

        if (flavorString.toLowerCase().contains("democountry1")) {
            mergedFlavour.setApplicationId("com.android.example.country1.demo")
            mergedFlavour.versionName = android.defaultConfig.versionName + ".country1.demo";
            ...
        }
        if (flavorString.toLowerCase().contains("prodcountry1")) {
            mergedFlavour.setApplicationId("com.android.example.country1")
            mergedFlavour.versionName = android.defaultConfig.versionName + ".country1";
            ...
        }
        if (flavorString.toLowerCase().contains("democountry2")) {
            mergedFlavour.setApplicationId("com.android.example.country2.demo")
            mergedFlavour.versionName = android.defaultConfig.versionName + ".country2.demo";
            ...
        }
        if (flavorString.toLowerCase().contains("prodcountry2")) {
            mergedFlavour.setApplicationId("com.android.example.country2")
            mergedFlavour.versionName = android.defaultConfig.versionName + ".country2";
            ...
        }
    }

    dexOptions {
        incremental true
        preDexLibraries false
        javaMaxHeapSize "4G"
    }
}


def props = new Properties()
if (rootProject.file("release.properties").exists()) {
    props.load(new FileInputStream(rootProject.file("release.properties")))
    android.signingConfigs.release.storeFile rootProject.file(props.keyStore)
    android.signingConfigs.release.storePassword props.storePassword
    android.signingConfigs.release.keyAlias props.keyAlias
    android.signingConfigs.release.keyPassword props.keyPassword
} else {
    android.signingConfigs.release.storePassword = 'storePassword'
    android.signingConfigs.release.keyAlias = 'keyAlias'
    android.signingConfigs.release.keyPassword = 'keyPassword'
}


dependencies {
    compile 'com.android.support:appcompat-v7:23.3.0'
    compile 'com.android.support:support-v4:23.3.0'
    compile 'com.squareup.okhttp3:okhttp:3.2.0'
    compile 'com.squareup.okhttp3:logging-interceptor:3.2.0'
    compile 'com.squareup.retrofit2:retrofit:2.0.2'
    compile 'com.squareup.retrofit2:converter-jackson:2.0.2'
    ...

    testCompile 'junit:junit:4.12'
    androidTestCompile 'com.android.support.test.espresso:espresso-core:2.2.2'
    androidTestCompile 'com.squareup.retrofit2:retrofit-mock:2.0.2'
    androidTestCompile 'com.android.support.test:runner:0.5'
    androidTestCompile 'com.android.support.test:rules:0.5'
    androidTestCompile 'com.squareup.spoon:spoon-client:1.5.1'
    //Version resolutins
    androidTestCompile 'com.google.code.findbugs:jsr305:3.0.0'
    androidTestCompile 'com.android.support:support-annotations:23.3.0'
}

Note: I know there are a lot of similar questions but after a couple of days of searching and trying solutions I have not found something that works for me.

UPDATE :

Instrumentation test case:

public class RegulatorRestApiAdapterTest extends InstrumentationTestCase {

private MockRetrofit mockRetrofit;
private Retrofit retrofit;

@Override
public void setUp() throws Exception {
    retrofit = new Retrofit.Builder().baseUrl("http://test.com")
            .client(new OkHttpClient())
            .addConverterFactory(JacksonConverterFactory.create())
            .build();

    NetworkBehavior behavior = NetworkBehavior.create();

    mockRetrofit = new MockRetrofit.Builder(retrofit)
            .networkBehavior(behavior)
            .build();
}


@SmallTest
public void testEcho() throws Exception {
    BehaviorDelegate<BackendRestApi> delegate = mockRetrofit.create(BackendRestApi.class);
    RegulatorRestApi mockBackendRestApi = new MockBackendRestApi(delegate);

    Echo echo = new Echo();
    echo.setEchoRequest("EchoString");

    //Actual Test
    Call<Echo> call = mockBackendRestApi .echo(echo);
    Response<Echo> echoResponse = call.execute();

    //Asserting response
    Assert.assertTrue(echoResponse.isSuccessful());
    Assert.assertEquals("EchoString", echoResponse.body().getEchoResponse());
}
}

Espresso test:

@RunWith(AndroidJUnit4.class)
@LargeTest
public class EspressoTest {

    @Rule
    public ActivityTestRule<LoginActivity> mActivityRule =
            new ActivityTestRule<>(LoginActivity.class);

    @Test
    public void findViewPerformActionAndCheckAssertion() {
        // Find Button and Click on it
        onView(withId(R.id.numpad_ok)).perform(click());

        // Find TextView and verify the correct text that is displayed
        onView(withId(R.id.text_view_rocks)).check(matches(withText(
           mActivityRule.getActivity().getString(R.string.android_testing_rocks))));
    }
}

Both tests fail with the same error and code of neither reaches execution. I'm using Android version 6 and successfully execute Instrumentation and Espresso test examples from the Internet on the same emulator.

like image 234
JFreeman Avatar asked May 01 '16 20:05

JFreeman


1 Answers

I managed to finally resolve it. It might be useful to someone else so I'm posting here.

The way that I was setting application ID was interfering with test application. Although in Android Studio it looked like it was installing application with correct package name when I checked on the device itself the test application ID was lacking ".demo" from "version" flavor dimension.

I made use of the newly introduced ( for flavors )

applicationIdSuffix = ".demo"

Source : http://android-developers.blogspot.bg/2015/12/leveraging-product-flavors-in-android.html

Here is the modified section of my build.gradle:

defaultConfig {
    applicationId "com.example"
    versionName "1"
    versionCode 1
    minSdkVersion 14
    targetSdkVersion 23
    testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    testProguardFile 'proguard-test-rules.pro'
}

buildTypes {
    debug {
        debuggable true
        minifyEnabled true
        applicationIdSuffix ".debug"
        versionNameSuffix ".debug"
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules-debug.pro'
    }

    release {
       minifyEnabled true // this is a default setting
       useProguard true
       proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
       signingConfig signingConfigs.release
    }
}

flavorDimensions "country", "version"

productFlavors {
    country1 {
        dimension "country1"
        applicationIdSuffix = ".country1"
        proguardFile 'src/country1/proguard-country1.pro'
    }
    country2 {
        dimension "country2"
        applicationIdSuffix = ".country2"
        proguardFile 'src/country2/proguard-country2.pro'
    }
    demo {
        dimension "version"
        applicationIdSuffix = ".demo"
    }
    prod {
        dimension "version"
    }
}

So far I don't think

versionNameSuffix

is usable with flavors so the code below remains.

applicationVariants.all { variant ->
    def flavorString = variant.getVariantData().getVariantConfiguration().getFlavorName()
    def mergedFlavour = variant.getVariantData().getVariantConfiguration().getMergedFlavor();

    if (flavorString.toLowerCase().contains("country1demo")) {
        mergedFlavour.versionName = android.defaultConfig.versionName + ".country1.demo";
        ...
    }
    if (flavorString.toLowerCase().contains("country1prod")) {
        mergedFlavour.versionName = android.defaultConfig.versionName + ".country1";
        ...
    }
    if (flavorString.toLowerCase().contains("country2demo")) {
        mergedFlavour.versionName = android.defaultConfig.versionName + ".country2.demo";
        ...
    }
    if (flavorString.toLowerCase().contains("country2prod")) {
        mergedFlavour.versionName = android.defaultConfig.versionName + ".country2";
        ...
    }
}
like image 170
JFreeman Avatar answered Sep 28 '22 04:09

JFreeman