gpt4 book ai didi

android - 基于事件的安卓测试

转载 作者:行者123 更新时间:2023-11-28 20:46:36 25 4
gpt4 key购买 nike

我正在使用 robotium 进行测试,我遇到了一堆计时问题,这些问题让我很难知道 Activity (或 View )何时完成加载。因此,我正在编写的测试不是很可靠。

我正在寻找一种方法,用可以推送到测试框架的事件来检测我的被测应用程序。如果我的被测应用程序可以在预期事件发生时“告诉”我的测试,这将非常有用。我用过 Event Tracing for Windows对于过去的 windows\windows phone 效果很好。

我正在寻找的执行此操作的穷人方法是让我的测试应用程序实时读取 logcat 并在预期事件发生时通知测试。

还有人有其他想法吗?

最佳答案

为了解决这个问题,我依赖操作系统 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;
}
}

关于android - 基于事件的安卓测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7014797/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com