android自动化测试CTS源码分析之五
来源:互联网 发布:闽南人迷信知乎 编辑:程序博客网 时间:2024/06/10 08:07
6. Instrumentation
6.1 启动Instrumentation
获取adb shell am instrument –w命令后,AM.java中的onRun方法对该命令处理如下
else if (op.equals("instrument")) { runInstrument();
runInstrument方法如下,
if (!mAm.startInstrumentation(cn, profileFile, 0, args, watcher, connection, userId, abi)) { throw new AndroidException("INSTRUMENTATION_FAILED: " + cn.flattenToString()); }
调用ActivityManagerService的startInstrumentation方法启动Instrumentation,并且传入相关命令参数。
final long origId = Binder.clearCallingIdentity(); // Instrumentation can kill and relaunch even persistent processes forceStopPackageLocked(ii.targetPackage, -1, true, false, true, true, false, userId, "start instr"); ProcessRecord app = addAppLocked(ai, false, abiOverride); app.instrumentationClass = className; app.instrumentationInfo = ai; app.instrumentationProfileFile = profileFile; app.instrumentationArguments = arguments; app.instrumentationWatcher = watcher; app.instrumentationUiAutomationConnection = uiAutomationConnection; app.instrumentationResultClass = className; Binder.restoreCallingIdentity(origId);
addAppLocked 方法中会调用startProcessLocked方法,到此和Activity等四大组件启动的流程完全一样。
最后在ActivityManagerService的attachApplicationLocked方法中,
Activity的启动主要调用ActivityStackSupervisor的attachApplicationLocked方法,
而Instrumentation的启动主要是调用ApplicationThreadNative的bindApplication方法,
然后跨进程调用ActivityThread的内部类ApplicationThread的bindApplication方法。
ProfilerInfo profilerInfo = profileFile == null ? null : new ProfilerInfo(profileFile, profileFd, samplingInterval, profileAutoStop); thread.bindApplication(processName, appInfo, providers, app.instrumentationClass, profilerInfo, app.instrumentationArguments, app.instrumentationWatcher, app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace, isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(mConfiguration), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked()); updateLruProcessLocked(app, false, null); app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
当然,启动Instrumentation的过程中也会创建进程。
ActivityThread的内部类ApplicationThread的bindApplication方法部分代码如下,
AppBindData data = new AppBindData(); data.processName = processName; data.appInfo = appInfo; data.providers = providers; data.instrumentationName = instrumentationName; data.instrumentationArgs = instrumentationArgs; data.instrumentationWatcher = instrumentationWatcher; data.instrumentationUiAutomationConnection = instrumentationUiConnection; data.debugMode = debugMode; data.enableOpenGlTrace = enableOpenGlTrace; data.restrictedBackupMode = isRestrictedBackupMode; data.persistent = persistent; data.config = config; data.compatInfo = compatInfo; data.initProfilerInfo = profilerInfo; sendMessage(H.BIND_APPLICATION, data);
主要时发送handler消息切换到主线程执行。
Handler对BIND_APPLICATION消息处理如下,
AppBindData data = (AppBindData)msg.obj;handleBindApplication(data);
handleBindApplication方法中有关instrumentation代码如下,
首先利用发射构造instrumentation对象,
try { java.lang.ClassLoader cl = instrContext.getClassLoader(); mInstrumentation = (Instrumentation) cl.loadClass(data.instrumentationName.getClassName()).newInstance(); } catch (Exception e) { throw new RuntimeException( "Unable to instantiate instrumentation " + data.instrumentationName + ": " + e.toString(), e); }
然后调用instrumentation对象的init方法。
mInstrumentation.init(this, instrContext, appContext, new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
最后调用instrumentation对象的onCreate方法。
mInstrumentation.onCreate(data.instrumentationArgs);
6.2 Instrumentation作用
Instrumentation在自动化测试中主要作用是什么呢?
简单点说,进行自动化测试时,很多时候并不需要界面。因此可以这么说,在自动化测试中,Instrumentation作用相当于Activity。
其中的方法几乎和Activity对应的方法一摸一样。例如,
public void onCreate(Bundle arguments) {}public void onStart() { }public void onDestroy() { }
CTS的蓝牙apk的AndroidManifest.xml文件如下,
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.cts.bluetooth"> <uses-permission android:name="android.permission.BLUETOOTH" /> <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> <uses-permission android:name="android.permission.DISABLE_KEYGUARD" /> <application> <uses-library android:name="android.test.runner" /> </application> <!-- This is a self-instrumenting test package. --> <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner" android:targetPackage="com.android.cts.bluetooth" android:label="CTS tests of bluetooth component"> <meta-data android:name="listener" android:value="com.android.cts.runner.CtsTestRunListener" /> </instrumentation></manifest>
也只是将instrumentation替换了activity.
AndroidJUnitRunner和InstrumentationTestRunner都是继承于Instrumentation,作用大同小异,
但是测试原理完全一样,因此本文选择InstrumentationTestRunner进行分析。
InstrumentationTestRunner扮演的角色类似于当中的UiAutomatorTestRunner类,
通过解析获取和建立目标测试用例和测试集然后开始测试。
onCreate方法调用流程图如下,
InstrumentationTestRunner的onStart方法如下,
try { //新建打印结果对象 StringResultPrinter resultPrinter = new StringResultPrinter(writer); //设置测试监听 mTestRunner.addTestListener(resultPrinter); // 获取开始的系统时间 long startTime = System.currentTimeMillis(); // 开始进行测试 mTestRunner.runTest(); // 测试时间 long runTime = System.currentTimeMillis() - startTime; // 打印测试结果 resultPrinter.printResult(mTestRunner.getTestResult(), runTime); } catch (Throwable t) { // catch all exceptions so a more verbose error message can be outputted writer.println(String.format("Test run aborted due to unexpected exception: %s", t.getMessage())); t.printStackTrace(writer); } finally { mResults.putString(Instrumentation.REPORT_KEY_STREAMRESULT, String.format("\nTest results for %s=%s", mTestRunner.getTestClassName(), byteArrayOutputStream.toString())); if (mCoverage) { generateCoverageReport(); } writer.close(); // 调用finish方法 finish(Activity.RESULT_OK, mResults); } }
6.3,测试
在InstrumentationTestRunner的onStart方法中会调用AndroidTestRunner的runTest进行测试, runTest方法如下,
public void runTest(TestResult testResult) { mTestResult = testResult; for (TestListener testListener : mTestListeners) { mTestResult.addListener(testListener); } Context testContext = mInstrumentation == null ? mContext : mInstrumentation.getContext(); for (TestCase testCase : mTestCases) { setContextIfAndroidTestCase(testCase, mContext, testContext); setInstrumentationIfInstrumentationTestCase(testCase, mInstrumentation); setPerformanceWriterIfPerformanceCollectorTestCase(testCase, mPerfWriter); testCase.run(mTestResult); } }
首先设置监听,然后逐个调用测试方法。
CTS测试中,每个apk测试的TestCase完全不一样,一般都继承于AndroidTestCase,而AndroidTestCase继承于TestCase。
以蓝牙测试为例,测试类BasicAdapterTest定义如下,
public class BasicAdapterTest extends AndroidTestCase {
该测试类有8个以test开头的测试用例。
具体的调用过程就不论述了,
TestCase的runBare方法如下,
public void runBare() throws Throwable {Throwable exception= null;setUp();try {runTest();} catch (Throwable running) {exception= running;}finally {try {tearDown();} catch (Throwable tearingDown) {if (exception == null) exception= tearingDown;}}if (exception != null) throw exception;}
1,在测试之前会调用setUp方法。
2,利用反射的方法进行测试用例的调用。
3,测试完成之后,会调用tearDown方法。
至于具体的测试用例,可以看蓝牙的测试。
- android自动化测试CTS源码分析之五
- android自动化测试CTS源码分析之二
- android自动化测试CTS源码分析之三
- android自动化测试CTS源码分析之四
- android自动化测试CTS源码分析之一
- android自动化测试之CTS
- Android自动化测试之CTS
- android自动化测试之CTS
- android自动化测试Uiautomator源码分析之五
- android-cts兼容性自动化测试
- Android测试(五)CTS测试
- android自动化测试Uiautomator源码分析之二
- android自动化测试Uiautomator源码分析之三
- android自动化测试Uiautomator源码分析之四
- android自动化测试Monkeyrunner源码分析之二
- android自动化测试Monkeyrunner源码分析之三
- android自动化测试Monkeyrunner源码分析之四
- Android自动化测试——CTS测试
- android中Listview+GridView遇到的坑
- 编码能力简单分类
- date和String之间的转换,数据库
- 学好Linux了吗?没有就来看看这个命令系列~
- shell脚本中常见工具grep的使用
- android自动化测试CTS源码分析之五
- 532. K-diff Pairs in an Array
- Java Reactive 异步与并发编程
- ossfs挂载到本地磁盘
- 笔试题——字符串编码
- 2_2最近邻算法kNN(k_nearest_neighbor)——file2matrix_2_2
- Android的事件传递机制
- 序列和
- 【C#】查询选定日期范围内相关数据