Android测试框架及例子

本文详细介绍了如何使用ActivityInstrumentationTestCase2进行Android自动化测试,包括测试用例的源码框架、最佳实践以及关键操作注意事项。通过实例分析,展示了如何在测试集合中验证待测活动的初始化、界面元素的操作以及如何确保测试过程中的应用状态有意义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

从图3-2中可以看到,基本所有的测试用例都是通过InstrumenationTestRunner执行的,而各个测试类型被设计来执行特定的测试,在本章中,主要讲解ActivityInstrumentationTestCase2的用法,其他的类型将放在后续章节里讲解。ActivityInstrumentationTestCase2这个类型是用来针对单个活动执行功能测试。它通过InstrumentationTestCase.launchActivity函数使用系统API来创建待测活动,可以在这个测试用例里直接操控活动,在待测应用的UI线程上执行测试函数,也允许我们向待测应用注入一个自定义的意图对象。

3.2.1 ActivityInstrumentationTestCase2测试用例

一个ActivityInstrumentationTestCase2的测试用例源码框架一般如代码清单3-5所示。

代码清单3-5 ActivityInstrumentationTestCase2测试用例的源码框架
 

  1. 1. public class SpinnerActivityTest extends  
  2. 2.  ActivityInstrumentationTestCase2<SpinnerActivity>{  
  3. 3.     publicSpinnerActivityTest() {  
  4. 4.     super(SpinnerActivity.class);  
  5. 5.     }  
  6. 6.  
  7. 7.     @Override  
  8. 8.     protected void setUp() throws Exception {  
  9. 9.         super.setUp();  
  10. 10.            // 添加自定义的初始化逻辑  
  11. 11.     }  
  12. 12.  
  13. 13.     @Override  
  14. 14.     protected void tearDown() throws Exception {  
  15. 15.            super.tearDown();  
  16. 16.     }  
  17. 17.  
  18. 18.     public void test测试用例() throws Exception {  
  19. 19.            // ...  
  20. 20.     }  
  21. 21. } 

ActivityInstrumentationTestCase2泛型类的参数类型是MainActivity,这样就指定了测试用例的待测活动,而且它只有一个构造函数——需要一个待测活动类型才能创建测试用例,其函数声明如下:
 

  1. ActivityInstrumentationTestCase2(Class<T> activityClass) 

传递的活动类型应该跟泛型类参数保持一致,代码清单3-5的第1~5行就演示了这个要求。

在Android SDK的示例工程“SpinnerTest”中,有一个很完整的ActivityInstrumentationTestCase2测试用例的示例,演示了Android仪表盘测试用例的一些最佳实践,如代码清单3-6所示。为了方便读者阅读,笔者将其中的注释用中文翻译过来。

在启动待测活动之前,先将触控模式禁用,以便控件能接收到键盘消息,如代码清单3-6的第54行。这是因为在Android系统里,如果打开触控模式,有些控件是不能通过代码的方式设置输入焦点的,手指戳到一个控件后该控件自然而然就获取到输入焦点了,例如戳一个按钮除了导致其获取输入焦点以外,还触发了其单击事件。而如果设备不支持触摸屏,例如老式的手机,需要先用方向键导航到按钮控件使其高亮显示,然后再按主键来触发单击事件。在Android系统中,出于多种因素的考虑,在触控模式下,除了文本编辑框等特殊的控件,可触控的控件如按钮、下拉框等无法设置其具有输入焦点。这样在自动化测试时,就会导致一个严重的问题,因为无法设置输入焦点,在发送按键消息时,就没办法知道哪个控件最终会接收到这些按键消息,一个简单的方案就是,在测试执行之前,强制待测应用退出触控模式。这样在93行,我们才能在代码中设置具有输入焦点的控件。

在测试集合中,应该有一个测试用例验证待测活动是否正常初始化,如69~78行之间的testPreconditions函数。

对界面元素的操作必须放在UI线程中执行,如90~97行的代码块。

代码清单3-6 Android示例工程SpinnerTest里的最佳实践
 

  1. 1. package com.android.example.spinner.test;  
  2. 2.  
  3. 3. import com.android.example.spinner.SpinnerActivity;  
  4. 4.  
  5. 5. import android.test.ActivityInstrumentationTestCase2;  
  6. 6. import android.view.KeyEvent;  
  7. 7. import android.widget.Spinner;  
  8. 8. import android.widget.SpinnerAdapter;  
  9. 9. import android.widget.TextView;  
  10. 10.  
  11. 11. public class SpinnerActivityTest  
  12. 12.     extends ActivityInstrumentationTestCase2<SpinnerActivity> {  
  13. 13.     // 下拉框选项数组mLocalAdapter中的元素个数  
  14. 14.     public static final int ADAPTER_COUNT = 9;  
  15. 15.  
  16. 16.     // Saturn这个字符串在下拉框选项数组mLocalAdapter的位置(从0开始计算)  
  17. 17.     public static final int TEST_POSITION = 5;  
  18. 18.  
  19. 19.     // 下拉框的初始位置应该是0  
  20. 20.     public static final int INITIAL_POSITION = 0;  
  21. 21.  
  22. 22.     // 待测活动的引用  
  23. 23.     private SpinnerActivity mActivity;  
  24. 24.  
  25. 25.     // 待测活动上下拉框当前显示的文本  
  26. 26.     private String mSelection;  
  27. 27.  
  28. 28.     // 下拉框当前的选择的位置  
  29. 29.     private int mPos;  
  30. 30.  
  31. 31.     // 待测活动里的下拉框对象的引用,通过仪表盘API来操作  
  32. 32.     private Spinner mSpinner;  
  33. 33.  
  34. 34.     // 待测活动里下拉框的数据来源对象  
  35. 35.     private SpinnerAdapter mPlanetData;  
  36. 36.  
  37. 37.     /*  
  38. 38.      * 创建测试用例对象的构造函数,必须在构造函数里调用基类  
  39. 39.      * ActivityInstrumentationTestCase2的构造函数,传入  
  40. 40.      * 待测活动的类型以便系统到时可以启动活动  
  41. 41.      */  
  42. 42.     public SpinnerActivityTest() {  
  43. 43.         super(SpinnerActivity.class);  
  44. 44.     }  
  45. 45.  
  46. 46.     @Override  
  47. 47.     protected void setUp() throws Exception {  
  48. 48.         // JUnit要求TestCase子类的setUp函数必须  
  49. 49.         // 调用基类的setUp函数  
  50. 50.         super.setUp();  
  51. 51.  
  52. 52.         // 关闭待测应用的触控模式,以便向下拉框发送按键消息  
  53. 53.         // 这个操作必须在getActivity()之前调用  
  54. 54.         setActivityInitialTouchMode(false);  
  55. 55.  
  56. 56.         // 启动待测应用并打开待测活动。  
  57. 57.         mActivity = getActivity();  
  58. 58.  
  59. 59.         // 获取待测活动里的下拉框对象,这样也可以确保待测活动  
  60. 60.         // 正确初始化  
  61. 61.         mSpinner = (Spinner)mActivity.findViewById(  
  62. 62.            com.android.example.spinner.R.id.Spinner01);  
  63. 63.         mPlanetData = mSpinner.getAdapter();  
  64. 64.     }  
  65. 65.  
  66. 66.     // 测试待测应用的一些关键对象的初始值,以此确保待测应用  
  67. 67.     // 的状态在测试过程中是有意义的,如果这个测试用例(函数)  
  68. 68.     // 失败了,基本上可以忽略其他测试用例的测试结果  
  69. 69.     public void testPreconditions() {  
  70. 70.         // 确保待测下拉框的选择元素的回调函数被正确设置  
  71. 71.         assertTrue(mSpinner.getOnItemSelectedListener() != null);  
  72. 72.  
  73. 73.         // 验证下拉框的选项数据初始化正常  
  74. 74.         assertTrue(mPlanetData != null);  
  75. 75.  
  76. 76.         // 并验证下拉框的选项数据的元素个数是正确的  
  77. 77.         assertEquals(mPlanetData.getCount(), ADAPTER_COUNT);  
  78. 78.     }  
  79. 79.  
  80. 80.     // 通过向待测活动的界面发送按键消息,在验证下拉框的状态  
  81. 81.     // 是否与期望的一致  
  82. 82.     public void testSpinnerUI() {  
  83. 83.         // 设置待测下拉框控件具有输入焦点,并设置它的初始位置。  
  84. 84.         // 因为这段代码需要操作界面上的控件,因此需要运行在  
  85. 85.         // 待测应用的线程中,而不是测试用例线程中  
  86. 86.         //  
  87. 87.         // 只需要将要在UI线程上执行的代码作为参数传入runOnUiThread  
  88. 88.         // 函数里就可以了,代码块是放在Runnable匿名对象  
  89. 89.         // 的run()函数里  
  90. 90.         mActivity.runOnUiThread(  
  91. 91.             new Runnable() {  
  92. 92.                 public void run() {  
  93. 93.                     mSpinner.requestFocus();  
  94. 94.                     mSpinner.setSelection(INITIAL_POSITION);  
  95. 95.                 }  
  96. 96.             }  
  97. 97.         );  
  98. 98.  
  99. 99.         // 使用手机物理键盘上方向键的主键激活下拉框  
  100. 100.         this.sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);  
  101. 101.  
  102. 102.         // 向下拉框发送5次向“下”按键消息  
  103. 103.         // 即高亮显示下拉框的第5个元素  
  104. 104.         for (int i = 1; i <= TEST_POSITION; i++) {  
  105. 105.             this.sendKeys(KeyEvent.KEYCODE_DPAD_DOWN);  
  106. 106.         }  
  107. 107.  
  108. 108.         // 选择下拉框当前高亮的元素  
  109. 109.         this.sendKeys(KeyEvent.KEYCODE_DPAD_CENTER);  
  110. 110.  
  111. 111.         // 获取被选元素的位置  
  112. 112.         mPos = mSpinner.getSelectedItemPosition();  
  113. 113.  
  114. 114.         // 从下拉框的选项数组mLocalAdapter中获取被选元素的数据  
  115. 115.         // (是一个字符串对象)  
  116. 116.         mSelection = (String)mSpinner.getItemAtPosition(mPos);  
  117. 117.  
  118. 118.         // 获取界面上显示下拉框被选元素的文本框对象  
  119. 119.         TextView resultView = (TextView) mActivity.findViewById(  
  120. 120.             com.android.example.spinner.R.id.SpinnerResult);  
  121. 121.  
  122. 122.         // 获取文本框的当前文本  
  123. 123.         String resultText = (String) resultView.getText();  
  124. 124.  
  125. 125.         // 验证下拉框显示的值的确是被选的元素  
  126. 126.         assertEquals(resultText,mSelection);  
  127. 127.     }  
  128. 128. } 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值