Skip to content

Instantly share code, notes, and snippets.

@lordcodes
Last active November 2, 2015 21:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lordcodes/55801438a960ebbc2b2e to your computer and use it in GitHub Desktop.
Save lordcodes/55801438a960ebbc2b2e to your computer and use it in GitHub Desktop.
Gradle code to fix issue in Robolectric when running tests on a library project. Based on an answer here (https://github.com/robolectric/robolectric/issues/1796), but altered to store the libraries in the build directory and to pull the package name from your build variants
import static groovy.io.FileType.FILES
// This task discovers the manifest files for the .aars that we depend on and
// adds them to project.ext.manifestFiles for use in later tasks.
task discoverManifestFiles(dependsOn: 'prepareDebugDependencies') << {
def aars = new File(project.buildDir.absolutePath + "/intermediates/exploded-aar")
def manifestFiles = new ArrayList<File>()
// Iterate through the exploded-aars directory, finding the manifests
aars.eachFileRecurse(FILES) {
if (it.name.endsWith('AndroidManifest.xml') && !it.absolutePath.contains('aapt')) {
manifestFiles.add(it)
}
}
project.ext.manifestFiles = manifestFiles;
}
// After gradle's done compiling the code, it'll run this to add some more tasks for us.
afterEvaluate { project ->
// Debug and release get their own tasks
android.libraryVariants.each { variant ->
def myPackageNamespace = variant.applicationId
def myPackagePath = myPackageNamespace.replaceAll("\\.", "/")
def processedPackages = new ArrayList<String>()
// Task one of two that we're adding: it depends on discovering manifest files
// and on processing resources for this build variant. It copies the merged R.java file
// from our project's namespace (which contains the resource IDs included in our
// dependencies) and drops it into each of our dependencies' namespaces. This is to work
// around limitations in robolectric.
def copyRJavaTaskName = "copy${variant.name.capitalize()}RJavaForRobolectric"
task(copyRJavaTaskName,
dependsOn: ["process${variant.name.capitalize()}Resources", "discoverManifestFiles"]) << {
// For each manifest file we discovered earlier, open it up an pull out the package
project.ext.manifestFiles.each {
def parsedManifestRoot = (new XmlParser()).parse(it.absolutePath)
def targetPackageNamespace = parsedManifestRoot.@package
// If it was already added, skip it
if(!processedPackages.contains(targetPackageNamespace)){
processedPackages.add(targetPackageNamespace)
} else {
println "WARNING: Found two versions of $targetPackageNamespace; this could mess" +
" with your assets and resources"
// For some reason there are two versions of this dependency
// so skip additional iterations
return
}
def targetPackageNamespacePath = targetPackageNamespace.replaceAll("\\.", "/")
// Copy R.java from our outputs into the namespace of each dependency
// (and change the package line in the file, correspondingly)
copy {
from "build/generated/source/r/${variant.name}/$myPackagePath"
include 'R.java'
into "build/generated/source/r/${variant.name}/$targetPackageNamespacePath"
filter { line -> line.contains("package ${myPackageNamespace};") ? "package ${targetPackageNamespace};" : line }
}
}
}
// Insert this new task into the task tree: compiling unit tests depends on it.
tasks.getByName("compile${variant.name.capitalize()}UnitTestJavaWithJavac") dependsOn copyRJavaTaskName
// Second task we're adding: copy lib assets into the place where robolectric expects them.
// It depends on processing this variant's resources and on discovering manifest files.
def copyAssetsTaskName = "copy${variant.name.capitalize()}AssetsForRobolectric"
task(copyAssetsTaskName,
dependsOn: ["process${variant.name.capitalize()}Resources", "discoverManifestFiles"]) << {
// For each manifest file we discovered, find that project's assets folder and copy it
// to the same merged destination dir
project.ext.manifestFiles.each {
def manifestDirectory = it.parent
def src = "${manifestDirectory}/assets"
def dest = "build/intermediates/bundles/${variant.name}/assets"
copy {
from src
include '**/*'
into dest
}
}
}
// Insert this new task into the task tree: executing unit tests depends on it.
tasks.getByName("test${variant.name.capitalize()}UnitTest") dependsOn copyAssetsTaskName
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment