Для решения этой проблемы я использую logcat ОС.Я проверяю части кода, которые тестируются, с помощью сообщений трассировки и жду, пока они появятся в тестовом коде.Это, пожалуй, не самый эффективный способ ведения дел, но он соответствует моим потребностям.Сначала я попытался создать асинхронную задачу, которая читала бы из logcat, но столкнулась с проблемами синхронизации.Наконец-то я реализовал что-то вроде этого:
logger.info("Click on something");
EmSingleton.get().setCheckPoint();
solo.clickOnText(SOMETHING, 1, true); // writes RELOAD_COMPLETE to logcat when done
logger.info("Validate that the event is done);
EmSingleton.get().waitForEvent(GrouponLnConstants.TodaysDeal.RELOAD_COMPLETE, 15000);
// Do other stuff...
Код EventManager (который я завернул в синглтон под названием EmSingleton):
public class EventManager {
private ArrayList<String> args = null;
private long startTime;
public EventManager() {
args = new ArrayList<String>(Arrays.asList("-v", "time", "-d"));
setCheckPoint();
}
public EventManager(ArrayList<String> _args) {
this();
for(String s: args) {
if (!args.contains(s)) {
args.add(s);
}
}
}
public void setCheckPoint()
{
Time startTimeOS = new android.text.format.Time();
startTimeOS.setToNow();
startTime = startTimeOS.toMillis(true);
}
public LogEvent checkEvent(String filter) throws Exception {
ArrayList<LogEvent> events = gatherEvents();
for(LogEvent event: events){
if(event.checkMsgSubstring(filter)){
return event;
}
}
return null;
}
public LogEvent waitForEvent(String filter, int timeout) throws Exception
{
int retries = timeout/1000 == 0 ? 1 : timeout/1000;
for(int i = 0; i < retries; i++)
{
LogEvent event = checkEvent(filter);
if(event != null){
return event;
}
Thread.sleep(1000);
}
return null;
}
public ArrayList<LogEvent> getEvents() {
return gatherEvents();
}
public void clearEvents() throws Exception{
ArrayList<String> commandLine = new ArrayList<String>();
commandLine.add("logcat");
commandLine.add("-c");
ProcessBuilder pb = new ProcessBuilder(commandLine.toArray(new String[0]));
pb.redirectErrorStream(true);
Process logcatProcess = pb.start();
logcatProcess.waitFor();
}
protected ArrayList<LogEvent> gatherEvents() {
ArrayList<LogEvent> events = new ArrayList<LogEvent>();
final StringBuilder log = new StringBuilder();
BufferedReader br;
try {
ArrayList<String> commandLine = new ArrayList<String>();
commandLine.add("logcat");
if (null != args) {
commandLine.addAll(args);
}
ProcessBuilder pb = new ProcessBuilder(commandLine.toArray(new String[0]));
pb.redirectErrorStream(true);
Process logcatProcess = pb.start();
InputStream is = logcatProcess.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
br = new BufferedReader(isr);
String line = null;
while (true) {
line = br.readLine();
if(line == null){
break;
}
// Add events to the events arraylist if they occur after the LogCollector has started to run
LogEvent event = new LogEvent(line);
if(event.peekTimeMS() > startTime)
{
events.add(event);
}
}
} catch (Exception e) {
TestLogger.get().error("GrouponTest", String.format("gatherEvents doInBackground failed: %s", e.toString()));
}
return events;
}
}
Вам потребуется установить следующее разрешение в своем приложении:
<uses-permission android:name="android.permission.READ_LOGS">
Я также создал объект LogEvent для анализа событий, поступающих от logcat:
public class LogEvent {
String orignalString = null;
boolean parsed = false;
long timeMs = 0;
String timeString = null;
String verbosity = null;
String tag = null;
int pid = 0;
String msg = null;
// Lazy factory design pattern
// http://en.wikipedia.org/wiki/Lazy_initialization
public LogEvent(String s) {
orignalString = s;
}
public long getTimeMs() {
checkInit();
return timeMs;
}
public long peekTimeMS()
{
// Time is always formattted as such: MM-DD HH:MM:SS.XXX
return parseTime(orignalString.substring(0,5), orignalString.substring(6,18));
}
public String getTimeString() {
checkInit();
return timeString;
}
public String getVerbosity() {
checkInit();
return verbosity;
}
public String getTag() {
checkInit();
return tag;
}
public int getPid() {
checkInit();
return pid;
}
public String getMsg() {
checkInit();
return msg;
}
/**
* Checks to see if the event message contains a substring
* @param check
* @return
*/
public Boolean checkMsgSubstring(String check)
{
int index = orignalString.indexOf(check);
boolean isSubstring = (index >= 0);
return isSubstring;
}
public String toString()
{
checkInit();
return String.format("%s %s/%s(%d): %s", timeString, verbosity, tag, pid, msg);
}
private void checkInit()
{
if(!parsed)
{
parseEvent();
parsed = true;
}
}
private void parseEvent()
{
try{
String [] splits = orignalString.split("[ ]+");
// Sometimes the PID is of format ( XX) instead of (XX)
if(splits[2].indexOf(")") < 0)
{
splits[2] += splits[3];
ArrayList<String> formatted = new ArrayList<String>(Arrays.asList(splits));
formatted.remove(3);
splits = formatted.toArray(new String[formatted.size()]);
}
// Parse time
timeMs = parseTime(splits[0], splits[1]);
timeString = String.format("%s %s", splits[0], splits[1]);
// Parse tag
verbosity = parseVerbosity(splits[2]);
tag = parseTag(splits[2]);
pid = parsePid(splits[2]);
// Parse message (may be empty)
if (splits.length > 3) {
msg = orignalString.substring(orignalString.indexOf(splits[3]));
} else {
msg = "";
}
}
catch (Exception e)
{
// TODO: there are some strangely formated events in the system. need to deal with these?
}
}
/**
* Time comes in following format: 08-11 20:03:17.182:
* Parse into milliseconds
* @param day string of format 08-11
* @param hours string of format 20:03:17.182:
* @return
*/
private long parseTime(String day, String hours)
{
Time timeToSet = new Time();
Time currentTime = new Time();
currentTime.setToNow();
// Parse fields
String[] daySplits = day.split("-");
if(daySplits.length < 2)
return 0;
String[] hourSplits = hours.split(":");
if(hourSplits.length < 2)
return 0;
String[] secondSplits = hourSplits[2].split("\\.");
if(secondSplits.length < 2)
return 0;
int _year = currentTime.year;
int _month = Integer.parseInt(daySplits[0])-1;
int _day = Integer.parseInt(daySplits[1]);
int _hour = Integer.parseInt(hourSplits[0]);
int _min = Integer.parseInt(hourSplits[1]);
int _sec = Integer.parseInt(secondSplits[0]);
int _mili = Integer.parseInt(secondSplits[1]);
//set(int second, int minute, int hour, int monthDay, int month, int year)
timeToSet.set(_sec, _min, _hour, _day, _month, _year);
// return calculated value
long parsedTimeInMili = timeToSet.toMillis(true) + (long)_mili;
return parsedTimeInMili;
}
private String parseVerbosity(String s)
{
return s.split("/")[0];
}
private String parseTag(String s)
{
int verbosityLength = parseVerbosity(s).length() +1;
String tagPart = s.substring(verbosityLength);
return tagPart.split("\\(")[0];
}
private int parsePid(String s)
{
try {
String pidPart = s.split("\\(")[1];
return Integer.parseInt(pidPart.split("\\)")[0]);
} catch (Exception e) {
e.toString();
}
return -1;
}
}