Navigation Menu

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

how to force opt out the leakCanary in the test with LeakCanary 2? #1552

Closed
lannyf77 opened this issue Aug 26, 2019 · 13 comments · Fixed by #1618
Closed

how to force opt out the leakCanary in the test with LeakCanary 2? #1552

lannyf77 opened this issue Aug 26, 2019 · 13 comments · Fixed by #1618

Comments

@lannyf77
Copy link

https://square.github.io/leakcanary/upgrading-to-leakcanary-2.0/
says now it does not have leakcanary-android-no-op but only:

dependencies {
  debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.0-beta-3'
}

in our app with 1.6.3 we have

//leakcanary
deps.leakcanary = "com.squareup.leakcanary:leakcanary-android:1.6.3"
deps.leakcanary_no_op = "com.squareup.leakcanary:leakcanary-android-no-op:1.6.3"

and would like to not run leakCanary in the test

configurations.all { config ->
   
    // Ensure the no-op dependency is always used in JVM tests.
    if (config.name.contains('UnitTest') || config.name.contains('AndroidTest')) {
        config.resolutionStrategy.eachDependency { details ->
            if (details.requested.group == 'com.squareup.leakcanary' && details.requested.name == 'leakcanary-android') {
                details.useTarget(group: details.requested.group, name: 'leakcanary-android-no-op', version: details.requested.version)
            }
        }
    }
}
dependencies {
    debugImplementation deps.leakcanary
    releaseImplementation deps.leakcanary_no_op
    testImplementation(deps.leakcanary_no_op) {
        force = true
    }
    androidTestImplementation(deps.leakcanary_no_op) {
        force = true
    }
}

now with LeakCanary 2, how to force opt out the leakCanary for the test?

@pyricau
Copy link
Member

pyricau commented Aug 27, 2019

@lannyf77
Copy link
Author

I guess you mean in the test code to call AppWatcher.config = AppWatcher.config.copy(enabled = false). It should work as long as the build is a debug build if the dependency is added as

dependencies {
  // debugImplementation because LeakCanary should only run in debug builds.
  debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.0-beta-3'
}

is there a way to do it in gradle for disabling leakCanary for all tests?

@pyricau
Copy link
Member

pyricau commented Aug 30, 2019

LeakCanary automatically disable itself if it detects the androidx.test.platform.app.InstrumentationRegistry class in the classpath (ie there's the AndroidX Espresso in the classpath, so I'm assuming you're not using that. You could run LeakCanary.config = LeakCanary.config.copy(dumpHeap = false) from within your test application class and that should disable leakcanary heap dumping.

As you pasted above, you maybe be able to remove the dependency from the config:

configurations.all { config ->
   
    // Ensure the no-op dependency is always used in JVM tests.
    if (config.name.contains('UnitTest') || config.name.contains('AndroidTest')) {
        config.resolutionStrategy.eachDependency { details ->
            if (details.requested.group == 'com.squareup.leakcanary') {
               // TODO Remove the dependency
               // Is there a way to do that?
            }
        }
    }
}

@sahil2441
Copy link
Contributor

As @pyricau mentioned above, leakcanary disabled heapdump automatically when it detects instrumentation.

Further, the only way to find leaks is by explicitly attaching a listener to the instrumentation process, which could be done by adding :
-e listener leakcanary.FailTestOnLeakRunListener to the adb shell command, which I assume you are not doing.

@lannyf77 Not sure what exactly you're looking for, could you elaborate ?

@lannyf77
Copy link
Author

lannyf77 commented Sep 4, 2019

We would like to disable leakcanary for all tests, and it could be done previously with the leakcanary-android-no-op.

Currently I have to put in different implementation of something like below within different build flavor:

for release:

object LeakCanaryObjectWatcher {
    fun watch(watchedObject: Any) {
        // NO-OP
    }
    fun enableLeakCanary(enable: Boolean = true) {
        // NO-OP
    }
}

for debug:

object LeakCanaryObjectWatcher {
    fun watch(watchedObject: Any) {
        AppWatcher.objectWatcher.watch(watchedObject)
    }

    fun enableLeakCanary(enable: Boolean = true) {
        AppWatcher.config = AppWatcher.config.copy(enabled = enable)
    }
}

and in the test, do something like:

override fun beforeActivityLaunched() {
            LeakCanaryObjectWatcher.enableLeakCanary(false)
        }

@pyricau
Copy link
Member

pyricau commented Sep 5, 2019

@lannyf77 can you confirm that you're running tests directly on Android devices, however you are not using espresso? What's the purpose of said tests?

@lannyf77
Copy link
Author

@pyricau we do run test on real devices and with espresso, also for several submodules they have tests without ui such as for database; data model; middle tier etc. We would like to be able to run some flavor of test without leakCanary running.

@pyricau
Copy link
Member

pyricau commented Nov 13, 2019

Suggestion from @vRallev (based on our codebase) : we could look for "org.junit.Test" and disable leakcanary when found.

@tasomaniac
Copy link

tasomaniac commented Nov 13, 2019

As a user you can do this and it is fairly easy (plus it's useful for many things)

android {
  defaultConfig {
    testBuildType "espresso"
  }
  buildTypes {
    espresso.initWith(debug)
  }
}

And then add leak canary to only debug builds. Your Espresso build will not even have Leak Canary to begin with.

@pyricau
Copy link
Member

pyricau commented Nov 14, 2019

Thanks 🙏 . That's useful for people finding this issue. That being said, I want to automate this if possible so that LeakCanary keeps a minimal config and no one has to run into this.

pyricau added a commit that referenced this issue Nov 14, 2019
@pyricau pyricau added this to the 2.0 Next Release milestone Nov 14, 2019
pyricau added a commit that referenced this issue Nov 14, 2019
@hichamboushaba
Copy link

hichamboushaba commented Jun 29, 2022

I know this is an old issue and the fix is good for making sure the heap dump and analysis are not being executed on test builds.
But there is still another issue: having LeakCanary AppWatcher installed on test builds has another side effect, as the ServiceWatcher swaps the instance of IActivityManager with a new proxy instance, this causes an issue with Fastlane's screengrab, as it relies on reflection to access the IActivityManager instance to handle Locale switching, this is the cause of this issue (at least it's for us, as there may be other libraries that cause it too).
To solve this, currently, we are switching to the leakcanary-android-core artifact, and handling LeakCanary's initialization manually (@tasomaniac's solution above would work too).

@pyricau do you think it makes sense to add the tests detection logic to MainProcessAppWatcherInstaller as well?

@pyricau
Copy link
Member

pyricau commented Jul 8, 2022

@hichamboushaba can you file a new issue with these details and a link to this issue?

@hichamboushaba
Copy link

@pyricau done #2400

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

Successfully merging a pull request may close this issue.

5 participants