androidjunitandroid-testingrobolectric

Robolectric tests memory creep and inability to close the scenario


Some background:

When I run the tests I get a lot memory creep. I've seen suggestions to call close on the activity/fragment scenario. I've tried applying that to all my tests. For some tests, that works without a problem, for others that puts things into a bad state. Running the tests one at time works. Running all the tests in the class, the first test works, others fail to start the ui. If I don't close the scenario, they are fine. I've been pulling my hair out. Today I made a spreadsheet listing each class and various things I thought might be the cause the problem.

Some shared state? That would seem like the obvious (and maybe its the answer at some level). The spreadsheet revealed something interesting. The compose screens don't have the problem. There was just one instance of a compose screen that had the problem, then I realized while that screen was compose, that test was testing the overflow menu and that is layouts.

I have one screen that has the problem that's quite simple. Its viewModel just has a settings class, a coroutine dispatcher, and the saved state handle (note the layout itself is fairly complex, the viewModel and its logic are simple).

I really thought the issue was something that was injected into the viewModel that had shared state. I've replace the setting with a fake. That didn't help. I've played with the dispatcher I inject (and later realize that are exactly the same on the tests that don't have the problem). On the fake settings, and I added something to clear them between tests.

Some of screens that have the problem are just begging to be converted to compose. The danger of that is remove some of the simpler cases that have the problem.

So I know it happens with layouts and not compose. And some very simple layouts exhibit the problem. Most of layouts have the problem, a few do not. Some that have the issue are quite simple, others are fairly complicated. I don't see any pattern to the layout based views that exhibit the issue.


Solution

  • Some of my assumptions were incorrect. The tests were slowing down, but the culprit wasn't memory creep, but an issue with Robolectic and Compose.

    https://github.com/robolectric/robolectric/issues/9043

    In the end, creating a junit rule that resets the AndroidUIDispatcher's Choreographer solved the issue.

    Here's a gist for junit rule: https://gist.github.com/johngray1965/24d7a3f1e5ae5f0fc1adc24444fe12ac

    Note: it was very important that the rule runs before the compose rule (otherwise the compose rule may fail).