Giter Site home page Giter Site logo

vanniktech / gradle-android-junit-jacoco-plugin Goto Github PK

View Code? Open in Web Editor NEW
398.0 398.0 73.0 542 KB

Gradle plugin that generates JaCoCo reports from an Android Gradle Project

Home Page: http://vanniktech.com

License: Apache License 2.0

Groovy 98.25% Shell 1.75%
android gradle-plugin jacoco junit

gradle-android-junit-jacoco-plugin's People

Contributors

alexrwegener avatar aygalinc avatar bskim45 avatar cgcgbcbc avatar dazza5000 avatar fo2rist avatar gtcompscientist avatar henriquenfaria avatar igorwojda avatar jaredsburrows avatar jeppeman avatar jonatbergn avatar laimiux avatar lalunamel avatar ncd7 avatar ntarocco avatar outlying avatar passsy avatar rickie avatar setheclark avatar timyates avatar vanniktech avatar vasdeepika avatar vrallev avatar vysotskivadim avatar zsavely avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gradle-android-junit-jacoco-plugin's Issues

Coverage only for unit tests in Android projects

Currently, code is skipping all Android tests since Jacoco tasks are based on test${sourceName.capitalize()}UnitTest

I'm not sure if this is intended or not, but further, in code plugin ignores a lot of Android related stuff

private static ArrayList<String> getExcludes() {
    ['**/R.class',
     '**/R$*.class',
     '**/*$$*',
     '**/*$ViewInjector*.*',
     '**/*$ViewBinder*.*',
     '**/BuildConfig.*',
     '**/Manifest*.*',
     '**/*$Lambda$*.*', // Jacoco can not handle several "$" in class name.
     '**/*Dagger*.*', // Dagger auto-generated code.
     '**/*MembersInjector*.*', // Dagger auto-generated code.
     '**/*_Provide*Factory*.*' // Dagger auto-generated code.
    ]
}

This suggests that coverage should include instrumentation tests as well

Exclusions always cause Report to Fail

If I try to define some exclusions as in the DSL:

junitJacoco {
jacocoVersion = '0.7.2.201409121644' // type String
excludes = ['com/castillo/dd/', 'com/jess/ui/']
}

This will always cause the report portion to fail. If I remove the excludes the report is generated as expected.

I'm using version 0.5.0 of the plugin.

Generate csv report

Would you be open to generating the csv report in addition to the html and xml reports? Or giving the option to generate via extension? Would be more than willing to open a pr. Thanks!

Coverage doesn't work when flag missing

When using newer versions of jacoco, such as 0.7.6.201602180812, the coverage report show's no coverage unless the includeNoLocationClasses flag is set to true, see snippet below. If this library can be updated to automatically specify it for jacoco versions > 0.7.2, then you can probably remove defining it to 0.7.2.201409121644 in JunitJacocoExtension and use the default in gradle.

android {
    testOptions {
        unitTests.all {
            jacoco {
                includeNoLocationClasses = true
            }
        }
    }
}

See related bugs:
robolectric/robolectric#2230
jacoco/jacoco#288

Fix broken code cov

CodeCov has not been updated in months:
https://codecov.io/gh/vanniktech/gradle-android-junit-jacoco-plugin/commits

See the latest CI build:
https://travis-ci.org/vanniktech/gradle-android-junit-jacoco-plugin#L364

    Executing gcov (find /home/travis/build/[secure]/gradle-android-junit-jacoco-plugin -type f -name '*.gcno'  -exec gcov -pb  {} +)
==> Collecting reports
Error: No coverage report found
Tip: See an example jdk repo: https://github.com/codecov/example-jdk
Support channels:
  Email:   [email protected]
  IRC:     #codecov
  Gitter:  https://gitter.im/codecov/support
  Twitter: @codecov
Done. Your build exited with 0.

Rewrite Plugin to Kotlin

If i use the plugin with android build tools in version 3.3.0 and gradle in 4.10.2, i get a conflict on groovy version.

A current workaround can be to specify manually the groovy version in buildscript dependencies section :
dependencies { //Jacoco-Android classpath 'org.codehaus.groovy:groovy-all:2.4.15' classpath ("com.vanniktech:gradle-android-junit-jacoco-plugin:0.14.0-SNAPSHOT") }

The exception is the following :

* Exception is: org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':components:gxma.forum.protocol.coap.udp.adapter.component:jacocoDebug'. at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:110) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:77) at org.gradle.api.internal.tasks.execution.OutputDirectoryCreatingTaskExecuter.execute(OutputDirectoryCreatingTaskExecuter.java:51) at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:59) at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54) at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:59) at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:101) at org.gradle.api.internal.tasks.execution.FinalizeInputFilePropertiesTaskExecuter.execute(FinalizeInputFilePropertiesTaskExecuter.java:44) at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:91) at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:62) at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:59) at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54) at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43) at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.run(EventFiringTaskExecuter.java:51) at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:300) at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:292) at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:174) at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90) at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:46) at org.gradle.execution.taskgraph.LocalTaskInfoExecutor.execute(LocalTaskInfoExecutor.java:42) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareWorkItemExecutor.execute(DefaultTaskExecutionGraph.java:277) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareWorkItemExecutor.execute(DefaultTaskExecutionGraph.java:262) at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:135) at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:130) at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.execute(DefaultTaskPlanExecutor.java:200) at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.executeWithWork(DefaultTaskPlanExecutor.java:191) at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.run(DefaultTaskPlanExecutor.java:130) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63) at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46) at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55) Caused by: org.gradle.workers.WorkerExecutionException: There was a failure while executing work items at org.gradle.workers.internal.DefaultWorkerExecutor.workerExecutionException(DefaultWorkerExecutor.java:155) at org.gradle.workers.internal.DefaultWorkerExecutor.await(DefaultWorkerExecutor.java:149) at com.android.build.gradle.internal.tasks.JacocoTaskDelegate.run(JacocoTaskDelegate.java:100) at com.android.build.gradle.internal.tasks.JacocoTask.run(JacocoTask.java:77) at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73) at org.gradle.api.internal.project.taskfactory.IncrementalTaskAction.doExecute(IncrementalTaskAction.java:50) at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:39) at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:26) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:131) at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:300) at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:292) at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:174) at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90) at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:120) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:99) ... 31 more Caused by: org.gradle.workers.internal.DefaultWorkerExecutor$WorkExecutionException: A failure occurred while executing com.android.build.gradle.internal.tasks.JacocoTaskDelegate$JacocoWorkerAction at org.gradle.workers.internal.DefaultWorkerExecutor$1.call(DefaultWorkerExecutor.java:104) at org.gradle.workers.internal.DefaultWorkerExecutor$1.call(DefaultWorkerExecutor.java:96) at org.gradle.internal.work.AbstractConditionalExecution$1.run(AbstractConditionalExecution.java:38) at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runExecution(DefaultConditionalExecutionQueue.java:212) at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.runBatch(DefaultConditionalExecutionQueue.java:161) at org.gradle.internal.work.DefaultConditionalExecutionQueue$ExecutionRunner.run(DefaultConditionalExecutionQueue.java:130) ... 3 more Caused by: java.lang.ExceptionInInitializerError at org.gradle.api.internal.classloading.GroovySystemLoaderFactory.forClassLoader(GroovySystemLoaderFactory.java:44) at org.gradle.workers.internal.IsolatedClassloaderWorkerFactory.executeInWorkerClassLoader(IsolatedClassloaderWorkerFactory.java:97) at org.gradle.workers.internal.IsolatedClassloaderWorkerFactory.access$100(IsolatedClassloaderWorkerFactory.java:54) at org.gradle.workers.internal.IsolatedClassloaderWorkerFactory$1$1.call(IsolatedClassloaderWorkerFactory.java:78) at org.gradle.workers.internal.IsolatedClassloaderWorkerFactory$1$1.call(IsolatedClassloaderWorkerFactory.java:75) at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:314) at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:304) at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:174) at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:100) at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36) at org.gradle.workers.internal.IsolatedClassloaderWorkerFactory$1.execute(IsolatedClassloaderWorkerFactory.java:75) at org.gradle.workers.internal.DefaultWorkerExecutor$1.call(DefaultWorkerExecutor.java:102) ... 8 more Caused by: groovy.lang.GroovyRuntimeException: Conflicting module versions. Module [groovy-all is loaded in version 2.4.12 and you are trying to load version 2.4.15 ... 20 more

0.6-SNAPSHOT build failed: Could not resolve all dependencies for configuration

I am trying to use the version 0.6.0-SNAPSHOT because I need your addition of
includeNoLocationClasses = true
parameter added with the fix to #51, but when I build the app with this version of your plugin I have:

FAILURE: Build failed with an exception.

* What went wrong:
A problem occurred configuring project ':app'.
> Failed to notify project evaluation listener.
   > Could not resolve all dependencies for configuration ':app:_storeDebugApk'.
      > A problem occurred configuring project ':nspcoreui'.
         > Android tasks have already been created.
This happens when calling android.applicationVariants,
android.libraryVariants or android.testVariants.
Once these methods are called, it is not possible to
continue configuring the model.
   > Android tasks have already been created.
This happens when calling android.applicationVariants,
android.libraryVariants or android.testVariants.
Once these methods are called, it is not possible to
continue configuring the model.

* Try:
Run with --info or --debug option to get more log output.

* Exception is:

See attached full stack trace for more details.
Everything works instead with the release 0.5.
Can you help me out? I need it urgently if possible...

stacktrace.txt

The build.grade of mymodule1 is:


apply plugin: 'com.android.library'
apply plugin: 'me.tatarka.retrolambda'
apply plugin: 'com.vanniktech.android.junit.jacoco'

apply from: 'linter.gradle'

junitJacoco {
    jacocoVersion = rootProject.ext.jacocoVersion // type String
//    ignoreProjects = [] // type String array
    excludes =  rootProject.ext.jacocoExcludes
//    includeNoLocationClasses = true
}

android {
    compileSdkVersion rootProject.ext.compileSdkVersion
    buildToolsVersion rootProject.ext.buildToolsVersion

    dataBinding {
        enabled = true
    }

    defaultConfig {
        minSdkVersion 15
        versionCode 1
        versionName "1.0"
    }
    lintOptions {
        abortOnError false
    }
    buildTypes {
        debug {
            debuggable true
            testCoverageEnabled = true
        }
        release {
            testCoverageEnabled = false
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile "io.reactivex:rxjava:${rootProject.ext.rxJavaVersion}"
    compile "com.jakewharton.timber:timber:${rootProject.ext.timberVersion}"

    testCompile 'junit:junit:4.12'
    testCompile 'org.mockito:mockito-core:1.10.19'

    compile "com.android.support:support-annotations:${rootProject.ext.supportLibVersion}"

    compile "com.android.support:design:${rootProject.ext.supportLibVersion}"
    compile "com.android.support:appcompat-v7:${rootProject.ext.supportLibVersion}"
    compile "com.android.support:support-v4:${rootProject.ext.supportLibVersion}"

    compile "com.android.support:cardview-v7:${rootProject.ext.supportLibVersion}"
    compile "com.android.support:recyclerview-v7:${rootProject.ext.supportLibVersion}"
}

Gradle android plugin 3.0.0 failed

After update android gradle plugin to version 3.0.0 build failed with follow error:

Error:Execution failed for task ':app:transformClassesWithFirebasePerformancePluginForDebug'.

SHA-256 digest error for org/jacoco/agent/rt/RT.class

How this plugin work with Jenkins

I have a project working in Jenkins and a Record JaCoCo coverage report Jenkins Task after build.

And I make "Path to exec files" pointing to testDebugUnitTest.exec which is Junit JaCoCo gradle plugin produced, but after project build, JaCoCo report has 0 coverage about this code in Jenkins JaCoCo plugin dashborad, while reports/jacoco has a correct index.html for report in workspace.

It's a bug or not? if it's not how I can make it coverage right with code.

Multi Module report support

Hi, I could not find much info about it, sorry if the plugin already has support for this.
I have an app with unit tests in many android library modules, like
app/tests
shared/tests
repo/tests

If I run ./gradlew jacocoTestReportDebug it would run just the app/tests, right?
Is it possible to run the test report in all modules at once?

AndroidTest support

Hi, would it be possible to add androidTest unit test support ?
I think something like

final def testTaskName = "test${sourceName.capitalize()}UnitTest"
final def taskName = "jacocoTestReport${sourceName.capitalize()}"
final def buildTypeName = android.testBuildType.capitalize()
subProject.task(taskName, type: JacocoReport, dependsOn: [testTaskName, "connected${buildTypeName}AndroidTest"])

Could go here

Feature modules integration

Hi,

I'm migrating a pet project from a single module to multi modules (and instant app in the future) and I need JaCoCo integration. So, I tryied the snapshot version (0.12.0-SNAPSHOT) in the project but the following exception was thrown when running any command of Gradle:

Caused by: groovy.lang.MissingMethodException: No signature of method: java.util.ArrayList.all() is applicable for argument types: (com.vanniktech.android.junit.jacoco.GenerationPlugin$_addJacocoAndroid_closure7) values: [com.vanniktech.android.junit.jacoco.GenerationPlugin$_addJacocoAndroid_closure7@697ddda9]
Possible solutions: any(), tail(), tail(), last(), last(), add(java.lang.Object)
        at com.vanniktech.android.junit.jacoco.GenerationPlugin.addJacocoAndroid(GenerationPlugin.groovy:127)
        at com.vanniktech.android.junit.jacoco.GenerationPlugin.addJacoco(GenerationPlugin.groovy:48)
        at com.vanniktech.android.junit.jacoco.GenerationPlugin.addJacoco(GenerationPlugin.groovy:41)
        at com.vanniktech.android.junit.jacoco.GenerationPlugin$_apply_closure2.doCall(GenerationPlugin.groovy:35)
        at org.gradle.listener.ClosureBackedMethodInvocationDispatch.dispatch(ClosureBackedMethodInvocationDispatch.java:40)
        at org.gradle.listener.ClosureBackedMethodInvocationDispatch.dispatch(ClosureBackedMethodInvocationDispatch.java:25)
        at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:42)
        at org.gradle.internal.event.BroadcastDispatch$SingletonDispatch.dispatch(BroadcastDispatch.java:230)
        at org.gradle.internal.event.BroadcastDispatch$SingletonDispatch.dispatch(BroadcastDispatch.java:149)
        at org.gradle.internal.event.AbstractBroadcastDispatch.dispatch(AbstractBroadcastDispatch.java:58)
        at org.gradle.internal.event.BroadcastDispatch$CompositeDispatch.dispatch(BroadcastDispatch.java:324)
        at org.gradle.internal.event.BroadcastDispatch$CompositeDispatch.dispatch(BroadcastDispatch.java:234)
        at org.gradle.internal.event.ListenerBroadcast.dispatch(ListenerBroadcast.java:140)
        at org.gradle.internal.event.ListenerBroadcast.dispatch(ListenerBroadcast.java:37)
        at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
        at com.sun.proxy.$Proxy24.afterEvaluate(Unknown Source)
        at org.gradle.configuration.project.LifecycleProjectEvaluator.notifyAfterEvaluate(LifecycleProjectEvaluator.java:76)

Thanks

can't find /reports/jacocoCombined folder after running combinedTestReportDebug

Hi,

My project has multiple android library modules and an android application module. All the android Espresso tests are in android application module. jacocoTestReportDebug and jacocoTestReportMerged are running fine for unit tests and seeing merged reports under root build folder, but when I run combinedTestReportDebug I don't see any jacocoCombined folder under root build folder.
I did add this statement in my root build.gradle file
apply plugin: "com.vanniktech.android.junit.jacoco"
junitJacoco {
includeInstrumentationCoverageInMergedReport = true
}

Here are last few lines from combinedTestReportDebug task:
Task :App:combinedTestReportDebug SKIPPED
file or directory ‘…App/build/outputs/code_coverage', not found
Skipping task ':App:combinedTestReportDebug' as task onlyIf is false.

I do see code_coverage folder in app build folder. Can you help me with this?

Thanks!

Support for Java 8 and Android Gradle Plugin 3.0.0

After upgrading the android gradle plugin to version 3.0.0 and adding java 8, the jacoco report is NOT generated anymore. Is this an issue with Java 8? If yes, how can get it to generate the report again?

How to get merged report for multiple module and multiple flavor

Hi, I am currently using this awesome plugin to generate coverage report.

My project structure looks like this:

app(android): with flavor 'mock' and 'prod'
  -- data (android) with flavor 'mock' and 'prod'
  -- domain (java) 

I have followed the tutorial and my root build.gradle is here:

buildscript {
    dependencies {
        ...
        classpath "com.vanniktech:gradle-android-junit-jacoco-plugin:0.13.0"
    }
}

apply plugin: "com.vanniktech.android.junit.jacoco"

Nothing more for module's build.gradle.

The questions is that how can I generate merged jacoco report which covers all related subprojects with specific flavor?

Like combinedMockDebug report which covers all subProjects and subProjects's unitTest and androidTest.

And one more thing, how can I ignore Kotlin generated class, like get and set in data class

Thanks in advance.

PS:
I can't find task
mergeJacocoReports and jacocoTestReportMerged
I only can find
combinedTestReportMockDeubg and jacocoTestReport<Flavor><BuildType>

Add Kotlin source directories

Currently it looks like the plugin is hard coded to expect all source files under either the product flavor/java or src/main/java. In my project, I have Kotlin and Java files separated. Is there a way with the plugin to configure it so that this extra directory can be added for a source folder.

In junitExtensions it would be nice to say have:

coverateSourceDirs = ["src/main/java", "src/main/kotlin"]

Fix code coverage for non android modules

There seems to be something wrong since if you run ./gradlew jacocoTestReport from this project and open the html site open build/reports/jacoco/test/html/index.html you'll get a blank page.

Master breaks Java modules

When using the latest master SNAPSHOT in this repository and executing ./gradlew jacocoTestReport it fails with:

org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':jacocoTestReport'.
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:110)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:77)
        at org.gradle.api.internal.tasks.execution.OutputDirectoryCreatingTaskExecuter.execute(OutputDirectoryCreatingTaskExecuter.java:51)
        at org.gradle.api.internal.tasks.execution.SkipCachedTaskExecuter.execute(SkipCachedTaskExecuter.java:105)
        at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:59)
        at org.gradle.api.internal.tasks.execution.ResolveTaskOutputCachingStateExecuter.execute(ResolveTaskOutputCachingStateExecuter.java:54)
        at org.gradle.api.internal.tasks.execution.ResolveBuildCacheKeyExecuter.execute(ResolveBuildCacheKeyExecuter.java:79)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:59)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:101)
        at org.gradle.api.internal.tasks.execution.FinalizeInputFilePropertiesTaskExecuter.execute(FinalizeInputFilePropertiesTaskExecuter.java:44)
        at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:91)
        at org.gradle.api.internal.tasks.execution.ResolveTaskArtifactStateTaskExecuter.execute(ResolveTaskArtifactStateTaskExecuter.java:62)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:59)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:54)
        at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
        at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:34)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.run(EventFiringTaskExecuter.java:51)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:300)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:292)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:174)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:46)
        at org.gradle.execution.taskgraph.LocalTaskInfoExecutor.execute(LocalTaskInfoExecutor.java:42)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareWorkItemExecutor.execute(DefaultTaskExecutionGraph.java:277)
        at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareWorkItemExecutor.execute(DefaultTaskExecutionGraph.java:262)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:135)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker$1.execute(DefaultTaskPlanExecutor.java:130)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.execute(DefaultTaskPlanExecutor.java:200)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.executeWithWork(DefaultTaskPlanExecutor.java:191)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor$ExecutorWorker.run(DefaultTaskPlanExecutor.java:130)
        at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:63)
        at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:46)
        at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:55)
Caused by: : Unable to read execution data file /Users/nik/dev/GitHub/gradle-android-junit-jacoco-plugin/build/jacoco/test.exec
        at org.jacoco.ant.ReportTask.loadExecutionData(ReportTask.java:515)
        at org.jacoco.ant.ReportTask.execute(ReportTask.java:489)
        at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:293)
        at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:106)
        at org.gradle.api.internal.project.ant.BasicAntBuilder.nodeCompleted(BasicAntBuilder.java:78)
        at org.gradle.internal.metaobject.BeanDynamicObject$MetaClassAdapter.invokeMethod(BeanDynamicObject.java:479)
        at org.gradle.internal.metaobject.BeanDynamicObject.tryInvokeMethod(BeanDynamicObject.java:191)
        at org.gradle.internal.metaobject.AbstractDynamicObject.invokeMethod(AbstractDynamicObject.java:160)
        at org.gradle.api.internal.project.antbuilder.AntBuilderDelegate.nodeCompleted(AntBuilderDelegate.java:118)
        at org.gradle.internal.jacoco.AbstractAntJacocoReport.invokeJacocoReport(AbstractAntJacocoReport.java:56)
        at org.gradle.internal.jacoco.AntJacocoReport$1.execute(AntJacocoReport.java:38)
        at org.gradle.internal.jacoco.AntJacocoReport$1.execute(AntJacocoReport.java:35)
        at org.gradle.internal.jacoco.AbstractAntJacocoReport$1.doCall(AbstractAntJacocoReport.java:46)
        at org.gradle.api.internal.ClosureBackedAction.execute(ClosureBackedAction.java:71)
        at org.gradle.api.internal.ClosureBackedAction.execute(ClosureBackedAction.java:53)
        at org.gradle.api.internal.project.antbuilder.DefaultIsolatedAntBuilder$2.execute(DefaultIsolatedAntBuilder.java:152)
        at org.gradle.api.internal.project.antbuilder.DefaultIsolatedAntBuilder$2.execute(DefaultIsolatedAntBuilder.java:134)
        at org.gradle.api.internal.project.antbuilder.ClassPathToClassLoaderCache.withCachedClassLoader(ClassPathToClassLoaderCache.java:134)
        at org.gradle.api.internal.project.antbuilder.DefaultIsolatedAntBuilder.execute(DefaultIsolatedAntBuilder.java:128)
        at org.gradle.internal.jacoco.AbstractAntJacocoReport.configureAntReportTask(AbstractAntJacocoReport.java:38)
        at org.gradle.internal.jacoco.AntJacocoReport.execute(AntJacocoReport.java:35)
        at org.gradle.testing.jacoco.tasks.JacocoReport.generate(JacocoReport.java:78)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:73)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:46)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:39)
        at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:26)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:801)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:768)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$1.run(ExecuteActionsTaskExecuter.java:131)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:300)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:292)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:174)
        at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:90)
        at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:120)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:99)
        ... 33 more
Caused by: java.io.IOException: Incompatible version 1007.
        at org.jacoco.core.data.ExecutionDataReader.readHeader(ExecutionDataReader.java:127)
        at org.jacoco.core.data.ExecutionDataReader.readBlock(ExecutionDataReader.java:107)
        at org.jacoco.core.data.ExecutionDataReader.read(ExecutionDataReader.java:87)
        at org.jacoco.core.tools.ExecFileLoader.load(ExecFileLoader.java:59)
        at org.jacoco.ant.ReportTask.loadExecutionData(ReportTask.java:513)
        ... 68 more

Support different flavors / build config for multiple modules with one gradle task

Hey, like your description said:

When having debug & release build types and red & blue flavors the following tasks would be created: jacocoTestReportRedDebug, jacocoTestReportBlueDebug, jacocoTestReportRedRelease and jacocoTestReportBlueRelease.

This introduces the problem, that your build scripts need multiple gradle tasks to generate every report of the project. For example:

./gradlew jacocoTestReportBlueDebug
./gradlew jacocoTestReportRedRelease

It would be awesome if it had the same behavior as the assemble gradle task. For example the following code executes assembleBlueDebug and assembleRedDebug:

./gradlew assembleDebug

Jenkins integration

First of all, thanks for this plugin! We use it on Android projects to track coverage.

This is a feature request for better Jenkins integration. We use the Jenkins Jacoco plugin as seen here - https://wiki.jenkins.io/display/JENKINS/JaCoCo+Plugin#JaCoCoPlugin-Recordingcoverageforbuilds. We can fail a build if coverage dips below a threshold, for example. The problem is that we have to define exclusions twice: once in our gradle file for local runs, and again in our Jenkins plugin configration. It also doesn't know about our class file locations, and it's easy to misconfigure to include test classes in coverage numbers. Is there some way to avoid this duplication, and use your plugin to do all of the work, and expose the results to Jenkins? I know they support an HTML publisher which could show the coverage reports, but I think the Jacoco plugin is the only thing that can expose specific coverage to Jenkins for build health, failing builds, etc.

Plugin execution fails if build flavors are configured

Suppose the following configuration (root build.gradle):

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        jcenter()
        mavenLocal()
        maven {
            url "https://oss.sonatype.org/service/local/repositories/snapshots/content" // needed for jacoco snapshot plugin
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.1.0-alpha5'
        classpath 'com.vanniktech:gradle-android-junit-jacoco-plugin:0.4.0-SNAPSHOT'
    }
}

allprojects {
    repositories {
        jcenter()
        mavenLocal()
    }
}

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

Now I have a single subproject called app which includes your latest 0.4.0-SNAPSHOT version as seen above like needed via apply plugin: "com.vanniktech.android.junit.jacoco" but also posses some build flavors. This is the shortened build.gradlefile:

apply plugin: 'com.android.application'
apply plugin: "com.vanniktech.android.junit.jacoco"

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"

    buildTypes {
        release {
        debug
    }

    flavorDimensions "target"

    productFlavors {
        staging {
            dimension "target"
        }
        live {
            dimension "target"
        }
    }
}

Because of this configuration, there is no testDebugUnitTest task, but rather there are tasks for testStagingDebugUnitTest and testLiveDebugUnitTest, one for each flavor. Because of this, calling gradle jacocoTestReportDebug on the root project fails as follows:

% gradle jacocoTestReportDebug

FAILURE: Build failed with an exception.

* What went wrong:
Could not determine the dependencies of task ':app:jacocoTestReportDebug'.
> Task with path 'testDebugUnitTest' not found in project ':app'.

The plugin should correctly create a task for each flavor like jacocoTestReportStagingDebug and jacocoTestReportLiveDebug or take care somehow other of that issue.

Why ./gradle build test launch androidConnectedTest task ?

Hi,

I have integrated your plugin in one of my project and i have the following problem.
I develop several gradle module to build a modular middleware.
I have a test module that contains an Android app in order to do the integration test of my middleware. Test have different flavor depending on the network layers that my middleware use (Http, Ble, usb...).
At this point, i have a CI environment that build and run test only for http because it can be keep inside the simulator.

My Ci start to build all modules and unit test them. But when i launch ./gradlew build test, it also triggers androidConnectedHttpTest and androidConnectedBleTest. In my understanding, ./gradlew test must only runs unit test.

Before I integrate your plugin instrumented tests were not launched.

So is this a bug or i misunderstand something ?

I try with plugin in version 0.13 & 0.14.0-SNAPSHOT, Gradle in 4.10.2 & android build tools in 3.3.0.

excluded variants break build

The plugin adds dependencies for tasks of build types which are excluded and therefore not found.

android {
    ...
    variantFilter { variant ->
        if (variant.name == "debug") {
            variant.setIgnore(true)
        }
    }
}

Results in:

FAILURE: Build failed with an exception.

* What went wrong:
Could not determine the dependencies of task ':app:jacocoTestReportDebug'.
> Task with path 'testDebugUnitTest' not found in project ':app'.

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

BUILD FAILED

Problems with outputting merged reports and updating JaCoCo version

Hi! First of all thanks for the plugin - I've found that it's the only one that actually works for me.
However, I faced with several problems (because of a multi-module project) which I can't solve.

  1. Task jacocoTestReportMerged (after executing ./gradlew clean jacocoTestReport mergeJacocoReports jacocoTestReportMerged) fails with the following stacktrace:
Caused by: java.lang.IllegalStateException: Can't add different class with same name: com/gen/bettermeditation/utils/preferences/NameOfTheClass
        at org.jacoco.core.analysis.CoverageBuilder.visitCoverage(CoverageBuilder.java:106)
        at org.jacoco.core.analysis.Analyzer$1.visitEnd(Analyzer.java:92)
        at org.objectweb.asm.ClassVisitor.visitEnd(ClassVisitor.java:317)
        at org.jacoco.core.internal.flow.ClassProbesAdapter.visitEnd(ClassProbesAdapter.java:133)
        at org.objectweb.asm.ClassReader.accept(ClassReader.java:697)
        at org.objectweb.asm.ClassReader.accept(ClassReader.java:506)
        at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:107)
        at org.jacoco.core.analysis.Analyzer.analyzeClass(Analyzer.java:142)

If I exclude NameOfTheClass.class through the excludes in the module config, I'll get another fail with another class and so on. This happens only with jacocoTestReportMerged task but not with mergeJacocoReports.

  1. I want to use a newer version of the JaCoCo, because it possibly works better with Kotlin (related items: this and this). However, if I override configs in each module with, for example, version 0.8.1 my build (./gradlew clean jacocoTestReport mergeJacocoReports) will fail with the following stacktrace:
Caused by: java.io.IOException: Incompatible version 1007.
        at org.jacoco.core.data.ExecutionDataReader.readHeader(ExecutionDataReader.java:127)
        at org.jacoco.core.data.ExecutionDataReader.readBlock(ExecutionDataReader.java:107)
        at org.jacoco.core.data.ExecutionDataReader.read(ExecutionDataReader.java:87)
        at org.jacoco.core.tools.ExecFileLoader.load(ExecFileLoader.java:59)
        at org.jacoco.ant.MergeTask.load(MergeTask.java:85)
        ... 61 more

Am I doing something wrong?

The JacocoReportBase.setExecutionData(FileCollection) method has been deprecated. This is scheduled to be removed in Gradle 6.0.

The JacocoReportBase.setExecutionData(FileCollection) method has been deprecated. This is scheduled to be removed in Gradle 6.0. Use getExecutionData().from(...)
        at org.gradle.testing.jacoco.tasks.JacocoReportBase.setExecutionData(JacocoReportBase.java:109)
        at org.gradle.testing.jacoco.tasks.JacocoReport_Decorated.setExecutionData(Unknown Source)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at groovy.lang.Closure.setProperty(Closure.java:353)
        at com.vanniktech.android.junit.jacoco.GenerationPlugin$_addJacocoAndroid_closure7$_closure14.doCall(GenerationPlugin.groovy:203)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:326)
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1041)
        at groovy.lang.Closure.call(Closure.java:411)
        at groovy.lang.Closure.call(Closure.java:427)
        at org.gradle.util.ClosureBackedAction.execute(ClosureBackedAction.java:70)
        at org.gradle.util.ConfigureUtil.configureTarget(ConfigureUtil.java:154)
        at org.gradle.util.ConfigureUtil.configureSelf(ConfigureUtil.java:130)
        at org.gradle.api.internal.AbstractTask.configure(AbstractTask.java:575)
        at org.gradle.api.internal.project.DefaultProject.task(DefaultProject.java:1240)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at com.vanniktech.android.junit.jacoco.GenerationPlugin$_addJacocoAndroid_closure7.doCall(GenerationPlugin.groovy:143)

Test report has created ,but coverage report not.

I run gradlew jacocoTestReportDebug ,test report has create,but jacoco's coverage report not.
What's the matter? Is my build.gradle config error? Or command error?
My project is Android Project and I add config in the root build.gradle .

Use jacoco version 0.7.7 to be compatible to jenkins plugin

Hey,

we use this plugin in combination with the JaCoCo Jenkins Plugin to show a coverage report trend in the jenkins build. While searching for a reason why the code coverage reports in Jenkins are empty, I found the following issue: https://issues.jenkins-ci.org/browse/JENKINS-28652

Unfortunately JaCoCo 0.7.5 breaks compatibility to previous binary formats of the jacoco.exec files. The JaCoCo plugin up to version 1.0.19 is based on JaCoCo 0.7.4, thus you cannot use this version with projects which already use JaCoCo 0.7.5 or newer. JaCoCo plugin starting with version 2.0.0 uses JaCoCo 0.7.5 and thus requires also this version to be used in your projects. Please stick to JaCoCo plugin 1.0.19 or lower if you still use JaCoCo 0.7.4 or lower

This gradle plugin still uses an old JaCoCo version 0.7.2 as a default. So to improve the compatibility (without having to configure it manually), I updated the version to the latest version '0.7.7.201606060606'. Are there any objections about this change?

Enhancement: Provide configuration option for CI generated instrumented coverage

Currently to add instrumentation coverage reports generated by Firebase Test Lab, I do the following:

tasks.withType(JacocoMerge.class) { task ->
  project.subprojects { subProject ->
    task.executionData += subProject.fileTree(subProject.buildDir).matching {
      include "**/*.ec"
    }
  }
}

This is required as combined report tasks depend on the connected check tasks. It would be nice if this were configurable via the extension.

E.g.

junitJacoco {
  ...
  combinedDependsOnInstrumentation = true // type boolean
}

Execute task "jacocoTestReportMerged" failure on Gradle 5.0

Greate plugin for jacaco support!
Everything is ok when using with jacoco 0.8.2, gradle 4.10.2, jdk8 and this plugin 0.13.0.

After upgrade gradle to 5.0, execute task "jacocoTestReportMerged" has below error info:

FAILURE: Build failed with an exception.

What went wrong:

java.lang.StackOverflowError (no error message)

PS: Task "jacocoTestReport" is ok.

Snapshot build is broken

The last couple of days I keep getting:

"Plugin with id 'com.vanniktech.android.junit.jacoco' not found."

This is how my top level build.gradle file looks like:

buildscript {
ext.kotlin_version = '1.2.41'
ext.gradle_plugin = '3.1.2'
ext.gitflow_plugin = '0.2.0'
ext.android_junit_jacoco_plugin = '0.12.0-SNAPSHOT'
ext.sonar_plugin = '2.6.2'
ext.gradle_git_plugin = '2.2.0'
repositories {
jcenter()
google()
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
}
dependencies {
classpath "com.android.tools.build:gradle:$gradle_plugin"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.github.amkay:gradle-gitflow:$gitflow_plugin"
classpath "com.vanniktech:gradle-android-junit-jacoco-plugin:$android_junit_jacoco_plugin"
classpath "org.sonarsource.scanner.gradle:sonarqube-gradle-plugin:$sonar_plugin"
classpath "org.ajoberstar:grgit:$gradle_git_plugin"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
ext {
// dependencies versions
support = "27.1.1"
googlePlay = "15.0.0"
roomVersion = "1.1.0"
testSupport = "1.0.1"
espresso = "3.0.2"
constraintLayout = "1.1.0"
multidex = "1.0.3"
junit = "4.12"
mockito = "2.18.3"
json = "20171018"
dagger = "2.14.1"
rxjava = "2.1.12"
rxandroid = "2.0.1"
retrofit = "2.3.0"
evernote = "1.2.5"
stetho = "1.5.0"
}

Should I just switch to 0.11.0 release one?

gradlew task for generating combined result is not showing proper result

When I open generated index.html file in build/reports/jacocoCombined directory
It shows combined results fine,
but it shows coverage for all the instrumentation tests 0%
and coverage for JUnit tests is showing correctly.

One more thing is that when I open index.html in build/reports/coverage directory which is generated only for instrumentation tests is showing correct results,

why it is not being shown in the report which is generated for combined results?

Point to be added, includeInstrumentationCoverageInMergedReport is also true

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.