qileilove

          blog已經轉移至github,大家請訪問 http://qaseven.github.io/

          Android測試驅動開發實踐2

           在實際項目開發過程中,一般先實現核心功能,最后再做輔助性功能,這樣可以盡快驗證Idea的正確性,同時有助于讓老板、投資人或客戶看到可運行的產品,從而對產品充滿信心,加大對項目的支持。
            但是對于我們這個項目而言,我們首先需要得到一個Android應用MVC的架構體系,因此我們首先來實現一些典型功能,但是可以完整體現MVC架構的功能。在此我們選擇任何應用程序在啟動時都會顯示的Splash頁面,通常這個頁面會顯示一個應用圖片,過30秒左右再顯示程序的主界面,應用在這段時間完成數據加載等準備工作
            在這里我們要稍微背離一下測試驅動開發的標準方法,原因是我們在進行Android應用開發,由于Android系統限制有很多方面是很難做單元測試的,硬做單元測試,除了理論上的有效性外,沒有任何實際意義。
            在這里,我們采用驗收測試驅動開發的理念,即我們開發足夠功能來滿足一個驗收測試用例。這里我們選擇的一個驗收測試用例為:應用在開啟時,先顯示10秒應用圖片,然后自動進入應用首頁,也就是我們通常所看到的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);
          // 啟動異步任務準備應用數據
          }
          // 生命周期方法---結束
          private AppController appController = null;
          private AppModel appModel = null;
          }
          這個Activity所對應的布局文件為:
          <?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類,是應用的控制器類。Activity中用戶的操作和系統的狀態改變都會生成相應的事件,由AppController.processEvent來進行統一處理,同時異步任務、線程等產生的需要界面更新的操作,通過向AppController發送Message來實現(因為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中會根據用戶的操作或系統狀態,產生對應的事件,發送給AppController進行統一處理。
          * @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;
          }
          }
          /**
          * 異步任務、線程、后臺服務等需要更新界面時,向AppController發送消息即可
          */
          @Override
          public void handleMessage(Message msg) {
          super.handleMessage(msg);
          }
          /**
          * 關閉Splash頁面并打開應用主界面
          * @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;
          }
           在上面的代碼中,事件處理函數直接寫在的應用總的Controller中,其實也可以寫到具體的Controller中,為了代碼的可維護性,最好還是將事件處理寫到對應模塊的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;
          }
            在上面的事件定義中,事件中包含當前的Activity,事件ID和事件參數,這樣AppController就可以直接對事件進行處理了。
            最后,我們在Splash頁面停留10秒,這里需要定義一個常量,我們將應用中需要用到的重要常量,統一定義到AppKeys中,如下所示:
          package com.bjcic.wkj;
          public class AppKeys {
          public final static long SPLASH_DURATION = 10 * 1000;
          }
            好的,現在可以運行這個應用程序了,如果一切正常,應該可以看到一個Splash頁面顯示10秒鐘后,進入到程序主界面中。至此我們的第一個驗收測試用例就順利通過了。
            這時,我們再回到WkjTest這個工程中,以Android Junit形式運行MainActivityTest,這時應該顯示所有測試用例全部通過。
            注:大家也許注意到了,測試驅動開發是以一小步一小步的開發測試為基礎的,在實際工作中,有一半愉上的程序員喜歡先把所有代碼寫好,然后在進行調試。當然也有一部分開發人員寫一點調一點,這純屬于習慣性問題,不存在孰優孰劣的問題。但是采用測試驅動開發方法學,就要采用后面的工作方式。
            因此,測試驅動開發不一定適合所有人,對于喜歡一次性先把代碼寫好,然后進行調試的人來說,讓他們接受測試驅動開發的工作方式是很困難的,這一點希望大家能夠重視起來。
          相關文章:

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

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

          導航

          統計

          常用鏈接

          留言簿(55)

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 威远县| 若羌县| 惠来县| 莲花县| 太白县| 龙山县| 综艺| 桃园县| 仪陇县| 方山县| 平阳县| 新营市| 庐江县| 周至县| 美姑县| 凤城市| 康保县| 西青区| 乐陵市| 长丰县| 双鸭山市| 卢湾区| 葫芦岛市| 木里| 彭水| 德昌县| 长海县| 合作市| 来宾市| 铜陵市| 镇安县| 凤台县| 都昌县| 营山县| 台北县| 通化县| 泰来县| 砚山县| 嘉义县| 赤城县| 天镇县|