Android JUnit testing of Preferences
A fairly normal scenario: an Android application has a preferences activity, and selecting an option from a ListPreference triggers code to change that ListPreference's summary text. ie: Selecting "Green" from a color ListPreference would change the ListPreference's summary text to "Green" through a onPreferenceChange
callback.
I'd like to be able to use the Android JUnit testing to confirm that these summary changes are all being performed correctly. However, there seems to be very little information out there on how to do this.
I've tried variations of using setValue()
on ListPreference, both in the test thread and through runOnUiThread()
, with no success - this doesn't trigger the call to onPreferenceChange()
. I've also tried getInstrumentation().waitF开发者_如何学JAVAorIdleSync()
after calling setValue()
, but that's also with no success.
So, my question is: how is this done?
Thanks!
A few more hours of work produced this working solution, but I'm curious if anyone else has a better solution. This code was inspired by this solution to a similar question, but this case is different in two ways:
- It's intended for use by Android JUnit, which means it needs to call the ListPreference UI clicks via
runOnUiThread()
. - It expects there to be preference categories in use, which complicate finding the position (relative to the entire preferences list) to click. The above mentioned solution only works in cases without preference categories.
This method will accept the key for a particular ListPreference item, along with the position of the item in the list to be clicked. It will then perform that list item click, and other code would do the checking I'm looking for.
Note that this requires setActivityInitialTouchMode(true);
to be set before the getActivity()
call in the setUp()
method.
private void clickListPreference(String _listPreferenceKey, int _listItemPos){
final String listPreferenceKey = _listPreferenceKey;
final int listItemPos = _listItemPos;
mActivity.runOnUiThread(
new Runnable() {
public void run() {
// get a handle to the particular ListPreference
ListPreference listPreference= (ListPreference) mActivity.findPreference(listPreferenceKey);
// bring up the dialog box
mActivity.getPreferenceScreen().onItemClick( null, null, getPreferencePosition(), 0 );
// click the requested item
AlertDialog listDialog = (AlertDialog) listPreference.getDialog();
ListView listView = listDialog.getListView();
listView.performItemClick(listView, listItemPos, 0);
}
/***
* Finding a ListPreference is difficult when Preference Categories are involved,
* as the category header itself counts as a position in the preferences screen
* list.
*
* This method iterates over the preference items inside preference categories
* to find the ListPreference that is wanted.
*
* @return The position of the ListPreference relative to the entire preferences screen list
*/
private int getPreferencePosition(){
int counter = 0;
PreferenceScreen screen = mActivity.getPreferenceScreen();
// loop over categories
for (int i = 0; i < screen.getPreferenceCount(); i++){
PreferenceCategory cat = (PreferenceCategory) screen.getPreference(i);
counter++;
// loop over category items
for (int j = 0; j < cat.getPreferenceCount(); j++){
if (cat.getPreference(j).getKey().contentEquals(listPreferenceKey)){
return counter;
}
counter++;
}
}
return 0; // did not match
}
}
);
getInstrumentation().waitForIdleSync();
}
精彩评论