Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't load assets after updating to gradle 2.2.0 #2647

Closed
andymstone opened this issue Sep 20, 2016 · 36 comments
Closed

Can't load assets after updating to gradle 2.2.0 #2647

andymstone opened this issue Sep 20, 2016 · 36 comments

Comments

@andymstone
Copy link

Description

After updating to gradle 2.2.0 the app/build/intermediates directory no longer contains an assets directory (the app still builds and runs correctly so this appears to be a change in how the build process works). This means that Robolectric tests that rely on loading any assets will fail.

Steps to Reproduce

Put a file in app/src/main/assets then try to open the file, e.g.

@Test
public void simpleTest() {
    RuntimeEnvironment.application.getAssets().open("myfile.txt");
}

This works using gradle 2.1.3 and fails with gradle 2.2.0.

Robolectric & Android Version

Robolectric 3.1.2, Android 23

@asos-olivier
Copy link

In case it helps: I am experiencing the same issue but only with the debug variant (release variant is still working fine).

@ivanarellano
Copy link

@andymstone Thank you for the work around. I rolled back to 2.1.3 and went back to 100% passed.

@BrantApps
Copy link

Ditto. Tests work as expected with AS 2.2 and tools 2.1.3.

@powturns
Copy link

May be related to #2581

@digitalbuddha
Copy link

what does you @config look like?

@talenguyen
Copy link

I got the same problem

@hidroh
Copy link
Contributor

hidroh commented Sep 22, 2016

It looks like gradle plugin 2.2.0 no longer copies assets into build/intermediates/bundles/<flavor>/<build_type>/assets that the test runner expects when creating app manifest.

My fix would be to allow fallback to src/main/assets if none of the existing ones exist (assuming it's located there, which is my simple use case, you can of course make the logic more comprehensive for flavor/build type combinations).

private static final String SRC = "src/main";
...
if (FileFsFile.from(BUILD_OUTPUT, "assets").exists()) {
    assets = FileFsFile.from(BUILD_OUTPUT, "assets", flavor, type);
} else if (FileFsFile.from(BUILD_OUTPUT, "bundles", flavor, type, "assets").exists()) {
    assets = FileFsFile.from(BUILD_OUTPUT, "bundles", flavor, type, "assets");
} else {
    assets = FileFsFile.from(SRC, "assets");
}

If you use RobolectricGradleTestRunner with Robolectric 3.0 it's quite a straightforward fix, by creating a custom runner subclassing the existing one, copying the whole logic and appending the fallback logic as above.

@talenguyen
Copy link

I tried @hidroh solution and it worked. Thank you. @hidroh, you should have a PR for this.

@alecplumb
Copy link

I deleted my previous comment about assets working correctly with android gradle plugin 2.2.0 and Gradle 3.1, because it still did not work in some environments. However, after exiting Android Studio, stopping the gradle daemon (./gradlew --stop), and performing a clean build, the assets are copied into the intermediates folder as before and Robolectric tests using assets are working again, both from the command line an in Android Studio.

@otbinary
Copy link

otbinary commented Sep 29, 2016

Adding the following to app/build.gradle does the trick for me:

android.applicationVariants.all { variant ->
    def productFlavor = "${variant.productFlavors[0].name.capitalize()}"
    def buildType = "${variant.buildType.name.capitalize()}"
    tasks["compile${productFlavor}${buildType}UnitTestSources"].dependsOn(tasks["merge${productFlavor}${buildType}Assets"])
}

This creates a dependency for all compile*UnitTestSources Gradle tasks on the corresponding merge*Assets tasks. The merge tasks copy all assets to app/build/intermediates/assets, where Robolectric finds them.

@OndrejMalek
Copy link

OndrejMalek commented Oct 3, 2016

@otbinary thx it works. Just had to edit for projects with no product flavors

applicationVariants.all { variant ->
        def productFlavor = variant.productFlavors[0] != null ? "${variant.productFlavors[0].name.capitalize()}" : ""
        def buildType = "${variant.buildType.name.capitalize()}"
        tasks["compile${productFlavor}${buildType}UnitTestSources"].dependsOn(tasks["merge${productFlavor}${buildType}Assets"])
    }

@bojingo
Copy link

bojingo commented Oct 11, 2016

I used the workaround from @Vouskopes (which worked great!), but was able to successfully remove it after updating to Gradle 2.2.1, which was just released yesterday.

Upgrade to com.android.tools.build:gradle:2.2.1 and this issue could probably be closed.

@asos-davidf
Copy link

@bojingo Unfortunately I can't confirmed that it's fixed. I've tried the Gradle plugin 2.2.1 with both Android Studio 2.2 and 2.2.1, performed full clean each time (including Gradle cache removal) and I've had my Robolectric fail because of the missing assets.

@Vouskopes's fix is still required for me!

@Teka101
Copy link

Teka101 commented Oct 13, 2016

Works for me with Gradle 2.2.1 ! 👍

@eric-labelle
Copy link

@bojingo @Teka101 Make sure to do the clean before.

gradle clean
gradle test

You'll notice 2.2.1 does not fix anything. You probably simply had run generate before which has a dependency on generateAssets task whereas test does not anymore (you can take a look at task dependencies running gradle -m test

@Teka101
Copy link

Teka101 commented Oct 13, 2016

Oups.... you're rights ! 2.2.1 doesn't fix the bug...

viniciussoares added a commit to viniciussoares/ribot-android-boilerplate-kotlin that referenced this issue Oct 20, 2016
After updating to gradle 2.2.0 the app/build/intermediates directory no longer
contains an assets directory (the app still builds and runs correctly so this
appears to be a change in how the build process works).
This means that Robolectric tests that rely on loading any assets will fail.

robolectric/robolectric#2647
@stanmots
Copy link

With com.android.tools.build:gradle:2.2.2 this issue is still here :(

@emartynov
Copy link

I don't think it will be fixed on Google side. They changed their internal implementations, so we should adapt Robolectric functionality.

@ending0421
Copy link

ending0421 commented Nov 1, 2016

Hey @Vouskopes ,i get same issue . But in my case , i meet this issue in a library project and assert files needed are in another aar library which this library have to be dependent on . i've tried adding

applicationVariants.all { variant ->
        def productFlavor = variant.productFlavors[0] != null ? "${variant.productFlavors[0].name.capitalize()}" : ""
        def buildType = "${variant.buildType.name.capitalize()}"
        tasks["compile${productFlavor}${buildType}UnitTestSources"].dependsOn(tasks["merge${productFlavor}${buildType}Assets"])
    }

in build.gradle and changed applicationVariants to andorid.libraryVariants . But i'm still unlucky .
How can i do to fix this issue in my case ?
Thanks a lot .

@xian
Copy link
Member

xian commented Nov 15, 2016

Fixed on master with #2673. Thanks all!

@xian xian closed this as completed Nov 15, 2016
@bojingo
Copy link

bojingo commented Dec 14, 2016

I don't see anything about this having been released. Any idea on when this will be available in the central repositories so we can take advantage of this fix?

@stanmots
Copy link

I'm still having the same issue. Tried to use the latest stable version 3.1.4 and robolectric:3.2-SNAPSHOT.

@hshahdoost
Copy link

@storix it is fixed on 3.1.4, you must be referring to a different problem

@bojingo
Copy link

bojingo commented Jan 6, 2017

This is definitely not fixed with 3.1.4. My custom font (.ttf) file in the asset folder is not found when running Robolectric tests unless I have the fix from @Vouskopes.

Should be re-opened if 3.1.4 was expected to fix it.

@eric-labelle
Copy link

@bojingo 3.1.4 was released before the 2673 issue was merged therefore it is certainly not in this one but should although be in 3.2 that was juste released this week I think! :)

@xian
Copy link
Member

xian commented Jan 6, 2017

Yep, this is fixed with 3.2.

@nico-gonzalez
Copy link

@xian I am using Robolectric 3.2.2, Android Gradle Plugin 2.2.3 and AS 2.2.3 and I still have the issue. The only way to have it working is using the workaround by @otbinary. The weird thing is that locally works fine, but when running on a CI server it fails. Any ideas? Any directions to point me on what to check on the CI server setup?

@xian xian reopened this Feb 21, 2017
@xian xian added this to the tbd milestone Feb 21, 2017
@mohitagrawal
Copy link

I am seeing this issue in 3.3 version as well

@noloman
Copy link

noloman commented Mar 23, 2017

still experiencing the same with 3.2.2 and gradle 2.3.0. The workaround created by @otbinary works meanwhile

@thuytrinh
Copy link

If your build file contains the cross-product combination between flavor dimension and product flavor, this worked for me:

  applicationVariants.all {variant ->
    def flavorName = variant.flavorName.capitalize()
    def buildType = variant.buildType.name.capitalize()
    tasks["compile${flavorName}${buildType}UnitTestSources"]
        .dependsOn(tasks["merge${flavorName}${buildType}Assets"])
  }

@xian
Copy link
Member

xian commented Apr 18, 2017

This is caused by an issue with the Android Gradle plugin, tracked here: https://issuetracker.google.com/issues/37347564

Will keep this open until it's resolved there.

@datrixo
Copy link

datrixo commented May 25, 2017

@nico-gonzalez for some reason the gradle task:

compile$ProductFlavor$BuildTypeUnitTestSources

is not always called (and this one depends on task merge$ProductFlavor$BuildTypeAssets)

The ugly fix could be done by calling manualy this task before running tests:

./gradlew clean
./gradlew :app:compile$ProductFlavor$BuildTypeUnitTestSources
./gradlew test$ProductFlavor$BuildType

of course this solution works only together with this snippet in build.gradle:

android.applicationVariants.all { variant ->
    def productFlavor = variant.productFlavors[0] != null ? "${variant.productFlavors[0].name.capitalize()}" : ""
    def buildType = "${variant.buildType.name.capitalize()}"
    tasks["compile${productFlavor}${buildType}UnitTestSources"].dependsOn(tasks["merge${productFlavor}${buildType}Assets"])
}

@ultrah
Copy link

ultrah commented Jul 3, 2017

This variant of the workaround also works for multiple flavor dimensions:

android.applicationVariants.all { variant ->
    def productFlavor = ""
    variant.productFlavors.each {
        productFlavor += "${it.name.capitalize()}"
    }

    def buildType = "${variant.buildType.name.capitalize()}"
    tasks["compile${productFlavor}${buildType}UnitTestSources"].dependsOn(tasks["merge${productFlavor}${buildType}Assets"])
}

@nikitin-da
Copy link

Shouldn't it be closed? Corresponded ticked is fixed (https://issuetracker.google.com/issues/37347564)

@eduardomoroni
Copy link

eduardomoroni commented Aug 23, 2018

We had an issue after upgrading Gradle version to 4.7, android.applicationVariants seems not to exist anymore, we use libraryVariants. We also had another problem that was fonts files being generated under sdk/build/intermediates/bundles/mobileDebug instead of sdk/build/intermediates/bundles/mobile/debug. So we've added a specific workaround for our MobileDebug variant.
Our application is a multi-flavored app.

android {
  libraryVariants.all { variant ->
    def flavorName = variant.flavorName.capitalize()
    def buildType = variant.buildType.name.capitalize()
    def flavorBuild = "${flavorName}${buildType}"

    if (flavorName == "Mobile") {
      def copyFontsTask

      if (buildType == "Debug") {
        copyFontsTask = tasks["copyFontsToMobileDebug"]
      } else if (buildType == "Release") {
        copyFontsTask = tasks["copyFontsToMobileRelease"]
      }

      tasks["compile${flavorBuild}UnitTestSources"].dependsOn(copyFontsTask)
      copyFontsTask.dependsOn(tasks["merge${flavorBuild}Assets"])
    }
  }
}

task copyFontsToMobileDebug(type: Copy) {
  from 'build/intermediates/bundles/mobileDebug'
  into 'build/intermediates/bundles/mobile/debug'
}

task copyFontsToMobileRelease(type: Copy) {
  from 'build/intermediates/bundles/mobileRelease'
  into 'build/intermediates/bundles/mobile/release'
}

@jongerrish
Copy link
Contributor

GradleRobolectricTestRunner has been removed, instead you can simply use RobolectricTestRunner. You also no longer need to specify @config(constants = ..., manifest = ...)

We've revamped resources in Robolectric 4.0 to process the binary resource files + arsc table produced by aapt and the resource handling code is now much closer to that of the framework. This includes changes to parse the merged manifest using the Android platform code.

Mind giving this a try with 4.0 + binary resources by configuring your gradle.build as follows:-

testImplementation "org.robolectric:robolectric:4.0"

android {
  enableUnitTestBinaryResources=true
  testOptions {
    unitTests {
      includeAndroidResources = true
    }
  }
}

We're doing a big bug scrub and trying to be aggressive about it so apologies if this was closed in error, in which case feel free to reopen.

If this is still an issue an example project with failing test would be most helpful.

@xian xian removed this from the to prioritize milestone Nov 10, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests