Cts框架解析(21)-测试结果收集系统

来源:互联网 发布:四班三倒排班表软件 编辑:程序博客网 时间:2024/05/17 15:58

1.UML图



2.解释


cts框架中将case的执行和case结果的收集分成了独立的2个部分,我们称case的结果的收集叫测试结果收集器。设计的思路来源为ddmlib中的ITestRunListener接口,该接口是一个抽象的观察者组件,cts创建有很多的具体的组件。但是这些组件不是一个一个去注册成为监听者的,而是在run的时候传递给ddmlib中RemoteAndroidTestRunner类的。所以只要我们继承了该接口,在run的时候把该接口的实例对象传过去,我们就能在对象实例的相应方法中接受信息。但是我们想要有多个地方都能接受到测试结果呢?没关系,cts为我们准备了ResultForwarder类。看具体实现细节:


3.ResultForwarder


public class ResultForwarder implements ITestInvocationListener {private List<ITestInvocationListener> mListeners;/** * Create a {@link ResultForwarder} with deferred listener setting. Intended * only for use by subclasses. */protected ResultForwarder() {mListeners = Collections.emptyList();}/** * Create a {@link ResultForwarder}. *  * @param listeners *            the real {@link ITestInvocationListener}s to forward results *            to */public ResultForwarder(List<ITestInvocationListener> listeners) {mListeners = listeners;}/** * Alternate variable arg constructor for {@link ResultForwarder}. *  * @param listeners *            the real {@link ITestInvocationListener}s to forward results *            to */public ResultForwarder(ITestInvocationListener... listeners) {mListeners = Arrays.asList(listeners);}/** * Set the listeners after construction. Intended only for use by * subclasses. *  * @param listeners *            the real {@link ITestInvocationListener}s to forward results *            to */protected void setListeners(List<ITestInvocationListener> listeners) {mListeners = listeners;}/** * Set the listeners after construction. Intended only for use by * subclasses. *  * @param listeners *            the real {@link ITestInvocationListener}s to forward results *            to */protected void setListeners(ITestInvocationListener... listeners) {mListeners = Arrays.asList(listeners);}/** * {@inheritDoc} */@Overridepublic void invocationStarted(IBuildInfo buildInfo) {for (ITestInvocationListener listener : mListeners) {listener.invocationStarted(buildInfo);}}/** * {@inheritDoc} */@Overridepublic void invocationFailed(Throwable cause) {for (ITestInvocationListener listener : mListeners) {listener.invocationFailed(cause);}}/** * {@inheritDoc} */@Overridepublic void invocationEnded(long elapsedTime) {InvocationSummaryHelper.reportInvocationEnded(mListeners, elapsedTime);}/** * {@inheritDoc} */@Overridepublic TestSummary getSummary() {// should never be calledreturn null;}/** * {@inheritDoc} */@Overridepublic void testLog(String dataName, LogDataType dataType,InputStreamSource dataStream) {//CLog.logAndDisplay(LogLevel.INFO,//String.format("[testLog] dataName: %s", dataName));for (ITestInvocationListener listener : mListeners) {listener.testLog(dataName, dataType, dataStream);}}/** * {@inheritDoc}case开始时显式的调用 */@Overridepublic void testRunStarted(String runName, int testCount) {//CLog.logAndDisplay(LogLevel.INFO, String//.format("[testRunStarted] runName: %s testCount:%d", runName,//testCount));for (ITestInvocationListener listener : mListeners) {listener.testRunStarted(runName, testCount);}}/** * {@inheritDoc} */@Overridepublic void testRunFailed(String errorMessage) {//CLog.logAndDisplay(LogLevel.INFO,//String.format("[testRunFailed] errorMessage: %s", errorMessage));for (ITestInvocationListener listener : mListeners) {listener.testRunFailed(errorMessage);}}/** * {@inheritDoc} */@Overridepublic void testRunStopped(long elapsedTime) {//CLog.logAndDisplay(LogLevel.INFO,//String.format("[testRunStopped] elapsedTime: %d", elapsedTime));for (ITestInvocationListener listener : mListeners) {listener.testRunStopped(elapsedTime);}}/** * {@inheritDoc} */@Overridepublic void testRunEnded(long elapsedTime, Map<String, String> runMetrics) {//CLog.logAndDisplay(LogLevel.INFO,//String.format("[testRunEnded] elapsedTime: %d", elapsedTime));for (ITestInvocationListener listener : mListeners) {listener.testRunEnded(elapsedTime, runMetrics);}}/** * {@inheritDoc} */@Overridepublic void testStarted(TestIdentifier test) {//CLog.logAndDisplay(LogLevel.INFO,//String.format("[testStarted] %s", test.toString()));for (ITestInvocationListener listener : mListeners) {listener.testStarted(test);}}/** * {@inheritDoc} */@Overridepublic void testFailed(TestFailure status, TestIdentifier test, String trace) {//CLog.logAndDisplay(LogLevel.INFO,//String.format("[testFailed] %s", test.toString()));for (ITestInvocationListener listener : mListeners) {listener.testFailed(status, test, trace);}}/** * {@inheritDoc} */@Overridepublic void testEnded(TestIdentifier test, Map<String, String> testMetrics) {//CLog.logAndDisplay(LogLevel.INFO,//String.format("[testEnded] %s", test.toString()));for (ITestInvocationListener listener : mListeners) {listener.testEnded(test, testMetrics);}}}

该类中继承于ITestInvocationListener接口,ITestInvocationListener也继承与ITestRunListener接口,然后在ITestRunListener接口原有的方法上添加了一些cts所要用到的方法。而我们的ResultForwarder就是一个ITestInvocationListener接口,自然而然也是ITestRunListener对象。

而我们具体看看ResultForwarder构造方法你会发现,参数是多个ITestInvocationListener对象,传递进来保存到定义的集合中。这样当我们ResultForwarder传递到ddmlib内部的时候,ResultForwarder相应方法被调用后,里面的结果监听器集合里的每一个结果监听器都会收到结果。这样的设计难道不是很牛逼,我是觉得很牛逼啊!!!


4.ResultForwarder的子类


cts还给测试时配备了3个使用型的失败现场证据收集器,请看下面的三个类定义。


/** * 保存bugreport日志 A {@link ResultForwarder} that will forward a bugreport on * each failed test. */private static class FailedTestBugreportGenerator extends ResultForwarder {private ITestDevice mDevice;public FailedTestBugreportGenerator(ITestInvocationListener listener, ITestDevice device) {super(listener);mDevice = device;}// 当ddmlib中ITestRunListener监听器触发testFailed方法时,该方法被调用.ITestRunListener的方法是由ddmlib内部调用的// 该方法将在android-cts\repository\logs生成bugreport信息的文本文件并打包@Overridepublic void testFailed(TestFailure status, TestIdentifier test, String trace) {super.testFailed(status, test, trace);InputStreamSource bugSource = mDevice.getBugreport();// System.out.println("CtsTest.FailedTestBugreportGenerator.testFailed: 执行case失败,需要保存当前bugreport的信息");// CLog.logAndDisplay(LogLevel.INFO,// String.format("[testFailed] %s", test.toString()));super.testLog(String.format("bug-%s_%s", test.getClassName(), test.getTestName()), LogDataType.TEXT, bugSource);bugSource.cancel();}}/** * 保存system缓冲区的日志 A {@link ResultForwarder} that will forward a logcat * snapshot on each failed test. */private static class FailedTestLogcatGenerator extends ResultForwarder {private ITestDevice mDevice;private int mNumLogcatBytes;public FailedTestLogcatGenerator(ITestInvocationListener listener, ITestDevice device, int maxLogcatBytes) {super(listener);mDevice = device;mNumLogcatBytes = maxLogcatBytes;}@Overridepublic void testFailed(TestFailure status, TestIdentifier test, String trace) {super.testFailed(status, test, trace);// sleep a small amount of time to ensure test failure stack trace// makes it into logcat// captureRunUtil.getDefault().sleep(10);InputStreamSource logSource = mDevice.getLogcat(mNumLogcatBytes);super.testLog(String.format("logcat-%s_%s", test.getClassName(), test.getTestName()), LogDataType.TEXT, logSource);logSource.cancel();}}/** * 保存截图 A {@link ResultForwarder} that will forward a screenshot on test * failures. */private static class FailedTestScreenshotGenerator extends ResultForwarder {private ITestDevice mDevice;public FailedTestScreenshotGenerator(ITestInvocationListener listener, ITestDevice device) {super(listener);mDevice = device;}@Overridepublic void testFailed(TestFailure status, TestIdentifier test, String trace) {super.testFailed(status, test, trace);try {InputStreamSource screenSource = mDevice.getScreenshot();super.testLog(String.format("screenshot-%s_%s", test.getClassName(), test.getTestName()), LogDataType.PNG, screenSource);screenSource.cancel();} catch (DeviceNotAvailableException e) {// TODO: rethrow this somehowCLog.e("Device %s became unavailable while capturing screenshot, %s", mDevice.getSerialNumber(), e.toString());}}}

老大:bugreport信息保存

老二:logcat信息保存

老三:现场截图


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 18孩子不想上学怎么办 宝宝不爱吃蔬菜怎么办 孩子总丢东西怎么办 孩子经常丢东西怎么办 孩子总是丢东西怎么办 孩子负能量太多怎么办 不要孩子老了怎么办 父母都内向孩子怎么办 孩子不喜欢读课外书怎么办 学习学不进去怎么办 小孩停不下来怎么办 小孩老爱玩不爱学习怎么办 小孩子不喜欢吃菜怎么办 孩子初中不爱学习怎么办 大学不爱学家长怎么办 小孩子不爱读书不听话怎么办 小孩不爱读书写字怎么办 一年级学生不爱学习怎么办 孩子练字怕累怎么办 孩子不愿意学英语怎么办 生了儿子 不喜欢 怎么办 养两个儿子的怎么办 看诗词记不住怎么办 经常读书记不住怎么办 孩子不爱记数字怎么办 考研学不进去怎么办 读了职高后悔怎么办 不喜欢看书的人怎么办 生的儿子不喜欢怎么办 孩子上网不回家怎么办 儿子不想读书了怎么办 中考体育考不好怎么办 小孩突然没礼貌怎么办 小孩读书记忆差怎么办 这几天不爱吃饭怎么办 读书读到不懂的怎么办 读书很多词不懂怎么办 看书看不进去怎么办 一年级小孩不喜欢读书怎么办 考研还不想学习怎么办 怎么吃还是瘦怎么办