Robolectric is an awesome library that makes UI unit test on Android a lot easier and faster. In UI test, one of the most basic thing is to simulate user interaction, such as clicking a button.
Click should be the most basic user interaction, besides invokeing the
View.performClick() method, Robolectric provides a more smarter version
Robolectric.clickOn(View), which checks the view visibility and
enabled status before actually “click” the view. If a view is either not visible or disabled, the click action will not be performed. This mechanism is useful to avoid some silly cases in automated tests.
Long click is a more advanced
click action. To simulate a long click action,
View.performLongClick() can be invoked. But since Robolectric doesn’t provide any long click helper, make sure you do it by yourself, including checking whether view is
long-clickable, which usually will be set manually or more often, when
View.setOnLongClickListener is invoked; view is visible and enabled as what
click does. Although
Long click is avaible to use, but from my experience, long click on a individual view is rarely used in real UI design, instead
long click is usually performed on an item of list view or grid view. This is the trickest case that I’ll leave it to the last.
Click on List View or Grid View item. Well, idally, this shouldn’t be so much different than click on a indiviual view. But in Android implementation, item click is handled by the list view with a much more complicated API. To perform an
boolean performItemClick(View v, int position, long id) can be invoked.
performItemClick requires 3 parameters, the first one is the view being clicked, the second one is the position of clicked view’s corresponding data item in adapter and the last is the if of clicked view’s corresponding data item. Complicated, isn’t it?
In Android implementation, item view displayed in ListView/GridView is actually provided by its adapter. Adapter works like a presenter in MVP pattern that creates/update item view based on the item data it holds. It also provides the id for the item. So to perform a item click, besides the ListView/GridView, you also need its adapter.
Following implementation explains how it works:
In the code,
AbsListView is the base class of
GridView. To click the item, you need
- Get the adapter of the
- Create an
item viewfor specific
- Calculate the
item idof corresponding
performItemClickmethod with data we got before.
In the implementation, for simplicity reason, we ignored some cases, such as convertView reusing. From my experience, in most cases, it won’t impact the functionality, so we don’t need to worry about it, unless you clearly know that matters, then you need to cover them in your tests.
Well, this action is also not a commonly used. It is only used in limited cases, such as selecting multiple item or displaying context menu for specific item.
To perform a long click on the item is the most trickest case. In previous 3 cases, we either directly or indrectly depends on
View.perform***Click method. But not sure why, android doesn’t provide similar public API method of
item long click. By diving into Anrdoid source code, we can figure out that Item Long Click isn’t really handled by ListView itself, instead it is handled by a
CheckForKeyLongPress. To invoke method on this object isn’t that streight forward, and might involes unnecessary multithread issue.
I just want to click a item, why I have to deal with these unnecessary complicates? So I learnt from the
CheckForKeyLongPress implementation, and implmented my own “API”:
My main purpose of perform a click is to trigger the corresponding listener, so I tried to invoke the listener directly with some necessary pre-checks. This aporach will not triggers these UI effects, but I assume it can meet most test cases.