• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • Android單元測試在蘑菇街支付金融部門的實踐(3)

    發表于:2016-06-12來源:推酷作者:鄒小創點擊數: 標簽:單元測試
    使用這種方式,所有production code都不用專門為testing增加任何多余的代碼,同時還能得到依賴注入的其他好處。 Robolectric:解決Android單元測試最大的痛點

      使用這種方式,所有production code都不用專門為testing增加任何多余的代碼,同時還能得到依賴注入的其他好處。

      Robolectric:解決Android單元測試最大的痛點

      接下來講講Android單元測試最大的痛點,那就是JVM上面運行純JUnit單元測試時是不能使用Android相關的類的,因為我們開發用到的安卓環境是沒有實現的,里面只定義了一些接口,所有方法的實現都是throw new RuntimeException("stub");,如果我們單元測試代碼里面用到了安卓相關的代碼的話,那么運行時就會遇到RuntimeException("Stub")。

      要解決這個問題,一般來說有三種方案:

      使用Android提供的Instrumentation系統,將單元測試代碼運行在模擬器或者是真機上。

      用一定的架構,比如MVP等等,將安卓相關的代碼隔離開了,中間的Presenter或Model是存java實現的,可以在JVM上面測試。View或其他android相關的代碼則不測。

      使用Robolectric框架,這個框架基本可以理解為在JVM上面實現了一套安卓的模擬環境,同時給安卓相關的類增加了其他一些增強的功能,以方便做單元測試,使用這個框架,我們就可以在JVM上面跑單元測試的時候,就可以使用安卓相關的類了。

      第一種方案能work,但是速度非常慢,因為每次運行一次單元測試,都需要將整個項目打包成apk,上傳到模擬器或真機上,就跟運行了一次app似得,這個顯然不是單元測試該有的速度,更無法做TDD。這種方案首先被否決。

      剛開始,我們采用的是Robolectric,原因有兩個:1. 我們項目當時還沒有比較清楚的架構,android跟純java代碼的隔離沒有做好;2. 很多安卓相關的代碼,還是需要測試的,比如說自定義View等等。然而慢慢的,我們的態度從擁抱Robolectric,到盡量不用它,盡量使用純java代碼去實現??赡艽蠹矣X得安卓相關的代碼會很多,而純java的很少,然而慢慢的你會發現,其實不是這樣的,純java的代碼其實真不少,而且往往是核心的邏輯所在。之所以盡量不用Robolectric,是因為Robolectric雖然相對于Instrumentation testing來說快多了。但畢竟他也需要merge一些資源,build出來一個模擬的app,因此相對于純java和JUnit來說,這個速度依然是很慢的。

      用具體的數字來對比說明:

      運行Instrumentation testing:幾十秒,取決于app的大小

      Robolectric:10秒左右

      JUnit:幾秒鐘之內

      當然,雖然運行一次Robolectric在10秒左右,但是對比運行一次app,還是要快太多。因此,剛開始的時候,從Robolectric開始完全是OK的。

      以上就是現在我們這邊單元測試用到的幾個基本技術:JUnit4 + Mockito + Dagger2 + Robolectric?;緛碚f,并沒有什么黑科技,都是業界標準。

      一個具體的案例

      接下來,我通過一個具體的案例,跟大家介紹一下,我們這邊的一個app,具體是怎么單測的。

      這里是我們收銀臺界面的樣子:

      假設Activity名字為CheckoutActivity,當它啟動的時候,CheckoutActivity會去調一個CheckoutModel的loadCheckoutData()方法,這個方法又會去調更底層的一個封裝了用戶認證等信息的網絡請求Api類(mApi)的get方法,同時傳給這個Api類一個callback。這個callback的做的事情是將結果通過Otto Bus(mBus) post出去。CheckoutActivity里面Subscribe了這個Event(方法名是onCheckoutDataLoaded()),然后根據Event的值相應的顯示數據或錯誤信息。

      代碼簡寫如下:

      public class CheckoutActivity extends Activity {

      @Override

      protected void onCreate(Bundle savedInstanceState) {

      // other code, like setContentView, get data from Intent, etc.

      mCheckoutModel.loadCheckoutData(paymentId);

      }

      @Subscribe

      public void onCheckoutDataLoaded(DataLoadedEvent event) {

      if (event.successful()) {

      //Get data from event and update UI

      } else {

      //show error message

      }

      }

      }

      public class CheckoutModel {

      public void loadCheckoutData(String paymentId) {

      //Other code, like composing params

      mApi.get(someUrl, someParams, new NetworkCallback() {

      @Override

    原文轉自:http://www.jianshu.com/p/9f7a992fe9ec

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>