Archinamon / android-gradle-aspectj

gradle plug-in adding supports of AspectJ into Android project
Apache License 2.0
365 stars 58 forks source link

Instrumented tests fails when aspectj plugin is applied #93

Open ashj11 opened 5 years ago

ashj11 commented 5 years ago

Preconditions: Application's build.gradle has the aspectj plugin enabled apply plugin: 'com.archinamon.aspectj' Aspects are added to another module( library module ), with the plugin com.archinamon.aspectj-provides applied. This has been configured with includeAspectsFromJar in the app's build.gradle

Problem: When i launch Instrumentation tests my app fails to start due to:

java.lang.ClassNotFoundException: Didn't find class "com.example.MyApp" on path: DexPathList ... Task transformClassesWithAspectjForDebugAndroidTest doesn't get executed correctly, though transformClassesWithAspectjForDebug prints the weaving info correctly.

:transformClassesWithAspectjForDebugAndroidTest
---------- Starting augmentation with AspectJ transformer ----------
Ajc classpath doesn't has needed runtime environment
---------- Exit AspectJ transformer w/o processing ----------

Note that running the application works fine( weaving works too ). Issue is only with Instrumented tests. Though https://github.com/Archinamon/android-gradle-aspectj/issues/72 looks similar, it doesn't provide much insights into the solution. The issue doesn't seem to be related to Java 8.

ashj11 commented 5 years ago

The example project seems to be excluding annotation support for certain dependencies.

androidTestCompile('com.android.support.test:runner:0.5') { exclude module: 'support-annotations' }
androidTestCompile('com.android.support.test:rules:0.5') { exclude module: 'support-annotations' }

I tried doing the same, which didnt help

    androidTestImplementation( "androidx.test:runner:$runner_version" ) {
        exclude module: 'annotation'
    }
    androidTestImplementation( "androidx.test:rules:$runner_version" ) {
        exclude module: 'annotation'
    }

@Archinamon Could you please guide?

Archinamon commented 5 years ago

What version of the gradle dist and android gradle plugin are you trying to apply it with? Do you want to augment androidTest module's code with aj?

ashj11 commented 5 years ago

Thanks for the reply @Archinamon Gradle plugin version that I am using is 3.2.1( com.android.tools.build:gradle:3.2.1 ). And gradle dist is 4.6 ( distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip ). I don't want the androidTest module's code to get augmented. I just want the source files to get augmented. When i run the connected test with aspectj plugin enabled, it fails to find any test class. Fails with No test found. When plugin is disabled, the tests run correctly. Do I need to do any additional configuration to make this work?

Output ( No tests found)

10:13:32 V/InstrumentationResultParser: INSTRUMENTATION_RESULT: stream=
10:13:32 V/InstrumentationResultParser: 
10:13:32 V/InstrumentationResultParser: Time: 0
10:13:32 V/InstrumentationResultParser: 
10:13:32 V/InstrumentationResultParser: OK (0 tests)
10:13:32 V/InstrumentationResultParser: 
10:13:32 V/InstrumentationResultParser: 
10:13:32 V/InstrumentationResultParser: INSTRUMENTATION_CODE: 0
10:13:32 V/InstrumentationResultParser: 
Starting 0 tests on Pixel_XL_API_27_Wifi(AVD) - 8.1.0

transformClassesWithAspectjForDebug seems to be correct.

> Task :transformClassesWithAspectjForDebug
---------- Starting augmentation with AspectJ transformer ----------
include aspects from :: <path>/build/intermediates/intermediate-jars/debug/classes.jar
Weaving in simple mode
Ajc config: -encoding :: , UTF-8, , -source :: , 1.7, , -target :: , 1.7, , -d :: , <path>d/build/intermediates/transforms/aspectj/debug/0, , -bootclasspath :: , <path>/Android/sdk/platforms/android-28/android.jar:<path>/Android/sdk/platforms/android-28/optional/org.apache.http.legacy.jar, , -classpath :: , [ list files ],
, -inpath :: , [ list files ],
, -aspectpath :: , <path>/aspectj-hooks/build/intermediates/intermediate-jars/debug/classes.jar, , -log :: , <path>/build/ajc-transform.log, , -showWeaveInfo :: 
Detailed log in ajc-transform.log
---------- Finish AspectJ transformer ----------
:transformClassesWithAspectjForDebug spend 4771ms
:transformClassesWithAspectjForDebug spend 4771ms

But transformClassesWithAspectjForDebugAndroidTest fails with the below error

> Task :transformClassesWithAspectjForDebugAndroidTest
---------- Starting augmentation with AspectJ transformer ----------
Ajc classpath doesn't has needed runtime environment
---------- Exit AspectJ transformer w/o processing ----------
ashj11 commented 5 years ago

@Archinamon I have created a demo project to show the issue. https://github.com/ashj11/android-aspectj-demo. Could you please have a look and let me know what I am missing?

ashj11 commented 5 years ago

Update: If i use com.archinamon.aspectj-junit instead, the connected tests will get executed correctly, but doesn't seem to use/call the aspect. Also, if i include apply plugin: 'com.google.firebase.firebase-perf', then the main activity itself will not be found. I am really looking forward to finding a solution to these two issues, since including compile time weaving will help us improve our performance reporting mechanism. @Archinamon Could you please suggest ?

ashj11 commented 5 years ago

@Archinamon Any update on this? Aspectj gradle plugin looked really promising for us for performance stats measurement and we would love to use it in our app. We will appreciate any help you can provide.

alex-tiurin commented 5 years ago

I have the same issue "java.lang.ClassNotFoundException: Didn't find class ..." when trying to run instrumentation test. I will really appreciate any solution.

rmatesz commented 5 years ago

I had the same issue and investigated the issue a bit deeper. Somehow aspectjrt can't be found in androidTest related classpath, so therefore the aspectj transformer does nothing with androidTest files (do not even copy them to output folders), so therefore the actual test apk contains no classes at all. I did a quick workaround by modifying AspectjTransform.kt file to always copy unprocessed files to output. Here you can find the patch file with the modification: instrumentation_test_patch.zip

It won't allow you to augment androidTest code, but tests will be executed properly.

alex-tiurin commented 5 years ago

@rmatesz thanks for you reply. it's great to start instrumentation tests but i really need to augment androidTest code. i'm trying to create annotation which will be applied inside androidTest code.

ashj11 commented 5 years ago

Thanks @rmatesz. Finally i got some time to debug this and here is my observation.

Archinamon commented 4 years ago

hasAjRT has been removed. You could try out the 3.4.0 version.

kzsolti commented 4 years ago

We've tried the latest 3.4.3 version, and unfortunately the compilation of the instrumented tests still fails. The logs show:

> Task :app:transformClassesWithAspectjForGoogleDebugAndroidTest FAILED
---------- Starting augmentation with AspectJ transformer ----------
Weaving in simple mode
Ajc config: -encoding :: , UTF-8, , -source :: , 1.8, , -target :: , 1.8, , -d :: , ...\build\intermediates\transforms\aspectj\androidTest\google\debug\0, , -bootclasspath :: , C:\Users\...\AppData\Local\Android\Sdk\platforms\android-28\android.jar;C:\Users\...\AppData\Local\Android\Sdk\platforms\android-28\optional\org.apache.http.legacy.jar, , -classpath :: , [ list files ],
, -inpath :: , [ list files ],
, -log :: , ...\build\ajc-transform.log, , -showWeaveInfo :: , -Xlint:adviceDidNotMatch=error :: 
Detailed log in ajc-transform.log

1 error

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:transformClassesWithAspectjForGoogleDebugAndroidTest'.
> [error] classpath error: unable to find org.aspectj.lang.JoinPoint (check that aspectjrt.jar is in your classpath)
  Look into ...\build\ajc-transform.log file for details

Caused by: org.gradle.api.GradleException: [error] classpath error: unable to find org.aspectj.lang.JoinPoint (check that aspectjrt.jar is in your classpath)
Look into ...\build\ajc-transform.log file for details
    at com.archinamon.api.AspectJWeaver.detectErrors(AspectJWeaver.kt:165)
    at com.archinamon.api.AspectJWeaver.doWeave$android_gradle_aspectj(AspectJWeaver.kt:144)
    at com.archinamon.api.transform.AspectJTransform.transform(AspectJTransform.kt:182)
    at com.android.build.gradle.internal.pipeline.TransformTask$2.call(TransformTask.java:239)
    at com.android.build.gradle.internal.pipeline.TransformTask$2.call(TransformTask.java:235)
    at com.android.builder.profile.ThreadRecorder.record(ThreadRecorder.java:102)
    at com.android.build.gradle.internal.pipeline.TransformTask.transform(TransformTask.java:230)

And the log file contains:

Thu Nov 07 10:26:37 CET 2019
[error] classpath error: unable to find org.aspectj.lang.JoinPoint (check that aspectjrt.jar is in your classpath)

It seems like the transform task actually runs now, however the weaver that is invoked fails nonetheless since the aspectjrt.jar is still not on the classpath.

ashj11 commented 4 years ago

@kzsolti Could you try adding classpath 'org.aspectj:aspectjrt:1.9.5' to your buildscript dependencies section. That seems to fix the issue for me.

ashj11 commented 4 years ago

@kzsolti If you are using Java based aspects, then there can be an issue( https://github.com/Archinamon/android-gradle-aspectj/issues/104 ). If you face this then, try using the version 3.4.0. @Archinamon The current issue https://github.com/Archinamon/android-gradle-aspectj/issues/93 can be closed as resolved( this issue has been resolved for me. can wait for @kzsolti also to confirm if this fixes his issue )

kzsolti commented 4 years ago

@kzsolti Could you try adding classpath 'org.aspectj:aspectjrt:1.9.5' to your buildscript dependencies section. That seems to fix the issue for me.

Hi @ashj11, unfortunately this suggestion does not solve the issue I described. I tried it, but we're still getting the same error.

mrmar096 commented 4 years ago

Update: If i use com.archinamon.aspectj-junit instead, the connected tests will get executed correctly, but doesn't seem to use/call the aspect. Also, if i include apply plugin: 'com.google.firebase.firebase-perf', then the main activity itself will not be found. I am really looking forward to finding a solution to these two issues, since including compile time weaving will help us improve our performance reporting mechanism. @Archinamon Could you please suggest ?

Hi,

This works for me:

You can change the plugin implementation depends on the gradle task executed. So in your build.gradle(app) file add this code after last 'apply plugin...':

if (getGradle().getStartParameter().getTaskRequests().toString().contains("AndroidTest") || getGradle().getStartParameter().getTaskRequests().toString().contains("UnitTest")) {
    apply plugin: 'com.archinamon.aspectj-junit'
    aspectj {
        compileTests = true
    }
} else {
    apply plugin: 'com.archinamon.aspectj'
    aspectj {
        compileTests = false
    }
}
kzsolti commented 3 years ago

Hi folks! Just an update if anyone is still following this thread: We have finally unblocked our project to be able to migrate to Gradle 6, and so we could update to the latest 4.2.1 version of this plugin as well. The androidTest transformation now seems to be fixed with this combination. I've no idea what change in the plugin resolved this issue for us, but we can finally abandon our fork that had a workaround.