言归正传,我们现在就开测试驱动开发。
首先建立一个Android工程,例如wkj,然后建立一个Android测试工程如WkjTest,这样就构成了一个Android测试开发的起点,下面就让我们正式开始Android测试驱动开发吧!我们开始编写第一个测试用例,由于是空工程,我们首先要测试的是MainActivity正确显示出AppModel所提供的应用名称-维康街。什么?Android创建的工程显示的是Hello World,怎么会是维康街?而且AppModel是个什么东西?细心的读者的这些问题没错,这就是测试驱动开发的工作模式:先写出失败的测试程序,然后再通过编程来通过这些测试用例。
打开WkjTest工作,创建新类MainActivityTest,并指定该类继承自android.test.ActivityInstrumentationTestCase2,代码如下所示:
package com.bjcic.wkj.test; import com.bjcic.wkj.MainActivity; import android.app.Activity; import android.test.ActivityInstrumentationTestCase2; import android.widget.TextView; public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> { public MainActivityTest() { super(MainActivity.class); } /** * 每个测试用例开始运行前必须执行的代码 */ @Override protected void setUp() throws Exception { super.setUp(); setActivityInitialTouchMode(false); activity = getActivity(); } /** * 每个测试用例运行结束时必须执行的代码 */ @Override protected void tearDown() throws Exception { super.tearDown(); } /** * 测试界面上标题文字为:维康街 */ public void testTemp001() { titleTxtv = (TextView)activity.findViewById(com.bjcic.wkj.R.id.j_titleTxtv); assertEquals(activity.getString(com.bjcic.wkj.R.string.welcome_msg), titleTxtv.getText()); } private Activity activity = null; private TextView titleTxtv = null; }
另外,注意我们对测试用例的命名,testTemp001,表明是临时性的测试用例。采用这种方式命名的测试用例,表明是在开发过程中使用的临时测试用例,不是用于回归测试中的正式测试用例。
下面开始编写功能性代码,来使这个测试用例通过。
还记得在本文开头处提到的MVC架构吗?现在我们就开始来一步步实现这个MVC架构。我们将Activity当作视图View,View读取Model中数据并显示到界面上,testTemp001这是为了测试这一工作模式。
在Android中怎样来实现一个Model呢?实现Model当然有很多种方式,我在这里采用扩展Application类来当作Model,即定义AppModel并继承Application,这样做的好处是Model不用采用Singleton模式也可以实现单例模式了,而且可以很方便在Activity中获取到。在我们这个最简单的应用中,需要Model中存在welcom_msg信息,这时在MainActivity中才可以通过向Model请求数据并显示在界面中。
AppModel类如下所示:
package com.bjcic.wkj; import android.app.Application; public class AppModel extends Application { // 生命周期方法开始 public void onCreate() { super.onCreate(); welcomeMsg = getString(R.string.welcome_msg); } public void onTerminate() { super.onTerminate(); } // 生命周期方法结束 private String welcomeMsg = null; public String getWelcomeMsg() { return welcomeMsg; } public void setWelcomeMsg(String welcomeMsg) { this.welcomeMsg = welcomeMsg; } }
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); appModel = (AppModel)getApplication(); } @Override public void onResume() { super.onResume(); ((TextView)findViewById(R.id.j_titleTxtv)).setText(appModel.getWelcomeMsg()); } private AppModel appModel = null;
<application android:allowBackup="true" android:name=".AppModel" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" >