#

总览

Name Location Description
libmock_ril hardware\ril\mock-ril A mock ril like SecRil.
mockrilcontroller frameworks\opt\telephony\mockril Communicate with libmock_ril,send and receive fake RIL cmd to/from libmock_ril via socket.
TelephonyMockRilTests frameworks\opt\telephony\tests\telephonymockriltests A Package communicates with libmock_ril via mockrilcontroller, it use InstrumentationTestCase framework to test libmock_ril`s mock functions.
FrameworksTelephonyTests frameworks\opt\telephony\tests\telephonytests A Package using InstrumentationTestRunner and TestCase to test Telephony.


上图中,同一层的模块功能相同:

RIL

Reference-ril是Android提供的参考代码。Mock-ril则是一个模拟的Ril模块。三者的功能相同。

Telephony

Telephony和RIL层之间通过Socket通信,mockrilcontroller功能和telephony-common类似,只不过其是与Mock-ril通信。还有一个区别是telephony-common编译为动态库,而mockrilcontroller为静态库

Package

TelephonyMockRilTests 模块中包含静态库mockrilcontroller。通过查看Manifest可以看出TelephonyMockRilTests 测试的目标package是其本身。主要目的是测试mockrilcontroller和Mock-ril模块。
FrameworksTelephonyTests模块中则包含动态库telephony-common,通过查看Manifest可以看出FrameworksTelephonyTests测试的目标package也是其本身。主要目的是测试telephony-common模块。

FrameworksTelephonyTests 分析

根据上一章的测试实例分析,现在来看FrameworksTelephonyTests就不太复杂了。FrameworksTelephonyTests能够同时测试Telephony-common和Mock-ril模块(TelephonyMockRilTests只是对Mock-ril的一个简单测试,在FrameworksTelephonyTests已经覆盖了这部分测试,所以就不再单独分析 TelephonyMockRilTests)。
测试是从TestRunner开始的,FrameworksTelephonyTests新建了一个自定义的TestRunner类TelephonyMockRilTestRunner,用来辅助测试Mock-ril,而对Telephony-common模块的测试,则是直接使用的Android测试框架的的InstrumentationTestRunner。
如下图所示,由于测试用例较多,这里仅挑选2个典型的测试用例进行说明。

GSMPhoneTest

GSMPhoneTest继承了AndroidTestCase类并实现了PerformanceTestCase接口,根据上文可知,AndroidTestCase 继承于JUnit的TestCase,并没有使用Instrumentation框架,所以GSMPhoneTest该用例不能使用Android Instrumentation框架的方法。

1 setUp():

首先初始化GSMTestHandler和GSMPhone对象,得到GSMPhone的引用。并通过GSMPhone对象的方法,注册EVENT_POST_DIAL等一系列事件。

sc = new SimulatedCommands();
mGSMPhone = new GSMPhone(mContext, sc, new TestPhoneNotifier(), true);

不过新建GSMPhone时,传递的RIL接口是一个模拟的接口,这样在调用GSMPhone方法时,并非调用到正常的RIL.java发送AT指令。而是一个模拟的ril对象SimulatedCommands上。
这样,该测试除了ril接口和调用者是虚拟的,其他Telephony流程和正常流程一致,见下图:

2 testOutgoingCallFailImmediately():

该测试方法用来测试呼出的呼叫立即失败的边缘测试(呼叫还没有出现在call list之前就立即终结),这会导致该失败的呼叫在ForegroundCall list中以IDLE call的形式出现。

public void testOutgoingCallFailImmediately() throws Exception {Message msg;mRadioControl.setNextDialFailImmediately(true);Connection cn = mGSMPhone.dial("+13125551212");msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);assertNotNull("Message Time Out", msg);assertEquals(PhoneConstants.State.IDLE, mGSMPhone.getState());assertEquals(Connection.DisconnectCause.NORMAL, cn.getDisconnectCause());assertEquals(0, mGSMPhone.getRingingCall().getConnections().size());assertEquals(1, mGSMPhone.getForegroundCall().getConnections().size());assertEquals(0, mGSMPhone.getBackgroundCall().getConnections().size());assertEquals(Call.State.IDLE, mGSMPhone.getRingingCall().getState());assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());assertEquals(Call.State.IDLE, mGSMPhone.getBackgroundCall().getState());assertTrue(mGSMPhone.getForegroundCall().getEarliestCreateTime() > 0);assertEquals(0, mGSMPhone.getForegroundCall().getEarliestConnectTime());
}

3 testHangupOnOutgoing:

该测试方法用来测试通话呼出后,在不同状态下(DIALING、ALERTING等)进行挂断。然后判断Phone的状态、Call的状态和连接断开原因是否符合预期。

public void testHangupOnOutgoing() throws Exception {Connection cn;Message msg;mRadioControl.setAutoProgressConnectingCall(false);// Test 1: local hangup in "DIALING" statemGSMPhone.dial("+13125551212");do {assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));}while (mGSMPhone.getForegroundCall().getState() != Call.State.DIALING);cn = mGSMPhone.getForegroundCall().getEarliestConnection();mGSMPhone.getForegroundCall().hangup();msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);assertNotNull("Message Time Out", msg);assertEquals(PhoneConstants.State.IDLE, mGSMPhone.getState());assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());assertEquals(Connection.DisconnectCause.LOCAL, cn.getDisconnectCause());// Test 2: local hangup in "ALERTING" statemGSMPhone.dial("+13125551212");do {assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));} while (mGSMPhone.getState() != PhoneConstants.State.OFFHOOK);mRadioControl.progressConnectingCallState();do {assertNotNull("Message Time Out", mGSMTestHandler.waitForMessage(ANY_MESSAGE));}while (mGSMPhone.getForegroundCall().getState() != Call.State.ALERTING);cn = mGSMPhone.getForegroundCall().getEarliestConnection();mGSMPhone.getForegroundCall().hangup();msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);assertNotNull("Message Time Out", msg);assertEquals(PhoneConstants.State.IDLE, mGSMPhone.getState());assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());assertEquals(Connection.DisconnectCause.LOCAL, cn.getDisconnectCause());// Test 3: local immediate hangup before GSM index is// assigned (CallTracker.hangupPendingMO case)mRadioControl.pauseResponses();cn = mGSMPhone.dial("+13125551212");cn.hangup();mRadioControl.resumeResponses();msg = mGSMTestHandler.waitForMessage(EVENT_DISCONNECT);assertNotNull("Message Time Out", msg);assertEquals(PhoneConstants.State.IDLE, mGSMPhone.getState());assertEquals(Call.State.DISCONNECTED, mGSMPhone.getForegroundCall().getState());assertEquals(Connection.DisconnectCause.LOCAL,            mGSMPhone.getForegroundCall().getEarliestConnection().getDisconnectCause());}

MockRilTest

MockRilTest继承了InstrumentationTestCase类,根据上文可知,InstrumentationTestCase继承于JUnit的TestCase,并使用Instrumentation框架,所以MockRilTest该用例可以使用Android Instrumentation框架的方法。该用例是由自定义的TestRunner——TelephonyMockRilTestRunner运行的。并持有RilChannel对象引用。进而调用RIL层的mock-ril进行测试。

1 setUp():

首先初始化TelephonyMockRilTestRunner和RilChannel对象,得到RilChannel的引用。通过RilChannel的socket和mock-ril进行通信。
如下图所示:


注:聚合关系的方向画错了,暂时没法修改,见谅。

MockRilTest通过RilChannel和mock-ril建立socket连接并通信。MockRilTest的各个测试方法通过Msg类的静态方法,收发RilChannel指令。

        mRunner = (TelephonyMockRilTestRunner)getInstrumentation();mMockRilChannel = mRunner.mMockRilChannel;

2 testGetRadioState():

  public void testGetRadioState() throws IOException {log("testGetRadioState E");Msg.send(mMockRilChannel, 1, 9876, 0, null);Msg resp = Msg.recv(mMockRilChannel);//resp.printHeader("testGetRadioState");assertTrue(String.format("expected cmd == 1 was %d", resp.getCmd()),resp.getCmd() == 1);assertTrue(String.format("expected token == 9876 was %d", resp.getToken()),resp.getToken() == 9876);assertTrue(String.format("expected status == 0 was %d", resp.getStatus()),resp.getStatus() == 0);RilCtrlCmds.CtrlRspRadioState rsp = resp.getDataAs(RilCtrlCmds.CtrlRspRadioState.class);int state = rsp.getState();log("testGetRadioState state=" + state);assertTrue(String.format("expected RadioState >= 0 && RadioState <= 9 was %d", state),((state >= 0) && (state <= 9)));log("testGetRadioState X");}

3 testStartIncomingCallAndHangup():

public void testStartIncomingCallAndHangup() throws IOException {log("testStartIncomingCallAndHangup");RilCtrlCmds.CtrlReqSetMTCall cmd = new RilCtrlCmds.CtrlReqSetMTCall();String incomingCall = "6502889108";// set the MT callcmd.setPhoneNumber(incomingCall);Msg.send(mMockRilChannel, RilCtrlCmds.CTRL_CMD_SET_MT_CALL, 0, 0, cmd);// get responseMsg resp = Msg.recv(mMockRilChannel);log("Get response status: " + resp.getStatus());assertTrue("The ril is not in a proper state to set MT calls.",resp.getStatus() == RilCtrlCmds.CTRL_STATUS_OK);// allow the incoming call alerting for some timetry {Thread.sleep(5000);} catch (InterruptedException e) {}// we are playing a trick to assume the current is 1RilCtrlCmds.CtrlHangupConnRemote hangupCmd = new RilCtrlCmds.CtrlHangupConnRemote();hangupCmd.setConnectionId(1);hangupCmd.setCallFailCause(16);   // normal hangupMsg.send(mMockRilChannel, RilCtrlCmds.CTRL_CMD_HANGUP_CONN_REMOTE, 0, 0, hangupCmd);// get responseresp = Msg.recv(mMockRilChannel);log("Get response for hangup connection: " + resp.getStatus());assertTrue("CTRL_CMD_HANGUP_CONN_REMOTE failed",resp.getStatus() == RilCtrlCmds.CTRL_STATUS_OK);}

运行测试

应用编译并安装到目标测试机器中后,通过ADB工具进入终端,通过指令:
am instrument -w com.android.frameworks.telephonytests /android.test.InstrumentationTestRunner
即可运行该测试应用,自动运行每一个测试用例,并将测试结果显示在输出中。如下所示:

com.android.internal.telephony.ATResponseParserTest:.
com.android.internal.telephony.AdnRecordTest:.
com.android.internal.telephony.ApnSettingTest:
Failure in testFromString:
junit.framework.AssertionFailedError: expected:<2> but was:<4>at com.android.internal.telephony.ApnSettingTest.assertApnSettingEqual(ApnSettingTest.java:42)at com.android.internal.telephony.ApnSettingTest.testFromString(ApnSettingTest.java:93)at java.lang.reflect.Method.invokeNative(Native Method)at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:190)at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:175)at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:555)at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1661)
.
com.android.internal.telephony.GsmAlphabetTest:...
com.android.internal.telephony.GsmSmsTest:..........
Error in testFragmentTurkishText:
java.lang.IllegalAccessError: tried to access method com.android.internal.telephony.GsmAlphabet.getEnabledSingleShiftTables:()V from class com.android.internal.telephony.GsmSmsTestat com.android.internal.telephony.GsmSmsTest.testFragmentTurkishText(GsmSmsTest.java:281)at java.lang.reflect.Method.invokeNative(Native Method)at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:190)at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:175)at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:555)at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1661)
...
com.android.internal.telephony.IccServiceTableTest:..
com.android.internal.telephony.IntRangeManagerTest:.........
com.android.internal.telephony.MccTableTest:.....
com.android.internal.telephony.NeighboringCellInfoTest:...
com.android.internal.telephony.PhoneNumberUtilsTest:..
Failure in testCheckAndProcessPlusCode:
junit.framework.ComparisonFailure: expected:<[011]8475797000> but was:<[+]8475797000>

总结

作为白盒测试,测试用例的设计至关重要,对于已有的代码,其类与类之间相关性较大的情况,测试用例的设计就会增加复杂度,需要设计多个模拟类来替代相关类,必要时应该在代码设计阶段就应该考虑其可测试性。
大多是先设计测试用例,以测试推进开发。

Telephony单元测试分析相关推荐

  1. SonarQube4.4+Jenkins进行代码检查实例之三-单元测试分析

    作者:张克强    作者微博:张克强-敏捷307 在 <SonarQube4.4+Jenkins进行代码检查实例之一> 中介绍了不编译只检查的方式. 在<SonarQube4.4+J ...

  2. Telephony框架分析

    引子 无论手机如何改变,功能如何丰富,它最核心最关键的功能依旧是通讯,通讯按现在的情况来说主要就是打电话发短信和上网,Android的通讯框架从上往下可以分为4个部分: Modem 这是整个通讯的硬件 ...

  3. Android5.1 Telephony流程分析——拨打电话流程(MO CALL)

    本文代码以MTK平台Android 5.1为分析对象,与Google原生AOSP有些许差异,请读者知悉. 此图主要是根据Android源代码拨打电话流程来绘制,记录了电话拨打的主要过程: 参考博客:h ...

  4. Android Telephony Call分析

    关于Call对象 一共4个 ./packages/apps/Dialer/java/com/android/incallui/call/DialerCall.java ./frameworks/bas ...

  5. Android4.4 Telephony流程分析——去电(MO)流程

    本文代码以MTK平台Android 4.4为分析对象,与Google原生AOSP有些许差异,请读者知悉. 下图为去电时序图: 右键复制图片地址,在浏览器中打开即可查看大图. 未完待续,有不对的地方,请 ...

  6. telephony.db分析

    主要存储了 siminfo 及 apn 相关数据信息. telephony.db,其在手机存储位置:                                                  ...

  7. VS2010单元测试入门实践教程

    摘要:本教程不会介绍单元测试的基本理论知识,也不会和大家讨论在实际项目中是否需要写单元测试代码的问题.但是如果你此时想使用VS中的单元测试的工具来测试某个方法是否正确,可你又从来没真正实践过,那么本教 ...

  8. MFQPPDCS大型嵌入式软件系统的测试分析和测试设计

    MFQ&PPDCS大型嵌入式软件系统的测试分析和测试设计 原创作者:邰晓梅 翻译:wzhj132 原创来源:2009年ICSEA大会上的论文<MFQ & PPDCS - Test ...

  9. 2109-微服务课上问题分析及总结

    文章目录 Day01~微服务架构入门 核心知识点 常见问题分析 常见Bug分析 课堂练习 课后作业 Day02~Nacos注册中心入门 核心知识点 常见问题分析 常见Bug分析 课堂小技巧 课后作业 ...

最新文章

  1. 《OpenCV3编程入门》学习笔记6 图像处理(六)图像金字塔与图片尺寸缩放
  2. USEARCH —— 最简单易学的扩增子分析流程
  3. 科大讯飞与优刻得、寒武纪等联合设立合肥智能语音创新发展有限公司
  4. simulink传递函数_又见Simulink库模型之(6):查找表
  5. tcp假连接_总结的23 个 TCP高频面试问题
  6. [ZJOI2007]报表统计(链表法+set)
  7. leetcode —— 19. 删除链表的倒数第N个节点
  8. php反选全选代码,jQuery中实现全选,反选实例代码 (推荐)
  9. git-ftp:用git管理ftp服务器简单入门
  10. 阿里巴巴矢量图标库批量添加图标
  11. android 平板怎么截图,小米平板4怎么截图 小米平板4截屏的三种方法
  12. 2020年最新计算机二级考试题库资料大全!
  13. python 针对二分类问题画roc曲线
  14. 目标检测——目标检测方法的综述
  15. AC695x学习笔记(3):按键
  16. 前端登录实现记住密码功能
  17. 关于电子科技大学在校大学生经济状况的调查
  18. 北京信息科技大学第十二届程序设计竞赛暨ACM选拔赛(同步赛)
  19. 计算机模拟数学实验的概念,数学建模与数学实验(课堂PPT)
  20. 《电子商务案例分析》读后结

热门文章

  1. 为什么996工作制只提互联网公司,其他行业没有吗?
  2. 【Guacamole中文文档】二、用户指南 —— 1.实现和架构
  3. MySQL查询时条件的顺序_mysql中查询条件的先后顺序问题?
  4. 外贸订单回暖,集装箱持续爆舱,低代码或将成外贸行业新的财富密码
  5. Ubuntu20.04.3引导修复(Boot Repair)
  6. 迈克尔•波特的“五力模型”中,最明显的竞争状态是()国开个人与团队管理知识点解析
  7. ktv点歌系统 Vue +Express+ Mongodb
  8. 腾讯8分钟产品课腾讯产品心法整理
  9. linux打开串口lazarus,Lazarus开发串口通信
  10. Lazarus crack,功能丰富的 Delphi 开发环境