qileilove

          blog已經(jīng)轉(zhuǎn)移至github,大家請訪問 http://qaseven.github.io/

          Android測試驅(qū)動開發(fā)實踐2

           在實際項目開發(fā)過程中,一般先實現(xiàn)核心功能,最后再做輔助性功能,這樣可以盡快驗證Idea的正確性,同時有助于讓老板、投資人或客戶看到可運行的產(chǎn)品,從而對產(chǎn)品充滿信心,加大對項目的支持。
            但是對于我們這個項目而言,我們首先需要得到一個Android應(yīng)用MVC的架構(gòu)體系,因此我們首先來實現(xiàn)一些典型功能,但是可以完整體現(xiàn)MVC架構(gòu)的功能。在此我們選擇任何應(yīng)用程序在啟動時都會顯示的Splash頁面,通常這個頁面會顯示一個應(yīng)用圖片,過30秒左右再顯示程序的主界面,應(yīng)用在這段時間完成數(shù)據(jù)加載等準備工作
            在這里我們要稍微背離一下測試驅(qū)動開發(fā)的標準方法,原因是我們在進行Android應(yīng)用開發(fā),由于Android系統(tǒng)限制有很多方面是很難做單元測試的,硬做單元測試,除了理論上的有效性外,沒有任何實際意義。
            在這里,我們采用驗收測試驅(qū)動開發(fā)的理念,即我們開發(fā)足夠功能來滿足一個驗收測試用例。這里我們選擇的一個驗收測試用例為:應(yīng)用在開啟時,先顯示10秒應(yīng)用圖片,然后自動進入應(yīng)用首頁,也就是我們通常所看到的Splash屏幕功能。
            我們首先定義SplashActivity類,代碼如下所示:
          package com.bjcic.wkj;
          import android.app.Activity;
          import android.content.Intent;
          import android.os.Bundle;
          import android.view.WindowManager;
          public class SplashActivity extends Activity {
          // 生命周期方法---開始
          @Override
          protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          //全屏
          setContentView(R.layout.splash);
          getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
          WindowManager.LayoutParams.FLAG_FULLSCREEN);
          appModel = (AppModel)getApplication();
          appController = appModel.getAppController();
          appController.postDelayed(new Runnable() {
          /**
          * 隔10秒鐘啟動主頁面
          */
          @Override
          public void run() {
          appController.processEvent(new AppEvent(SplashActivity.this, AppEvent.EVE_SPLASH_END, null));
          }
          }, AppKeys.SPLASH_DURATION);
          // 啟動異步任務(wù)準備應(yīng)用數(shù)據(jù)
          }
          // 生命周期方法---結(jié)束
          private AppController appController = null;
          private AppModel appModel = null;
          }
          這個Activity所對應(yīng)的布局文件為:
          <?xml version="1.0" encoding="utf-8"?>
          <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:orientation="vertical"
          android:background="@drawable/splash">
          </LinearLayout>
            布局文件就是定義了一下Splash屏幕的背景圖。
            這里我們引入了AppController類,是應(yīng)用的控制器類。Activity中用戶的操作和系統(tǒng)的狀態(tài)改變都會生成相應(yīng)的事件,由AppController.processEvent來進行統(tǒng)一處理,同時異步任務(wù)、線程等產(chǎn)生的需要界面更新的操作,通過向AppController發(fā)送Message來實現(xiàn)(因為AppController繼承了Handler類)。具體代碼如下所示:
          package com.bjcic.wkj;
          import android.app.Activity;
          import android.content.Intent;
          import android.os.Bundle;
          import android.os.Handler;
          import android.os.Message;
          import android.util.Log;
          public class AppController extends Handler {
          public AppController(AppModel appModel) {
          super();
          this.appModel = appModel;
          }
          /**
          * Activity中會根據(jù)用戶的操作或系統(tǒng)狀態(tài),產(chǎn)生對應(yīng)的事件,發(fā)送給AppController進行統(tǒng)一處理。
          * @param event
          */
          public void processEvent(AppEvent event) {
          switch (event.getEventId()) {
          case AppEvent.EVE_SPLASH_END: // 從Splash界面顯示主界面
          showMainActivity((Activity)event.getContext(), event.getParams());
          break;
          default:
          break;
          }
          }
          /**
          * 異步任務(wù)、線程、后臺服務(wù)等需要更新界面時,向AppController發(fā)送消息即可
          */
          @Override
          public void handleMessage(Message msg) {
          super.handleMessage(msg);
          }
          /**
          * 關(guān)閉Splash頁面并打開應(yīng)用主界面
          * @param activity
          * @param params
          */
          private void showMainActivity(Activity activity, Bundle params) {
          Log.d("wkj", "activity=" + activity + "; c=" + MainActivity.class + "!");
          Intent intent = new Intent(activity, MainActivity.class);
          activity.startActivity(intent);
          activity.finish();
          }
          private AppModel appModel = null;
          }
           在上面的代碼中,事件處理函數(shù)直接寫在的應(yīng)用總的Controller中,其實也可以寫到具體的Controller中,為了代碼的可維護性,最好還是將事件處理寫到對應(yīng)模塊的Controller中比較好。
            下面就是AppEvent的定義:
          package com.bjcic.wkj;
          import android.content.Context;
          import android.os.Bundle;
          public class AppEvent {
          public AppEvent(Context context, int eventId, Bundle params) {
          this.context = context;
          this.eventId = eventId;
          this.params = params;
          }
          public Context getContext() {
          return context;
          }
          public void setContext(Context context) {
          this.context = context;
          }
          public Bundle getParams() {
          return params;
          }
          public int getEventId() {
          return eventId;
          }
          public void setEventId(int eventId) {
          this.eventId = eventId;
          }
          public final static int EVE_NONE = 0;
          public final static int EVE_SPLASH_END = 1; // Splash界面顯示時間到期
          private Context context = null;
          private int eventId = 0;
          private Bundle params = null;
          }
            在上面的事件定義中,事件中包含當(dāng)前的Activity,事件ID和事件參數(shù),這樣AppController就可以直接對事件進行處理了。
            最后,我們在Splash頁面停留10秒,這里需要定義一個常量,我們將應(yīng)用中需要用到的重要常量,統(tǒng)一定義到AppKeys中,如下所示:
          package com.bjcic.wkj;
          public class AppKeys {
          public final static long SPLASH_DURATION = 10 * 1000;
          }
            好的,現(xiàn)在可以運行這個應(yīng)用程序了,如果一切正常,應(yīng)該可以看到一個Splash頁面顯示10秒鐘后,進入到程序主界面中。至此我們的第一個驗收測試用例就順利通過了。
            這時,我們再回到WkjTest這個工程中,以Android Junit形式運行MainActivityTest,這時應(yīng)該顯示所有測試用例全部通過。
            注:大家也許注意到了,測試驅(qū)動開發(fā)是以一小步一小步的開發(fā)測試為基礎(chǔ)的,在實際工作中,有一半愉上的程序員喜歡先把所有代碼寫好,然后在進行調(diào)試。當(dāng)然也有一部分開發(fā)人員寫一點調(diào)一點,這純屬于習(xí)慣性問題,不存在孰優(yōu)孰劣的問題。但是采用測試驅(qū)動開發(fā)方法學(xué),就要采用后面的工作方式。
            因此,測試驅(qū)動開發(fā)不一定適合所有人,對于喜歡一次性先把代碼寫好,然后進行調(diào)試的人來說,讓他們接受測試驅(qū)動開發(fā)的工作方式是很困難的,這一點希望大家能夠重視起來。
          相關(guān)文章:

          posted on 2013-12-20 09:21 順其自然EVO 閱讀(229) 評論(0)  編輯  收藏 所屬分類: android

          <2013年12月>
          24252627282930
          1234567
          891011121314
          15161718192021
          22232425262728
          2930311234

          導(dǎo)航

          統(tǒng)計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 镇坪县| 准格尔旗| 南昌市| 靖边县| 上思县| 凤凰县| 都安| 卢氏县| 安宁市| 左云县| 民权县| 梁平县| 疏勒县| 珲春市| 河池市| 宁都县| 黑龙江省| 永康市| 娄烦县| 墨玉县| 四会市| 和平县| 建湖县| 旬阳县| 新安县| 五台县| 西和县| 泰州市| 石泉县| 连江县| 安多县| 桦甸市| 安龙县| 长垣县| 湟源县| 连南| 广德县| 潮州市| 东源县| 聂荣县| 贵阳市|