第10章 其他测试策略
10.5 Robotium介绍
新型的大型机器人其中一个组件就是Robotium(http://code.google.com/p/robotium/),它是一个测试框架,用来简化编写测试用例的过程,需要了解被测应用的最小知识集合。Robotium主要是面向写一些强大的、自动化的黑盒Android测试用例。它可以覆盖功能型、系统、验收测试场景,甚至可以在同一个应用中,自动操作多个Android行为。
Robotium还可以用来测试那些我们不知道源代码的应用,甚至预设应用。
Robotium支持所有的行为、对话、弹出框,菜单以及上下文菜单。
我们现在就用Robotium来为TemperatureConverter新建一些测试用例。为了测试用例的组织结构好一点,我们给新建的包命名叫做com.example.aatg.tc.tests.robotium,放在TemperatureConverterTest工程里面。在这个包下面,我们正在给测试用例新建一个类,因为要开始测试TemperatureConverterActivity了。我们可以取名为TemperatureConverterActivityTests,虽然在另外一个包也有同样名字的类,那个类扩展了ActivityInstrmentationTestCase2,不过因为不在同一个包下面,名字相同也没事。毕竟,这两个测试类都是用来测试同一个活动的。
10.5.1 下载Robotium
我们需要下载robotoim-solo 的JAR包文件以及它对应的Javadoc文件,把这两个文件添加到工程中去。访问Robotium下载页面(http://code.google.com/p/robotium/downloads/list),然后选一个最新的版本,在本书编写的时候,最新版本是robotium-solo-2.1.jar。
10.5.2 工程设置
我们需要在TemperatureConverterTest工程属性的JAVA Build Path|libraries中添加这个jar包。添加好了之后,你展开这个节点,选中JAVAdoc in archive选项,添加Javadoc的地址,指向压缩的JAR文件。
10.5.3 新建测试用例
从前面的章节,我们知道如果为活动创建了测试用例,这些测试用例应该连接到系统的基础设施上执行,因此我们要将测试用例继承ActivitInstrumentationTestCase2,这也是接下来要做的事情。
10.5.4 testFahrenheitToCelsiusConversion()测试
测试用例的结构跟基于Instrumentation类写的测试用例或多或少有点类似。不同之处在于我们需要实例化Robotium的Solo,在测试用例的setUp()中实例化,然后再tearDown()中finalize()掉,如框10.18所示。
框10.18
package com.example.aatg.tc.test.robotium; import android.test.ActivityInstrumentationTestCase2; import com.example.aatg.tc.TemperatureConverterActivity; import com.jayway.android.robotium.solo.Solo; /** * @author diego * */ public class TemperatureConverterActivityTests extends ActivityInstrumentationTestCase2<TemperatureConverterActivity> { private Solo mSolo; private TemperatureConverterActivity mActivity; /** * @param name */ public TemperatureConverterActivityTests(String name) { super(TemperatureConverterActivity.class); setName(name); } /* (non-Javadoc) * @see android.test.ActivityInstrumentationTestCase2#setUp() */ protected void setUp() throws Exception { super.setUp(); mActivity = getActivity(); mSolo = new Solo(getInstrumentation(), mActivity); } /* (non-Javadoc) * @see android.test.ActivityInstrumentationTestCase2#tearDown() */ protected void tearDown() throws Exception { try { mSolo.finalize(); } catch (Throwable ex) { ex.printStackTrace(); } mActivity.finish(); super.tearDown(); } } |
要实例化Solo,我们需要把引用传给Instrumentation和被测的活动。
另一方面,要结束Solo,我们可以调用finalize()方法,然后结束掉这个行为,最后调用super.tearDown()。
Solo提供了很多方法来驱动UI测试和断言。让我们从重写testFahrenheitToCelsiusConversion()开始,之前采用的是传统方法,但是这个用例中用Solo提供的方法,如框10.19所示。
框10.19
public final void testFahrenheitToCelsiusConversion() { mSolo.clearEditText(CELSIUS); mSolo.clearEditText(FAHRENHEIT); final double f = 32.5d; mSolo.clickOnEditText(FAHRENHEIT); mSolo.enterText(FAHRENHEIT, Double.toString(f)); mSolo.clickOnEditText(CELSIUS); final double expectedC = TemperatureConverter.fahrenheitToCelsius(f); final double actualC = Double.parseDouble(mSolo.getEditText(CELSIUS). getText().toString()); final double delta = Math.abs(expectedC - actualC); final String msg = "" + f + "F -> " + expectedC + "C but was " + actualC + "C (delta " + delta + ")"; assertTrue(msg, delta < 0.005); } |
这里很类似,不过你注意到的第一个不同点在于,这个用例我们没有像之前那样获取UI元素指针,之前是在setUp()方法中用findViewById()来定位视图的。这里,我们利用了Solo最大的一个优势,就是用一些标准来定位视图。这个用例中,标准就是他们在屏幕上展示的顺序,因为他们的索引都分配好了。mSolo.clearEditTest(int index)方法入参是元素在屏幕上的位置,用int索引表示,从0开始计算。因此,我们在测试用例中给这些常量赋值,对应UI上的元素,摄氏度这个字段是在最上面,华氏温度区域是在下面:
private static final int CELSIUS = 0;
private static final int FAHRENHEIT = 1;
另一个方法也是同样的方式,必要的时候就会提供这些常量。这个测试用例跟com.example.aatg.tc.test.TemperatureConverteerActivityTest很像,但是仔细观察,你会发现细小的不同点。这里我们站在一个更高的角度,不用去担心交互或者执行细节;比如,在我们之前的测试用例中,调用mCelsius.requestFocus()来触发温度转换,但是这里,我们只是模拟了用户操作,调用mSolo.clickOnEditTest(CelSius)。
正因为这点,我们也同样不想用EditNumber.getNumber()。我们只需要获得屏幕上文本框中的数据,转换成Double型,然后跟预期值对比。
我们切合实际地简化了测试用例,但是Solo的最大优势还没有显示出来,即将开始。
10.5.5 再访testOnCreateOptionsMenu()
自从宣布要实现testOnCreteOptionsMenu()以来,你可能等这一刻已久。这次我们要站在更高的角度,不处理这些细节。在单击菜单选项的时候,唤起一个新的活动,这已经不是我们的问题了;我们只需要从UI的视觉角度来处理这个用例。
下面截图展示了小数点区域的对话框,如图10.3所示。
我们的目的是将小数点区域的值变成5,然后验证这个变化的真实发生效果。
下面这段代码片段描述了测试用例的详细情况,如框10.20所示。
本文选自《Android应用测试指南》第十章,本站经人民邮电出版社和作者的授权。
版权声明:51Testing软件测试网获人民邮电出版社和作者授权连载本书部分章节。
任何个人或单位未获得明确的书面许可,不得对本文内容复制、转载或进行镜像,否则将追究法律责任。