5

Mamy aplikację wielomodułową. Gdzie mamy 3 projekty biblioteczne i 1 projekt uruchomienia.Raport pokrycia testu Android dla aplikacji wielomodułowej

module1 (Libraray) module2 (Libraray) zależy module1 module3 (Libraray) zależy module1

początku (nie ma żadnego kodu źródłowego jej tylko launcher dla wszystkich lib) zależy Module1 i modułu 2

W module 1 uzyskujemy dostęp do modułów moduł 2 i moduł 3 przy użyciu wzoru elewacji. Z tego względu musimy napisać wszystkie przypadki testowe w projekcie Launch, ponieważ mamy dostęp do wszystkich klas w projekcie uruchamiania, abyśmy mieli dostęp do wszystkich klas i przypadki testowe nie zawiedzie z powodu wyjątku NoClassDefException.

Kiedy piszemy przypadki testowe w projekcie Launch, jesteśmy w stanie uruchomić przypadki testowe i otrzymujemy raport wykonania jako 100% i tworzymy plik index.html ze wszystkimi szczegółami przypadków testowych, ale kiedy spróbuj wygenerować raport pokrycia, a następnie nie wyświetla żadnych danych do raportu pokrycia. Poniżej znajduje się mój plik gradle.

apply plugin: 'com.android.application' 
apply plugin: 'jacoco' 
android { 
compileSdkVersion 22 
buildToolsVersion "23.0.2"` 

defaultConfig { 
    applicationId "com.test.mobile" 
    minSdkVersion 14 
    targetSdkVersion 17 
    multiDexEnabled true 
    testApplicationId "com.test.mobile.test" 
    testInstrumentationRunner 'android.support.test.runner.AndroidJUnitRunner' 
} 

repositories { 
    mavenCentral() 
} 

buildTypes { 

    release { 
     minifyEnabled true 
     proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-project.txt' 
    } 

    debug{ 
     testCoverageEnabled true 
    } 
} 


dexOptions { 
    preDexLibraries = false 
    javaMaxHeapSize "4096M" 
    jumboMode = true 
    incremental false 
} 

afterEvaluate { 
    tasks.matching { 
     it.name.startsWith('dex') 
    }.each { dx -> 
     if (dx.additionalParameters == null) { 
      dx.additionalParameters = [] 
     } 
     dx.additionalParameters += '--multi-dex' 
     dx.additionalParameters += "--main-dex-list=$projectDir\\multidex-main-dex-list.txt".toString() 
    } 
}} 
dependencies { 
compile project(':module2') 
compile project(':module3') 
compile "com.android.support.test.espresso:espresso-idling-resource:2.2.1" 

// Dependencies for local unit tests 
testCompile "junit:junit:4.12" exclude group: 'com.android.support', module: 'support-annotations' 

testCompile "org.mockito:mockito-all:1.10.19" exclude group: 'com.android.support', module: 'support-annotations' 
testCompile "org.hamcrest:hamcrest-all:1.3" exclude group: 'com.android.support', module: 'support-annotations' 
testCompile "org.powermock:powermock-module-junit4:1.6.2" exclude group: 'com.android.support', module: 'support-annotations' 
testCompile "org.powermock:powermock-api-mockito:1.6.2" exclude group: 'com.android.support', module: 'support-annotations' 


// Android Testing Support Library's runner and rules 
androidTestCompile "com.android.support.test:runner:0.4.1" exclude group: 'com.android.support', module: 'support-annotations' 
androidTestCompile "com.android.support.test:rules:0.4.1" exclude group: 'com.android.support', module: 'support-annotations' 

// Espresso UI Testing dependencies. 
androidTestCompile "com.android.support.test.espresso:espresso-core:2.2.1" exclude group: 'com.google.code.findbugs' exclude group: 'javax.annotation' exclude group: 'com.android.support', module: 'support-annotations' exclude module: 'javax.annotation-api' 
androidTestCompile "com.android.support.test.espresso:espresso-contrib:2.2.1" exclude group: 'com.google.code.findbugs' exclude group: 'javax.annotation' exclude group: 'com.android.support', module: 'support-annotations' exclude module: 'javax.annotation-api' exclude group: 'com.android.support', module: 'support-v4' 
androidTestCompile "com.android.support.test.espresso:espresso-intents:2.2.1" exclude group: 'com.google.code.findbugs' exclude group: 'javax.annotation' exclude group: 'com.android.support', module: 'support-annotations' exclude module: 'javax.annotation-api'} 

task jacocoTestReport(type: JacocoReport, dependsOn: 'testDebugUnitTest') { def projects = new ArrayList() subprojects.each { prj -> projects.add(prj) }

reports { 
    xml.enabled = true 
    html.enabled = true 
} 

jacocoClasspath = configurations['androidJacocoAnt'] 

def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*'] 
def debugTree = fileTree(dir: "${buildDir}/intermediates/classes/debug", excludes: fileFilter) 
def mainSrc = "${project.projectDir}/src/main/java" 

sourceDirectories = files([mainSrc]) 
classDirectories = files([debugTree]) 
/*sourceDirectories = generateSourceFiles(projects) 
classDirectories = generateClassDirs(projects)*/ 

executionData = files(["${buildDir}/jacoco/testDebugUnitTest.exec", 
         "${buildDir}/outputs/code-coverage/connected/coverage.ec" 
])} 
+0

masz podobne zmiany w 'build.gradle' dla bibliotek? –

+0

Poniżej znajduje się jeden z plików projektu lib.compadle. 'android { compileSdkVersion 22 buildToolsVersion" 23.0.2" defaultConfig { minSdkVersion 14 targetSdkVersion 17 multiDexEnabled prawdziwe } buildTypes { uwalnianie { minifyEnabled fałszywe proguardFiles getDefaultProguardFile ('PROGUARD-android.txt'), 'Proguard-project.txt' } } } ' } Informacje o przypadkach testowych nie są dostępne w projektach biblioteki –

Odpowiedz

3

To co mieliśmy w naszym najwyższym build.gradle do generowania raportów pokrycia HTML:

def coverageSourceDirs = ['app/src/main/java', 'core/src/main/java', 'database/src/main/java'] 

def coverageExcludes = ['**/R.class', 
         '**/R$*.class', 
         '**/*$$ViewBinder*.*', 
         '**/inject/*', 
         '**/*$InjectAdapter.*', 
         '**/BuildConfig.*', 
         '**/Manifest*.*', 
         '**/Dagger*.*', 
         '**/*_Provide*Factory.*', 
         '**/*_Member*Injector.*', 
         '**/*_Factory.*'] 

def coverageClassDirectories = [fileTree(dir: 'app/build/intermediates/classes/debug', excludes: coverageExcludes), 
           fileTree(dir: 'core/build/intermediates/classes/debug', excludes: coverageExcludes), 
           fileTree(dir: 'database/build/intermediates/classes/debug', excludes: coverageExcludes)] 

task jacocoRootReport(type: JacocoReport) { 
    dependsOn "app:jacocoTestReport", 
      "core:jacocoTestReport", 
      "database:jacocoTestReport" 

    additionalSourceDirs = files(coverageSourceDirs) 
    sourceDirectories = files(coverageSourceDirs) 
    classDirectories = files(coverageClassDirectories) 
    executionData = files(tasks.getByPath("app:jacocoTestReport").executionData, 
      tasks.getByPath("core:jacocoTestReport").executionData, 
      tasks.getByPath("database:jacocoTestReport").executionData  
) 

    reports { 
     html.enabled = true 
     xml.enabled = false 
     csv.enabled = false 
    } 
    onlyIf = { 
     true 
    } 

    doFirst { 
     executionData = files(executionData.findAll { 
      it.exists() 
     }) 
    } 
} 

A w każdym modułem:

android { 
    buildTypes { 
     release { 
      minifyEnabled false 
      proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 
     } 

     debug { 
      testCoverageEnabled = true 
     } 
    } 
} 

def coverageSourceDirs = ['src/main/java'] 

task jacocoTestReport(type: JacocoReport, dependsOn: "testJenkinsUnitTest") { 
    group = "Reporting" 

    description = "Generate Jacoco coverage reports" 

    classDirectories = fileTree(dir: 'build/intermediates/classes/debug', 
      excludes: ['**/R.class', 
         '**/R$*.class', 
         '**/*$$ViewBinder*.*', 
         '**/inject/*', 
         '**/*$InjectAdapter.*', 
         '**/BuildConfig.*', 
         '**/Manifest*.*', 
         '**/Dagger*.*', 
         '**/*_Provide*Factory.*', 
         '**/*_Member*Injector.*', 
         '**/*_Factory.*', 
         '**/PagerTitleStripV22*.*']) 

    additionalSourceDirs = files(coverageSourceDirs) 
    sourceDirectories = files(coverageSourceDirs) 
    executionData = files('build/jacoco/testDebugUnitTest.exec') 

    doFirst { 
     new File("$buildDir/intermediates/classes/").eachFileRecurse { file -> 
      if (file.name.contains('$$')) { 
       file.renameTo(file.path.replace('$$', '$')) 
      } 
     } 
    } 

    reports { 
     xml.enabled = false 
     html.enabled = true 
    } 
} 

Zauważ, że nie potrzebujesz tego, jeśli analizujesz zasięg za pomocą wtyczki Jenkins lub sonaru.

P.S. jeśli masz jakiekolwiek problemy, sprawdź wszystkie ścieżki ręcznie, mogę coś pomylić. To jest naprawdę ból w konfiguracji to

+0

Czy masz przypadki testowe we wszystkich modułach tylko tylko w modułach głównych W naszym przypadku mamy moduł, który zawiera wszystkie przypadki testowe dla wszystkich modułów (aplikacja, rdzeń, baza danych). W tym module nie mamy żadnego kodu źródłowego. –

+0

Nie sądzę, że testy powinny być oddzielnym modułem :) I mamy testy w ramach bibliotek. Ale nie powinno to stanowić problemu, główna ścieżka do zajęć, źródła i wyniki zasięgu powinny być ustawione prawidłowo. –

+0

HI Bardzo dziękuję za wsparcie. Zaktualizowałem projekt testowy, który symuluje nasz problem w github. https://github.com/HariSoni87/codecoveragetest/tree/master/junittest_coverage_launch Proszę spojrzeć na projekt i poinformować nas, gdzie idziemy źle. Dokonaliśmy wielu zmian, które nie wydają się działać. –

4

mam 3 modułów nazwanych z gcm_demo, googleservices i networkcommunication więc pod build.gradle każdego modułu zapisu

apply plugin: 'jacoco' 

task jacocoTestReport(type: JacocoReport, dependsOn: ['testDebugUnitTest', 'createDebugCoverageReport']) { 
reports { 
    xml.enabled = true 
    html.enabled = true 
} 

def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*'] 
def debugTree = fileTree(dir: "${buildDir}/intermediates/classes/debug", excludes: fileFilter) 
def mainSrc = "${project.projectDir}/src/main/java" 

sourceDirectories = files([mainSrc]) 
classDirectories = files([debugTree]) 
executionData = fileTree(dir: "$buildDir", includes: [ 
     "jacoco/testDebugUnitTest.exec", "outputs/code-coverage/connected/*coverage.ec" 
]) 
} 

Teraz w Projekcie build.gradle napisać następujący scrpit

apply plugin: 'jacoco' 
task jacocoRootReport(type: JacocoReport, dependsOn: ['gcm_demo:jacocoTestReport', 'googleservice:jacocoTestReport', 'networkcommunication:jacocoTestReport']) { 
reports { 
    xml.enabled = true 
    html.enabled = true 
} 
sourceDirectories = files([tasks.getByPath("gcm_demo:jacocoTestReport").sourceDirectories, 
          tasks.getByPath("googleservice:jacocoTestReport").sourceDirectories, 
          tasks.getByPath("networkcommunication:jacocoTestReport").sourceDirectories]) 

classDirectories = files([tasks.getByPath("gcm_demo:jacocoTestReport").classDirectories, 
          tasks.getByPath("googleservice:jacocoTestReport").classDirectories, 
          tasks.getByPath("networkcommunication:jacocoTestReport").classDirectories]) 

executionData = files([tasks.getByPath("gcm_demo:jacocoTestReport").executionData, 
         tasks.getByPath("googleservice:jacocoTestReport").executionData, 
         tasks.getByPath("networkcommunication:jacocoTestReport").executionData]) 

} 

do stosowania egzekucji

gradlew clean jRR (short abbreviation) 

po pomyślnym folderze wyjściowym build jest

{project location}\build\reports\jacoco\jacocoRootReport\html\index.html 

to zapewnia pełne pokrycie projektowej UI i unittest

+0

Nadal widzę tylko pakiety modułów aplikacji w raportach pokrycia ... Nie mogę znaleźć pakietu submodułów w raporcie pokrycia. Czy możesz wyjaśnić, jak to zrobić? Również jestem w stanie uzyskać mój raport częściowy jacoc działa niezależnie i uzyskać raport zasięgu dla niego. jednak gdy uruchamiam kartę jacocoreporttask w module głównym, to nie zawiera ona modułów submodułowych? –