Giter Site home page Giter Site logo

android-gradle-java-app-template's Introduction

android-gradle-java-app-template's People

Contributors

dependabot[bot] avatar jaredsburrows 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

android-gradle-java-app-template's Issues

Clean build: Unsupported major.minor version 52.0

Hi,

I'm getting the following gradle error:

Execution failed for task ':test-lib:compileReleaseJavaWithJavac'.

javax/tools/DiagnosticListener : Unsupported major.minor version 52.0

I'm using java 7. It's set both in grade and in the project settings for Android Studio.
Do you have any ideas? version 52 is Java 8. Thanks

Robolectric + PowerMock

Hi,

Thanks for all the work you've put into this. It's highly appreciated.

I'm trying to run tests that use Robolectric and PowerMock. But I'm getting the following issue when using the "PowerMockRule" method.

Caused by: java.lang.IllegalStateException: PowerMockRule can only be used with the system classloader but was loaded by org.robolectric.internal.bytecode.InstrumentingClassLoader@2f21a0e5

Do you have any ideas? I've tried setting the suggestions by robolectric.

If I use @RunWith(RobolectricGradleTestRunner.class) I cannot test static methods, which is what I need.

Thanks!

Add modules for different setups

Current setups:

  • Example-AllLibraries - Everything
  • Example-Robolectric - Robolectric + JUnit 4 + Hamcrest
  • Example-RobolectricFlavors - Basic flavors
  • Robolectric + Mockito
  • Robolectric + EasyMock/PowerMock

Possible setups:

  • Robolectric + Espresso

[Contribute] Enable Mocked classes for Unit Tests

This code allows to embed own implementations of classes into mockable android JAR. In my case I embed: Log & SparseArray classes.

What script do:

  1. register patchMockableAndroidJar task as finalizer of the mockableAndroidJar
  2. patch all testing tasks classpath - include our version of mockable android instead of original
  3. copy test resources into folder where unit tests can find them during execution
  4. three tasks needed for that: copyMockableAndroidJar, patchMockableAndroidJar, copy${flavor}${buildType}TestResources
/* [ UNIT TESTING ] ================================================================================================= */

afterEvaluate {
  /* Adjust Mockable Android task  */
  tasks.matching { it.name.startsWith('mockableAndroidJar') }.each { mock ->
    // http://goo.gl/wXhBIF --> MockableJarGenerator.java
    mock.finalizedBy patchMockableAndroidJar
  }
  /* Patch classpath of the test tasks for using our own version of the mockable JAR */
  tasks.matching { it.name.startsWith("test") }.each { t ->
    def old = "mockable-android-${androidTargetSdkVersion}.jar"
    def mock = "${project.buildDir}\\intermediates\\patched-mockable-android-${androidTargetSdkVersion}.jar"

    try {
      t.classpath = files(t.classpath.files, mock).filter { it.name != old }
    } catch (final Throwable ignored) {
      // ignore task
    }
  }
  /* Include resources. See: https://code.google.com/p/android/issues/detail?id=64887#c13 */
  project.android.productFlavors.each { f ->
    project.android.buildTypes.each { b ->
      /** compose dynamic tasks */
      def tName = "copy${f.name.capitalize()}${b.name.capitalize()}TestResources"
      project.task(tName, type: Copy) {
        description = "Make resources available for test: test${f.name.capitalize()}${b.name.capitalize()}."
        group = 'Unit Testing'

        from project.android.sourceSets["test"].resources.srcDirs
        into "${project.buildDir}/intermediates/classes/test/${f.name}/${b.name}"
      }

      tasks.matching { it.name.equalsIgnoreCase("test${f.name}${b.name}") }.each {
        it.dependsOn tName
      }
    }
  }
}

/* Create a copy of original mockable Jar */
task copyMockableAndroidJar(type: Copy) {
  description = 'Create backup copy of mockable-android-${api}.jar file'
  group = 'Unit Testing'

  // incremental build support
  inputs.property "api", androidTargetSdkVersion
  outputs.files "mockable-android-${androidTargetSdkVersion}-original.jar"

  from "${project.buildDir}/intermediates/mockable-android-${androidTargetSdkVersion}.jar"
  into "${project.buildDir}/intermediates/"

  rename { String fileName ->
    fileName.replace("mockable-android-${androidTargetSdkVersion}.jar",
        "mockable-android-${androidTargetSdkVersion}-original.jar")
  }
}

/* Exclude classes that we want to replace by own implementation  */
task patchMockableAndroidJar(type: Zip, dependsOn: copyMockableAndroidJar) {
  description = 'patch mockable-android-${api}.jar by own classes'
  group = 'Unit Testing'

  // set archive name and destination
  entryCompression = ZipEntryCompression.STORED  // speedup task by excluding compression
  destinationDir = file("${project.buildDir}/intermediates")
  archiveName = "patched-mockable-android-${androidTargetSdkVersion}.jar"
  def source = "${project.buildDir}/intermediates/mockable-android-${androidTargetSdkVersion}-original.jar"

  // exclude from Mocks Jar classes which we replace by own implementation
  from(zipTree(source)) {
    exclude '**/android/util/SparseArray.class'
    exclude '**/android/util/Log.class'
  }
}

Getting 'OutOfMemoryError' from 'test-lib' project when running androidTest task

I'm not 100% sure what's happening here. I get the following message when building from Gradle 2.10 without the wrapper. You can see the desired task was 'connectedDebugAndroidTest' and I wouldn't think that the 'test-lib' project should have anything that needs running in this case.

I found this in the unmodified project while trying to track down a similar error in a project that I modeled after the template.

UNEXPECTED TOP-LEVEL ERROR:
java.lang.OutOfMemoryError: GC overhead limit exceeded
at java.util.regex.Pattern$BnM.optimize(Pattern.java:5408)
at java.util.regex.Pattern.compile(Pattern.java:1709)
at java.util.regex.Pattern.(Pattern.java:1351)
at java.util.regex.Pattern.compile(Pattern.java:1054)
at java.lang.String.replace(String.java:2226)
at com.android.dx.cf.direct.ClassPathOpener.compareClassNames(ClassPathOpener.java:197)
at com.android.dx.cf.direct.ClassPathOpener.access$000(ClassPathOpener.java:37)
at com.android.dx.cf.direct.ClassPathOpener$3.compare(ClassPathOpener.java:252)
at com.android.dx.cf.direct.ClassPathOpener$3.compare(ClassPathOpener.java:250)
at java.util.TimSort.countRunAndMakeAscending(TimSort.java:356)
at java.util.TimSort.sort(TimSort.java:230)
at java.util.Arrays.sort(Arrays.java:1435)
at java.util.Collections.sort(Collections.java:230)
at com.android.dx.cf.direct.ClassPathOpener.processArchive(ClassPathOpener.java:250)
at com.android.dx.cf.direct.ClassPathOpener.processOne(ClassPathOpener.java:166)
at com.android.dx.cf.direct.ClassPathOpener.process(ClassPathOpener.java:144)
at com.android.dx.command.dexer.Main.processOne(Main.java:672)
at com.android.dx.command.dexer.Main.processAllFiles(Main.java:574)
at com.android.dx.command.dexer.Main.runMonoDex(Main.java:311)
at com.android.dx.command.dexer.Main.run(Main.java:277)
at com.android.dx.command.dexer.Main.main(Main.java:245)
at com.android.dx.command.Main.main(Main.java:106)

:test-lib:transformClassesWithDexForDebugAndroidTest FAILED

FAILURE: Build failed with an exception.

Within the top level 'build.gradle' file, you have the following line:
.....
dependencies {
// testing
if (name.contains('test'))
.....

Is this supposed to match on ALL tests or just the unit test task?

Thanks, DD

Not able to run Espresso test case

Hi Jared,

I tried running test case to understand Espresso but came across below 2 issues , please review and clarify.

Issue 1:

./gradlew connectedAndroidTest

Got below error

AndroidGradleTemplate/app/all-libraries/src/androidTest/java/burrows/apps/example/template/instrumentation/MainActivityTest.java:20: warning: [deprecation] ActivityInstrumentationTestCase2(String,Class) in ActivityInstrumentationTestCase2 has been deprecated
super("burrows.apps.example.template", MainActivity.class);
^
where T is a type-variable:
T extends Activity declared in class ActivityInstrumentationTestCase2
error: warnings found and -Werror specified
1 error
1 warning
:app:all-libraries:compileDebugAndroidTestJavaWithJavac FAILED

Issue 2:

Right click an instrumentation test located in src/main/androidTest and click test

This path is wrong , README needs updation

Thanks & Regards,
Vikram

[Contribute] Static code analysis

Lint + TestResults + Jacoco

What script do:

  1. create a new groups of tasks Reporting and Reporting routine
  2. register global/aggregating tasks - checkOPenResults, lintOpenResults, testOpenResults, jacocoOpenResults
  3. create a set of tasks for each flavor, those tasks can be used for getting reports of the specific flavor

Script expect several things:

  1. declaration of several global properties: ENABLE_QUALITY, useTesting, useJacoco
  2. script uses external bash script for executing reports opening in web browser open-test-results.sh
// tools: Code Analysis Tools

import org.apache.tools.ant.taskdefs.condition.Os

buildscript {
  repositories {
    jcenter()
    mavenLocal()
    mavenCentral()
  }
  dependencies {
    // https://github.com/aaschmid/gradle-cpd-plugin
    classpath 'de.aaschmid.gradle.plugins:gradle-cpd-plugin:+'
  }
}

task checkOpenResults(dependsOn: ['check']) {
  description = 'Open reports of ALL attached Quality Tools in Web browser'
  group = 'Reporting'

  // do nothing, it used for dependency graph building only
}

if (ENABLE_QUALITY) {
  /* [ LINT ] ===================================================================================================== */
  task lintOpenResults(dependsOn: ['lint']) {
    description = 'Open all reports for all flavors and build configurations.'
    group = 'Reporting'
  }
  checkOpenResults.dependsOn lintOpenResults
  afterEvaluate { iterateVariants(this.&createLintOpenResultsTask) }
}

/* [ UNIT Test Results ] ======================================================================================== */
if (ENABLE_QUALITY && useTesting) {
  task testOpenResults(dependsOn: ['test']) {
    description = 'Open all Unit Tests results  for all flavors and build types.'
    group = 'Reporting'
  }
  checkOpenResults.dependsOn testOpenResults
  afterEvaluate { iterateVariants(this.&createTestOpenResultsTask) }
}

/* [ JACOCO coverage ] ========================================================================================== */
if (ENABLE_QUALITY && useTesting && useJacoco) {
  // Helpers:
  //  http://forums.gradle.org/gradle/topics/gradle_1_6_jacoco_in_multi_module_build
  //  http://goo.gl/1ZrSl0 --> JacocoPlugin.groovy
  //  http://goo.gl/0pkjse --> JacocoReportTask.groovy

  task jacocoOpenResults(dependsOn: ['test']) {
    // Task opens report file in default web-browser
    description = 'open Code Coverage for Unit Tests in web browser'
    group = 'Reporting'
  }
  checkOpenResults.dependsOn jacocoOpenResults
  afterEvaluate { iterateVariants(this.&createJacocoOpenResultsTask) }
}

/* [ HELPERS ] ====================================================================================================== */

def adoptToOs(String path) {
  if (Os.isFamily(Os.FAMILY_WINDOWS)) { // windows
    path = path.replace("/", "\\")
  } else if (Os.isFamily(Os.FAMILY_UNIX)) { // linux
    path = path.replace("\\", "/")
  } else if (Os.isFamily(Os.FAMILY_MAC)) { // mac os
    path = path.replace("\\", "/")
  }

  return path;
}

def openExternalBrowser(String path) {
  if (Os.isFamily(Os.FAMILY_WINDOWS)) { // windows
    return ['cmd.exe', '/C', path]
  } else if (Os.isFamily(Os.FAMILY_UNIX)) { // linux
    return ["${rootProject.rootDir}/gradle/open-test-results.sh", path]
  } else if (Os.isFamily(Os.FAMILY_MAC)) { // mac os
    // TODO: implement me
    return ['']
  }
}

def iterateVariants(func) {
  if (project.android.productFlavors.size() > 0) {
    project.android.productFlavors.each { f ->
      iterateBuildTypes(f.name, func)
    }
  } else {
    iterateBuildTypes('', func)
  }
}

def iterateBuildTypes(String flavor, func) {
  project.android.buildTypes.each { b ->
    func(flavor, b.name);
  }
}

/* [ TASKS CREATORS ] =============================================================================================== */

def createLintOpenResultsTask(String f, String b) {
  def flavor = f.capitalize()
  def buildType = b.capitalize()
  def taskName = "openLintReport${flavor}${buildType}"

  project.task(taskName, type: Exec, dependsOn: ["lint${flavor}${buildType}"]) {
    description = "open lint${flavor}${buildType} results in current web browser."
    group = 'Reporting Routine'

    ignoreExitValue true // task is not critical, ignore it failure

    // path is relative to current project path: {project}\\samples\\sample-01
    // file:/C:/Android/_projects_/meter/samples/sample-01/build/outputs/lint-results.html
    def lintFile = "lint-results-${flavor}${buildType}-fatal.html"
    def path = """${project.buildDir}\\outputs\\${lintFile}"""

    project.logger.info("  report: ${adoptToOs(path)}")
    commandLine openExternalBrowser(adoptToOs(path))
  }

  lintOpenResults.dependsOn taskName
}

def createTestOpenResultsTask(String f, String b) {
  def flavor = f.capitalize()
  def buildType = b.capitalize()
  def taskName = "openTestReport${flavor}${buildType}"

  project.task(taskName, type: Exec, dependsOn: ["test${flavor}${buildType}"]) {
    // Task opens report file in default web-browser
    description = 'open Unit Tests results in current web browser'
    group = 'Reporting Routine'

    ignoreExitValue true // task is not critical, ignore it failure

    // path is relative to current project path: {project}\\samples\\sample-01
    // file:///C:/Android/_projects_/meter/library/build/reports/tests/index.html
    def path = """${project.buildDir}\\reports\\tests\\${flavor}${buildType}\\index.html"""

    project.logger.info("  report: ${adoptToOs(path)}")
    commandLine openExternalBrowser(adoptToOs(path))
  }

  testOpenResults.dependsOn taskName
}

def createJacocoOpenResultsTask(String f, String b) {
  def flavor = f.capitalize()
  def buildType = b.capitalize()
  def taskName = "generateJacocoReport${flavor}${buildType}"

  project.task(taskName, type: JacocoReport, dependsOn: ["test${flavor}${buildType}"]) {
    description = 'Generates Jacoco coverage reports: XML and HTML'
    group = 'Reporting Routine'

    // use hidden configuration, for details look into JacocoPlugin.groovy
    jacocoClasspath = project.configurations['androidJacocoAnt']

    // exclude auto-generated classes and tests
    def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*', '**/Mock*.*']
    def testsTree = fileTree(dir: "${project.buildDir}/intermediates/classes/test/${flavor}/${buildType}", excludes: fileFilter)
    def flavorTree = fileTree(dir: "${project.buildDir}/intermediates/classes/${flavor}/${buildType}", excludes: fileFilter)

    // sources
    def testsSrc = "${project.projectDir}/src/test/java"
    def testsFlavorSrc = "${project.projectDir}/src/test${flavor}/java"
    def testsBuildSrc = "${project.projectDir}/src/test${buildType}/java"
    def testsVariantSrc = "${project.projectDir}/src/test${flavor}${buildType}/java"
    def mainSrc = "${project.projectDir}/src/main/java"

    // TODO: confirm order of the src dirs
    sourceDirectories = files([testsSrc, testsFlavorSrc, testsBuildSrc, testsVariantSrc, mainSrc])
    classDirectories = files([testsTree, flavorTree])
    executionData = fileTree(dir: project.projectDir, includes: ['**/*.exec', '**/*.ec'])

    reports {
      xml {
        enabled = true
        destination = "${project.buildDir}/reports/jacoco/${flavor}/${buildType}/jacoco.xml"
      }
      csv.enabled false
      html {
        enabled = true
        destination = "${project.buildDir}/reports/jacoco/${flavor}/${buildType}"
      }
    }
  }

  def taskName2 = "openJacocoReport${flavor}${buildType}"
  project.task(taskName2, type: Exec, dependsOn: [taskName]) {
    // Task opens report file in default web-browser
    description = 'open Code Coverage for Unit Tests in web browser'
    group = 'Reporting Routine'

    ignoreExitValue true // task is not critical, ignore it failure

    def path = """${project.buildDir}/reports/jacoco/${flavor}/${buildType}/index.html"""

    rootProject.logger.info('  report: ' + path)
    commandLine openExternalBrowser(adoptToOs(path))
  }

  jacocoOpenResults.dependsOn taskName2
}
#!/bin/bash

## http://www.gnu.org/software/bash/manual/bashref.html
## http://stackoverflow.com/questions/3124556/clean-way-to-launch-the-web-browser-from-shell-script
## http://askubuntu.com/questions/8252/how-to-launch-default-web-browser-from-the-terminal

executor=gnome-open
type gnome-open >/dev/null 2>&1 || {
    echo >&2 "gnome-open not installed.";
    executor=sensible-browser
    type sensible-browser >/dev/null 2>&1 || {
        echo >&2 "sensible-browser not installed."
        executor=x-www-browser
        type x-www-browser >/dev/null 2>&1 || {
            echo >&2 "x-www-browser not installed.";
            executor=xdg-open
            type xdg-open >/dev/null 2>&1 || {
                echo >&2 "xdg-open not installed. Aborting.";
                exit 1;
            }
        }
    }
}

URL=$1
echo "Found executor: $executor"

# run in background
exec "$executor" "$URL" &

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.