Skip to content

Instrumented tests fails when aspectj plugin is applied #93

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

Open
ashj11 opened this issue Apr 3, 2019 · 17 comments
Open

Instrumented tests fails when aspectj plugin is applied #93

ashj11 opened this issue Apr 3, 2019 · 17 comments

Comments

@ashj11
Copy link

ashj11 commented Apr 3, 2019

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 #72 looks similar, it doesn't provide much insights into the solution. The issue doesn't seem to be related to Java 8.

@ashj11
Copy link
Author

ashj11 commented Apr 4, 2019

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
Copy link
Owner

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
Copy link
Author

ashj11 commented Apr 9, 2019

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
Copy link
Author

ashj11 commented May 4, 2019

@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
Copy link
Author

ashj11 commented May 5, 2019

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
Copy link
Author

ashj11 commented May 21, 2019

@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
Copy link

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
Copy link

rmatesz commented May 27, 2019

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
Copy link

@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
Copy link
Author

ashj11 commented Aug 2, 2019

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

  • In AspectJTransform.kt, we are checking for aspectj runtime by checking for the existence of the jar by name.
    There are two cases in this.
  1. In the case of certain plugins like Firebase, they do operate on the jars and provide the extracted class files are input for the next transformation. In this case, though the aspectjrt class files are present in the path, the above check will fail.
  2. In the case of android integration tests, the aspectj runtime doesn't seem to be explicitly passed( not sure why ). But if i bypass the check and still allow it to weave, the weaving seems to be happening just fine. And the test passes.
  3. Even if we remove the hasAjRT check, If the aspectjrt is not genuinely present, then weaving fails with a very clear message to check for aspectrt.jar in the classpath, which seems to be good enough.
    @Archinamon given point 3, was there any strong reason for adding the jar presence check? If not, can we remove it.
    Removing aspectjrt check #97

@Archinamon
Copy link
Owner

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

@kzsolti
Copy link

kzsolti commented Nov 7, 2019

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
Copy link
Author

ashj11 commented Feb 12, 2020

@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
Copy link
Author

ashj11 commented Feb 12, 2020

@kzsolti If you are using Java based aspects, then there can be an issue( #104 ). If you face this then, try using the version 3.4.0.
@Archinamon The current issue #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
Copy link

kzsolti commented Feb 17, 2020

@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
Copy link

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
Copy link

kzsolti commented Oct 12, 2020

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants