Android 仪器测试 - "Unable to find instrumentation info for: ComponentInfo"
Android instrumentation tests - "Unable to find instrumentation info for: ComponentInfo"
我正在尝试 运行 在 Android 上进行仪器测试(或 Espresso 测试)。我从 Android Studio 和控制台得到的错误是:
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).
这是我的 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'
}
注意:我知道有很多类似的问题,但经过几天的搜索和尝试解决方案后,我还没有找到适合我的东西。
更新:
仪器测试用例:
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());
}
}
浓缩咖啡测试:
@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))));
}
}
两个测试都因相同的错误而失败,并且都没有执行代码。我正在使用 Android 版本 6,并在同一模拟器上成功地执行了来自 Internet 的 Instrumentation 和 Espresso 测试示例。
我终于解决了。它可能对其他人有用,所以我在这里发帖。
我设置应用程序 ID 的方式干扰了测试应用程序。虽然在 Android Studio 中,当我检查设备本身时,它看起来像是在安装具有正确包名称的应用程序,但测试应用程序 ID 缺少来自 "version" 风格维度的“.demo”。
我使用了新推出的(口味)
applicationIdSuffix = ".demo"
来源:http://android-developers.blogspot.bg/2015/12/leveraging-product-flavors-in-android.html
这是我的 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"
}
}
到目前为止我不认为
versionNameSuffix
可与 flavors 一起使用,因此下面的代码仍然存在。
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";
...
}
}
我正在尝试 运行 在 Android 上进行仪器测试(或 Espresso 测试)。我从 Android Studio 和控制台得到的错误是:
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).
这是我的 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'
}
注意:我知道有很多类似的问题,但经过几天的搜索和尝试解决方案后,我还没有找到适合我的东西。
更新:
仪器测试用例:
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());
}
}
浓缩咖啡测试:
@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))));
}
}
两个测试都因相同的错误而失败,并且都没有执行代码。我正在使用 Android 版本 6,并在同一模拟器上成功地执行了来自 Internet 的 Instrumentation 和 Espresso 测试示例。
我终于解决了。它可能对其他人有用,所以我在这里发帖。
我设置应用程序 ID 的方式干扰了测试应用程序。虽然在 Android Studio 中,当我检查设备本身时,它看起来像是在安装具有正确包名称的应用程序,但测试应用程序 ID 缺少来自 "version" 风格维度的“.demo”。
我使用了新推出的(口味)
applicationIdSuffix = ".demo"
来源:http://android-developers.blogspot.bg/2015/12/leveraging-product-flavors-in-android.html
这是我的 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"
}
}
到目前为止我不认为
versionNameSuffix
可与 flavors 一起使用,因此下面的代码仍然存在。
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";
...
}
}