./gradlew test connectedAndroidTest erases my getFilesDir() folder

你说的曾经没有我的故事 提交于 2021-02-08 14:13:41

问题


I'm writing a Room database into my getFilesDir() folder. (Writing the database onto the removable SD card is apparently going to require some major research!)

When I manually run my app, I want to write some records and leave them in the database, so I don't need to keep writing them again. When I run my tests, I switch the database name from "*.dat" to "_test.dat" (think Ruby on Rails's or Django's "environments" system). The tests are free to erase records.

This system works when I manually tweezer each test in Android Studio to run it. But when I run everything in a batch, in gradlew, something erases the "*.dat" version of the database. This means I must constantly manually repopulate the database, each time I manually test.

What inside gradlew is erasing the contents of my getFilesDir() folder? And how (without figuring out how to use "external" storage), do I defeat it?

Code samples available on request, but it's all just generic stuff. Switching to getExternalFilesDir() does not fix the problem. StackOverflow said to try ./gradlew test connectedAndroidTest -x uninstallAndroidTest, but there's no uninstallAndroidTest task.


The top level build.gradle:

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        google()
        jcenter()

    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.2'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()

    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

tasks.withType(Test) {
  testLogging {
    exceptionFormat "full"
    events "started", "skipped", "passed", "failed"
    showStandardStreams true
  }
}

The app/build.gradle:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.2"
    defaultConfig {
        applicationId "com.allflat.planarinfinity"
        minSdkVersion 26
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
//    packagingOptions {
//        exclude 'META-INF/DEPENDENCIES'
//        exclude 'META-INF/LICENSE'
//        exclude 'META-INF/LICENSE.txt'
//        exclude 'META-INF/license.txt'
//        exclude 'META-INF/NOTICE'
//        exclude 'META-INF/NOTICE.txt'
//        exclude 'META-INF/notice.txt'
//        exclude 'META-INF/ASL2.0'
//        exclude 'META-INF/INDEX.LIST'
//    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'com.google.android.material:material:1.0.0'
    testImplementation 'junit:junit:4.12'
   // testImplementation 'org.mockito:mockito-core:2.19.0'
    testImplementation 'androidx.arch.core:core-testing:2.1.0'
    androidTestImplementation 'org.powermock:powermock-core:2.0.2'
    androidTestImplementation 'org.powermock:powermock-module-junit4:2.0.2'
    androidTestImplementation 'org.powermock:powermock-api-easymock:2.0.2'
    androidTestImplementation 'androidx.test:core:1.2.0'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2-alpha02'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0-alpha02'
    androidTestImplementation 'com.android.support.test.espresso:espresso-contrib:3.2.0'
    androidTestImplementation 'androidx.test:rules:1.2.0'
//    androidTestImplementation 'androidx.test.platform.app:'
    implementation 'androidx.room:room-runtime:2.2.0'
    annotationProcessor 'androidx.room:room-compiler:2.2.0'
    testImplementation 'androidx.test:core:1.2.0'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test:rules:1.0.2'
    androidTestImplementation 'org.easymock:easymock:4.0.2'
//    androidTestImplementation 'org.mockito:mockito-core:2.19.0'
}

It's the 'uninstall' in here:

https://android.googlesource.com/platform/tools/base/+/8d969614b7beca74e4d17f2d1c5956e75053f7ce/build-system/builder/src/main/java/com/android/builder/internal/testing/SimpleTestCallable.java

Could someone take it out? It's annoying everyone.


回答1:


Per the winning entry here...

Run connectedAndroidTest and skip uninstall

...the answer is to write a Rakefile containing:

task default: [ :unit_test_and_install, :espresso_test ]

task :unit_test_and_install do
    sh './gradlew --console=verbose test installDebug installDebugAndroidTest'
end

devices = `adb devices`
serial_numbers = devices.split("\n")[1..-1].map{|q| q.split("\t")[0] }

task :espresso_test do

    threads = serial_numbers.map do |sn|
        Thread.new do
            sh "adb -s #{sn} shell am instrument -w -r -e package com.mycorp.myapp -e disableAnalytics true " + 
                    "com.mycorp.myapp.test/androidx.test.runner.AndroidJUnitRunner | tee #{sn}.txt"
        end
    end

    threads.each &:join

    serial_numbers.each do |sn|
        grop = `grep "^OK .*tests" #{sn}.txt`

        if grop == ''
            sh "cat #{sn}.txt"
            abort 'FAILURES on ' + sn
        end
    end

end

Then just enter $ rake. All the tests run, while my manual-testing data and configurations all survive.

We need a Ruby Rakefile, not a Makefile, because we need to process the output and look for errors to successfully return either 0 or 1 to the environment. But adb etc fails the rule "test faults are syntax errors," and does not propagate the correct exit value at fault time. I want my command line to abend and not commit broken code, so we stash the test outputs into SERIALNUMBER.txt files and then grep them.

And we need threads, so many devices can test at the same time without waiting for each other.

Correctly detecting errors allows one to integrate in one line, $ rake && git commit -am 'the same comment every time' && git push. If there were any errors, they display on the console, and the git commit does not happen.

And we need Makefile-style processing, because if any command fails we need to stop processing, following the rule "test faults are syntax errors."

(A new bug is at Espresso test fault time we no longer get the message saying where is the HTML output file, but because the error itself is in the spew this is less of a problem.)

Another bug: If I have two tablets hooked up via USB debugging, I get error: more than one device/emulator, which is utterly bogus because ./gradlew test connectedAndroidTest naturally works correctly on all devices... That's why the Rakefile must find all the devices and then dispatch adb shell -s to each one.

Please write any and all complaints about using a lowly Rakefile to call gradlew here: [__].



来源:https://stackoverflow.com/questions/57433975/gradlew-test-connectedandroidtest-erases-my-getfilesdir-folder

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!