Unit Testing animation results using Robolectric
Robolectric is a great tool to test classes that depend on Android views and classes properly. I use Robolectric heavily to test custom view logic.
I wrote a custom view to mimic TextInputLayout with some added app specific features. I also did the hint to label and label to hint animation in the custom view to mimic this.
So I have a
showLabel() method which animates hint to label text and
hideLabel() method which animates label to text.
So our naive test class for this view would look like this.
As mentioned in the comment, the assertions would fail. Why? Because the show/hide label method implementations doesn’t set the text synchronously. It sets the text only after the animation is over and the animation happens for about 250 milliseconds in our implementation.
So how do we make our assertion calls wait until the animation finishes? Google search with various keywords results in some number of solutions. Let me save you some clicks and list them here.
Mind you, none of these works. I don’t know the exact reason for the first three, but I can tell you why last one won’t work.
Thread.sleep() blocks the main thread, which means our animation is also blocked for 250 milliseconds, and our label/hint won’t be set, hence the assertion would fail, again.
So what is the solution?
We need to add one line to our test class, that is
And after showLabel/hideLabel method call, we should call
Shadows.shadowOf(Looper.getMainLooper()).idle() and assert call should follow. The
idle() call would basically runs all posted tasks in the main looper.
Now our test class becomes like this.
@LooperMode(LooperMode.Mode.PAUSED)for the test class
Shadows.shadowOf(Looper.getMainLooper()).idle()before assertion to run all pending animations