使用 "Conflict with dependency" 构建 Espresso 测试失败

Espresso test fail's to build with "Conflict with dependency"

我只是想使用 Android Studio 版本 3.2.1 中的 "Record Espresso test" 开始集成我的应用程序的一些基本测试。 我可以记录测试。之后,Studio 提示我缺少某些依赖项以及是否应该添加它们。 我这里 select 是的。 Gradle 想再次同步,该过程已顺利完成。 如果我现在想要 运行 其中一项测试,构建过程就会启动。它失败了

Conflict with dependency 'androidx.annotation:annotation' in project ':app'. Resolved versions for app (1.0.0-rc01) and test app (1.0.0) differ. See https://d.android.com/r/tools/test-apk-dependency-conflicts.html for details.

我查看了提供的 link,但它并没有真正让我更进一步。

谁能指导我正确的方向,我做错了什么?

由于 30000 个字符的限制,"androidDependencies" 的结果太长,无法附加到我的问题中。

我的Android应用程序Gradle文件

apply plugin: 'com.android.application'

project.ext.appPlayStoreVersion = 68
project.ext.appVersion = '1.8.2'
project.ext.appLabel = 'FreightWeight'

project.ext.compileSdk = 28
project.ext.minSdk = 21
project.ext.targetSdk = 28

project.ext.firebase_version = '16.0.1'
project.ext.firebase_ui_version = '2.1.1'
project.ext.support_library_version = '27.1.1'
project.ext.buildTools = '28.0.3'
project.ext.multidex_version = '1.0.1'
project.ext.glide_version = '3.7.0'
project.ext.constraints_version = '1.0.2'

// Create a variable called keystorePropertiesFile, and initialize it to your
// keystore.properties file, in the rootProject folder.
def keystorePropertiesFile = rootProject.file("keystore.properties")

// Initialize a new Properties() object called keystoreProperties.
def keystoreProperties = new Properties()

// Load your keystore.properties file into the keystoreProperties object.
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))


android {
    signingConfigs {
        configRelease {
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
            storeFile file(keystoreProperties['storeFile'])
            storePassword keystoreProperties['storePassword']
        }
    }
    compileSdkVersion compileSdk
    defaultConfig {
        applicationId "de.mobacomp.android.freightweight"
        minSdkVersion minSdk
        targetSdkVersion targetSdk
        versionCode appPlayStoreVersion
        versionName "$appVersion"
        // Enabling multidex support.
        multiDexEnabled false
        resValue "string", "app_version_name", versionName
        signingConfig signingConfigs.configRelease
        testInstrumentationRunner = 'android.support.test.runner.AndroidJUnitRunner'
    }
    buildTypes {
        release {
            minifyEnabled true
            resValue "string", "app_name", appLabel
            resValue "string", "mobile_ads_id", "ca-app-pub-xyz"
            resValue "string", "ad_unit_banner_1", "ca-app-pub-xyz"
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.configRelease
            resValue "string", "APP_FILEPROVIDER", defaultConfig.applicationId + ".release" + ".fileprovider"
            // lets generate a proper file name
            applicationVariants.all { variant ->
                variant.outputs.all { output ->
                    def fileName = applicationId + "-v" + appVersion + "_" + versionCode + ".apk"
                    outputFileName = new File("release", fileName)

                }
            }
        }
        debug {
            minifyEnabled false
            resValue "string", "app_name", "FW-debug"
            resValue "string", "mobile_ads_id", "ca-app-pub-xyz"
            resValue "string", "ad_unit_banner_1", "ca-app-pub-xyz"
            applicationIdSuffix ".debug"
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.configRelease
            resValue "string", "APP_FILEPROVIDER", defaultConfig.applicationId + ".debug" + ".fileprovider"
        }
    }
    dexOptions {
        javaMaxHeapSize "4g"
        jumboMode true
    }
    productFlavors {
    }
    buildToolsVersion '28.0.3'
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    testImplementation 'junit:junit:4.12'

    // GLide
    implementation "com.github.bumptech.glide:glide:$glide_version"

    // Firebase stuff
    implementation "com.firebaseui:firebase-ui-database:4.2.1"
    implementation "com.firebaseui:firebase-ui-auth:4.2.1"
    implementation "com.google.firebase:firebase-core:16.0.5"
    implementation "com.google.firebase:firebase-database:16.0.5"
    implementation "com.google.firebase:firebase-storage:16.0.5"
    implementation "com.google.firebase:firebase-auth:16.0.5"

    implementation 'com.google.firebase:firebase-ml-vision:18.0.1'
    implementation 'com.google.firebase:firebase-ml-vision-image-label-model:17.0.2'

    // Google Play stuff
    implementation "com.google.android.gms:play-services-auth:16.0.1"
    implementation "com.google.android.gms:play-services-base:16.0.1"
    implementation "com.google.android.gms:play-services-analytics:16.0.5"
    implementation "com.google.android.gms:play-services-cast-framework:16.1.0"
    implementation 'com.google.gms:google-services:4.1.0'

    implementation "com.android.support:preference-v14:28.0.0"
    implementation "com.android.support:mediarouter-v7:28.0.0"
    implementation "com.android.support:design:28.0.0"
    implementation "com.android.support:customtabs:28.0.0"
    implementation "com.android.support:cardview-v7:28.0.0"
    implementation "com.android.support:recyclerview-v7:28.0.0"
    implementation "com.android.support:support-v4:28.0.0"
    implementation "com.android.support:appcompat-v7:28.0.0"
    implementation "com.android.support:palette-v7:28.0.0"
    implementation "com.android.support.constraint:constraint-layout:1.1.3"
    implementation 'com.android.support:recyclerview-v7:28.0.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'
    androidTestImplementation 'androidx.test:rules:1.1.0'
}



apply plugin: 'com.google.gms.google-services'

最后,我记录了一个简短的测试(也尝试了更长的测试,同样的错误)

package de.mobacomp.android.freightweight;


import androidx.test.espresso.ViewInteraction;
import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;
import org.hamcrest.core.IsInstanceOf;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.Espresso.pressBack;
import static androidx.test.espresso.action.ViewActions.click;
import static androidx.test.espresso.action.ViewActions.scrollTo;
import static androidx.test.espresso.assertion.ViewAssertions.matches;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withClassName;
import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.allOf;

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

    @Rule
    public ActivityTestRule<MainFragmentActivity> mActivityTestRule = new ActivityTestRule<>(MainFragmentActivity.class);

    @Test
    public void mainFragmentActivityTest() {
        // Added a sleep statement to match the app's execution delay.
        // The recommended way to handle such scenarios is to use Espresso idling resources:
        // https://google.github.io/android-testing-support-library/docs/espresso/idling-resource/index.html
        try {
            Thread.sleep(7000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        ViewInteraction button = onView(
                allOf(withId(R.id.buttonContinueStartApp),
                        childAtPosition(
                                childAtPosition(
                                        IsInstanceOf.<View>instanceOf(android.widget.LinearLayout.class),
                                        0),
                                1),
                        isDisplayed()));
        button.check(matches(isDisplayed()));

        ViewInteraction button2 = onView(
                allOf(withId(R.id.buttonContinueStartApp),
                        childAtPosition(
                                childAtPosition(
                                        IsInstanceOf.<View>instanceOf(android.widget.LinearLayout.class),
                                        0),
                                1),
                        isDisplayed()));
        button2.check(matches(isDisplayed()));

        // Added a sleep statement to match the app's execution delay.
        // The recommended way to handle such scenarios is to use Espresso idling resources:
        // https://google.github.io/android-testing-support-library/docs/espresso/idling-resource/index.html
        try {
            Thread.sleep(250);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        ViewInteraction overflowMenuButton = onView(
                allOf(withContentDescription("More options"),
                        childAtPosition(
                                childAtPosition(
                                        withId(R.id.action_bar),
                                        2),
                                0),
                        isDisplayed()));
        overflowMenuButton.perform(click());

        // Added a sleep statement to match the app's execution delay.
        // The recommended way to handle such scenarios is to use Espresso idling resources:
        // https://google.github.io/android-testing-support-library/docs/espresso/idling-resource/index.html
        try {
            Thread.sleep(250);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        ViewInteraction appCompatTextView = onView(
                allOf(withId(R.id.title), withText("Datenschutz Hinweise"),
                        childAtPosition(
                                childAtPosition(
                                        withId(R.id.content),
                                        0),
                                0),
                        isDisplayed()));
        appCompatTextView.perform(click());

        pressBack();

        // Added a sleep statement to match the app's execution delay.
        // The recommended way to handle such scenarios is to use Espresso idling resources:
        // https://google.github.io/android-testing-support-library/docs/espresso/idling-resource/index.html
        try {
            Thread.sleep(250);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        ViewInteraction overflowMenuButton2 = onView(
                allOf(withContentDescription("More options"),
                        childAtPosition(
                                childAtPosition(
                                        withId(R.id.action_bar),
                                        2),
                                0),
                        isDisplayed()));
        overflowMenuButton2.perform(click());

        // Added a sleep statement to match the app's execution delay.
        // The recommended way to handle such scenarios is to use Espresso idling resources:
        // https://google.github.io/android-testing-support-library/docs/espresso/idling-resource/index.html
        try {
            Thread.sleep(250);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        ViewInteraction appCompatTextView2 = onView(
                allOf(withId(R.id.title), withText("Settings"),
                        childAtPosition(
                                childAtPosition(
                                        withId(R.id.content),
                                        0),
                                0),
                        isDisplayed()));
        appCompatTextView2.perform(click());

        ViewInteraction linearLayout = onView(
                allOf(childAtPosition(
                        allOf(withId(R.id.recycler_view),
                                childAtPosition(
                                        withId(android.R.id.list_container),
                                        0)),
                        1),
                        isDisplayed()));
        linearLayout.perform(click());

        ViewInteraction linearLayout2 = onView(
                allOf(childAtPosition(
                        allOf(withId(R.id.recycler_view),
                                childAtPosition(
                                        withId(android.R.id.list_container),
                                        0)),
                        3),
                        isDisplayed()));
        linearLayout2.perform(click());

        ViewInteraction linearLayout3 = onView(
                allOf(childAtPosition(
                        allOf(withId(R.id.recycler_view),
                                childAtPosition(
                                        withId(android.R.id.list_container),
                                        0)),
                        4),
                        isDisplayed()));
        linearLayout3.perform(click());
    }

    private static Matcher<View> childAtPosition(
            final Matcher<View> parentMatcher, final int position) {

        return new TypeSafeMatcher<View>() {
            @Override
            public void describeTo(Description description) {
                description.appendText("Child at position " + position + " in parent ");
                parentMatcher.describeTo(description);
            }

            @Override
            public boolean matchesSafely(View view) {
                ViewParent parent = view.getParent();
                return parent instanceof ViewGroup && parentMatcher.matches(parent)
                        && view.equals(((ViewGroup) parent).getChildAt(position));
            }
        };
    }
}

"androidDependencies" 的输出太大,所以这里是 link。 Link to the file on my webserver

按照建议删除了“'com.google.gms:google-services:4.1.0'”,没有变化。

删除 implementation 'com.google.gms:google-services:4.1.0' 这是完全错误的。

问题可能是您将 com.android.supportandroidx.test 一起使用 而且 testInstrumentationRunner = "android.support.test.runner.AndroidJUnitRunner"androidx.test.

的错误测试 运行ner

app 没有单一的 androidx 依赖项 - 除了 libs 目录中的一些 .jar。 运行 ./gradlew app:dependencies > ./dependencies.txt && gedit ./dependencies.txt 看看过时的 androidx.annotation:annotation:1.0.0-rc01 是从哪里来的。

这样我就可以将其标记为完成:

我前段时间已经在Studio中对androidx进行了重构。再让它运行,又找到11个要转换的部分,现在开始测试。我假设 Studio 中的 Recording Espresso Test 功能未 jet 转换为 androidx,因此会产生配置冲突。

所以现在我可以记录 Espresso 测试并正常编译了。

感谢您的帮助。