Travis CI和CodeCov Android

4

我正在尝试使用Travis CI,并让其运行测试以在codecov上查看结果。

.travis.yml:

language: android
sudo: required
jdk: oraclejdk8

before_cache:
 - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
 - rm -fr $HOME/.gradle/caches/*/plugin-resolution/

cache:
 directories:
 - $HOME/.gradle/caches/
 - $HOME/.gradle/wrapper/

env:
 global:
 - ANDROID_API=25
 - EMULATOR_API=21
 - ANDROID_BUILD_TOOLS=25.0.0
 - ADB_INSTALL_TIMEOUT=5 # minutes

android:
 components:
 - tools
 - platform-tools
 - build-tools-$ANDROID_BUILD_TOOLS
 - android-$ANDROID_API
 - android-$EMULATOR_API_LEVEL
 - extra-google-m2repository
 - extra-android-m2repository # for design library
 - addon-google_apis-google-19 # google play services
 - sys-img-armeabi-v7a-addon-google_apis-google-$ANDROID_API_LEVEL
 - sys-img-armeabi-v7a-addon-google_apis-google-$EMULATOR_API_LEVEL

licenses:
 - android-sdk-preview-license-.+
 - android-sdk-license-.+
 - google-gdk-license-.+

before_install:
- mkdir "$ANDROID_HOME/licenses" || true
- echo -e "\n8933bad161af4178b1185d1a37fbf41ea5269c55" > "$ANDROID_HOME/licenses/android-sdk-license"
- echo -e "\n84831b9409646a918e30573bab4c9c91346d8abd" > "$ANDROID_HOME/licenses/android-sdk-preview-license"
- chmod +x gradlew
#- ./gradlew dependencies || true # DON'T ADD unless you are getting "Install missing components using SDK manager"
#Source: https://medium.com/@oldergod/constraint-layout-and-circleci-travis-d50342696d2



script:
  - ./gradlew build jacocoTestReport assembleAndroidTest
  - echo no | android create avd --force -n test -t android-21 --abi armeabi-v7a
  - emulator -avd test -no-skin -no-audio -no-window &
  - android-wait-for-emulator
  - adb shell setprop dalvik.vm.dexopt-flags v=n,o=v
  - ./gradlew connectedCheck

after_success:
- bash <(curl -s https://codecov.io/bash)

build.gradle:

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

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.2'
        classpath 'com.dicedmelon.gradle:jacoco-android:0.1.1'
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

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

build.gradle(app):

apply plugin: 'com.android.application'
apply plugin: 'jacoco-android'

android {
    compileSdkVersion 24
    buildToolsVersion "24.0.3"
    defaultConfig {
        applicationId "<ID>"
        minSdkVersion 15
        targetSdkVersion 24
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        vectorDrawables.useSupportLibrary = true
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        debug {
            testCoverageEnabled true
        }
    }
    testOptions {
        unitTests.returnDefaultValues = true
    }
    lintOptions {
        abortOnError false
    }
    productFlavors {
        free {}
        paid {}
    }


    packagingOptions {
        exclude 'META-INF/DEPENDENCIES'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'
    }
}

dependencies {
    compile files('libs/httpclient-4.5.1.jar')
    compile fileTree(include: ['*.jar'], dir: 'libs')
    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
        exclude group: 'com.android.support', module: 'support-annotations'
    })
    compile 'com.android.support:appcompat-v7:24.2.1'
    compile 'com.android.support:support-v4:24.2.1'
    compile 'com.android.support:design:24.2.1'
    compile 'com.android.support:support-vector-drawable:24.2.1'
    testCompile 'junit:junit:4.12'
    compile files('libs/themoviedbapi-4.3.jar')
    compile files('libs/api-common-2.0.jar')
    compile files('libs/commons-codec-1.9.jar')
    compile files('libs/commons-lang3-3.4.jar')
    compile files('libs/httpcore-4.4.3.jar')
    compile files('libs/jackson-annotations-2.7.1.jar')
    compile files('libs/jackson-core-2.7.1.jar')
    compile files('libs/jackson-databind-2.7.1.jar')
    compile files('libs/slf4j-api-1.7.16.jar')
}

我们正在尝试运行的测试是一种仪器化测试。在Travis日志上的输出如下所示:
com.example.fabian.tinf15b4_lsmf.SeeMovieDetailsTest > seeMovieDetails[test(AVD) - 5.0.2] [31mFAILED [0m
    java.lang.NoSuchMethodError: No virtual method releaseConnection()V in class Lorg/apache/http/client/methods/HttpRequestBase; or its super classes (declaration of 'org.apache.http.client.methods.HttpRequestBase' appears in /system/framework/ext.jar)

    at org.yamj.api.common.http.DigestedResponseReader.processRequest(DigestedResponseReader.java:119)

Tests on test(AVD) - 5.0.2 failed: Instrumentation run failed due to 'java.lang.NoSuchMethodError'
:app:connectedFreeDebugAndroidTest FAILED

同时,还有自动生成的测试,它只是添加两个数字并检查结果,但Travis甚至没有经过它。

有人可以帮忙解决这个问题吗?


我没有使用HttpClient,但是下面添加了一些相关答案,或许可以帮助你。 - albodelu
1个回答

0

阅读这个相关问题关于HTTPClient - .releaseConnection的NoSuchMethodError

方法HttpRequestBase#releaseConnection()4.2版本中被添加了。 可能是由于jar包冲突。如果编译器没有编译错误,那么在运行时可能会加载另一个版本的类。真正的原因取决于您的构建工具。如果您使用的是maven/gradle,则可能存在一些传递依赖关系。 实际上,HttpRequestBase#releaseConnection()方法只是代理调用AbstractExecutionAwareRequest#reset()。而AbstractExecutionAwareRequest#reset()只是取消方法执行。这可能不是您需要的。 执行和释放httpClient资源的正确方法是关闭httpResponse,这意味着您可以释放httpClient内部线程池中的线程。
private static String makeRequest(HttpUriRequest httpRequest) throws IOException {
        CloseableHttpResponse httpResponse = httpClient.execute(httpRequest);
        try {
            HttpEntity httpEntity = httpResponse.getEntity();
            StringWriter writer = new StringWriter();
            IOUtils.copy(httpEntity.getContent(), writer, "UTF-8");
            return writer.toString();
        } finally {
            httpResponse.close();
        }
    }

快速入门中,您会看到.releaseConnection()不再使用(已弃用),而是关闭响应对象以确保连接关闭。
尝试使用不同的httpclienthttpcore版本(从这里):
看起来您有一个包含旧/新版本BasicHttpContext的jar文件。如果存在直接冲突,您将收到ClassNotFoundException。类加载器通常对此类事情很苛刻。在这种情况下,该类存在,但是没有另一个库(我认为是httpclient调用上下文)编译的方法。

对于API 23+,您还可以像这样在/app/build.gradle中添加已删除的apache库

android {
compileSdkVersion 24
buildToolsVersion "24.0.3"
    useLibrary 'org.apache.http.legacy'
    ...
}

Android 6.0版本不再支持Apache HTTP客户端。如果您的应用程序正在使用此客户端并且目标为Android 2.3(API级别9)或更高版本,请改用HttpURLConnection类。该API更加高效...。 本文这个示例似乎很有用,可以为Android和Travis-ci配置Codecov:
生成仪器测试代码覆盖率报告需要对构建脚本进行轻微更改。
android {
  buildTypes {
    debug {
      testCoverageEnabled true
    }
  }
}

为了避免测试被覆盖率报告忽略,我们需要配置以下设置:
android {
  testOptions {
    unitTests.all {
      jacoco {
        includeNoLocationClasses = true
      }
    }
  }
}

接下来,我们需要配置报告输出:
 jacocoAndroidUnitTestReport {
  csv.enabled false
  html.enabled true
  xml.enabled true
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接