<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    qileilove

    blog已經(jīng)轉(zhuǎn)移至github,大家請(qǐng)?jiān)L問(wèn) http://qaseven.github.io/

    Android測(cè)試驅(qū)動(dòng)開(kāi)發(fā)實(shí)踐2

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

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

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

    導(dǎo)航

    統(tǒng)計(jì)

    常用鏈接

    留言簿(55)

    隨筆分類

    隨筆檔案

    文章分類

    文章檔案

    搜索

    最新評(píng)論

    閱讀排行榜

    評(píng)論排行榜

    主站蜘蛛池模板: 亚洲成a人无码亚洲成www牛牛 | 精品亚洲福利一区二区| 4hu四虎最新免费地址| 水蜜桃亚洲一二三四在线| 三年片免费高清版| 亚洲人JIZZ日本人| 国产在线精品一区免费香蕉| 国产亚洲精品影视在线产品| 人成午夜免费大片在线观看| 精品亚洲一区二区三区在线观看| 久久久WWW成人免费精品| 亚洲尤码不卡AV麻豆| 国产免费AV片在线观看| 亚洲欧洲日产国码久在线观看| 国产好大好硬好爽免费不卡| 亚洲一区免费观看| aa级一级天堂片免费观看| 亚洲人AV在线无码影院观看| 国产一级淫片a免费播放口之| 国产97视频人人做人人爱免费| 日韩精品亚洲aⅴ在线影院| 免费国产99久久久香蕉| 亚洲国产成人精品青青草原| 两个人的视频高清在线观看免费| 精品久久久久亚洲| 亚洲国产精彩中文乱码AV| 2021国内精品久久久久精免费| 亚洲人成人无码.www石榴| 亚洲国产综合人成综合网站| 国产免费拔擦拔擦8X高清在线人| 亚洲偷自精品三十六区| www亚洲精品少妇裸乳一区二区| 33333在线亚洲| 日韩视频在线免费观看| 一二三区免费视频| 亚洲成AV人综合在线观看| 国产成人精品免费视频软件| 在线成人精品国产区免费| 亚洲一区二区三区成人网站| 国产精品亚洲玖玖玖在线观看| 国产91免费在线观看|