在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Android/ 安卓測(cè)試驅(qū)動(dòng)開發(fā)/安卓測(cè)試驗(yàn)證
Launch mode 和 Intent flags專題
Canvas & Drawables
UTAustinX_UT.9.01x: Effective Thinking Through Mathematics
《JavaScript 語(yǔ)言精粹》
Memory leak專題
React基礎(chǔ)
《Test Driven Development: By Example》一書
Developer tools
安卓開發(fā)技能樹
<a rel="nofollow" href="https://mp.weixin.qq.com/s?__biz=MzA3NDM
Best Practices for Interaction and Engagement
各個(gè)安卓版本引入的主要新特性
Building Apps with Connectivity &amp; the Cloud
List.toArray()再?gòu)?qiáng)轉(zhuǎn)是一定會(huì)失敗的
深入Android frameworks
Google dev 100 days系列視頻
Building Apps with Contacts &amp; Sign-In
關(guān)系型數(shù)據(jù)庫(kù)設(shè)計(jì)范式
《App研發(fā)錄》一書
REST API設(shè)計(jì)
Google IO 2015摘要
自定義View/ViewGroup以及高性能實(shí)現(xiàn)自定義UI
安卓系統(tǒng)點(diǎn)擊事件處理
《50 Android Hacks》一書
Building Apps with Content Sharing
Flux基礎(chǔ)
<a rel="nofollow" href="http://developer.android.com/training/in
依賴注入(以Dagger 2為例)
Java同步機(jī)制
Java對(duì)象內(nèi)存的使用情況
JSR133(Java memory model)
Google官方Material Design手冊(cè)(<a rel="nofollow" href="http://develop
Futurice公司安卓團(tuán)隊(duì)的建議
安卓性能優(yōu)化
  • 1.
Best Practices for Performance
<a rel="nofollow" href="http://www.vogella.com/tutorials/Android
<a rel="nofollow" href="http://blog.danlew.net/2014/11/19/styles
Handling Runtime Changes
<a rel="nofollow" href="http://www.vogella.com/tutorials/Android
Building Apps with Graphics &amp; Animation
<a rel="nofollow" href="http://tools.android.com/tech-docs/new-b
Android項(xiàng)目架構(gòu)
MVP(Model-View-Presenter)模式
<a rel="nofollow" href="http://www.infoq.com/cn/es6-in-depth/"">
《Android源碼設(shè)計(jì)模式解析與實(shí)戰(zhàn)》一書
Rx在Android中的最佳實(shí)踐
函數(shù)調(diào)用時(shí),傳遞參數(shù)應(yīng)該是不可變的(Immutable)
ProGuard
面向?qū)ο罅笤瓌t(SOLID+)
深入理解Java虛擬機(jī)
深入Java深淺拷貝、immutable、unmodifiable
Best Practices for User Input
UI上的一些高效方式/最佳實(shí)踐
<a rel="nofollow" href="https://blog.stylingandroid.com/ripples-
Best Practices for User Interface
安卓測(cè)試驅(qū)動(dòng)開發(fā)/安卓測(cè)試驗(yàn)證
暗時(shí)間:學(xué)會(huì)正確思考
技術(shù)筆記
Aspect Oriented Programming(AOP)
Best Practices for Background Jobs
安卓系統(tǒng)動(dòng)效專題
Feed系統(tǒng)的設(shè)計(jì)
Data binding(MVVM,Model-View-ViewModel)
Effective Java一書筆記
<a rel="nofollow" href="http://developer.android.com/training/in
Rx (Reactive eXtention)
MultiDex專題
一些很棒的點(diǎn)子
WebRTC

安卓測(cè)試驅(qū)動(dòng)開發(fā)/安卓測(cè)試驗(yàn)證

安卓測(cè)試主要包括兩種:?jiǎn)卧獪y(cè)試;集成測(cè)試;測(cè)試主要通過(guò)mock依賴,驗(yàn)證行為。 Mock框架、單元測(cè)試框架、集成測(cè)試框架是TDD所需的主要工具。

Mock框架:Mockito

  • stubbed的方法沒有必要verify
  • 當(dāng)被測(cè)代碼對(duì)返回值不關(guān)心時(shí),不要stub
  • mock對(duì)象的方法默認(rèn)將返回空值(null,空集合,默認(rèn)基本類型值)
  • stub可以被重載,但當(dāng)出現(xiàn)這種需求時(shí),就說(shuō)明stub已經(jīng)太多了,需要改進(jìn)設(shè)計(jì)
  • stub的順序有影響,但不應(yīng)依賴其順序的影響
  • 默認(rèn)使用Java原生equals進(jìn)行判斷,也支持ArgumentMatcher,有內(nèi)置, 也支持自定義/Hamcrest,但最后者不建議使用(影響可讀性)
  • 一旦使用了ArgumentMatcher,則所有的參數(shù)都要使用ArgumentMatcher
  • times(int),never(),atLeastOnce(),atLeast(int), atMost(int)驗(yàn)證調(diào)用次數(shù),verify默認(rèn)的是times(1),因此無(wú)需顯式指定
  • 驗(yàn)證無(wú)返回值函數(shù)拋出異常:doThrow(new RuntimeException()).when(mockedList).clear();
  • InOrder可以驗(yàn)證調(diào)用的順序(不同語(yǔ)句),原則上只需要驗(yàn)證關(guān)鍵邏輯,沒必要 所有調(diào)用都需要驗(yàn)證、甚至其順序
  • only()的語(yǔ)義:僅有該方法被調(diào)用,且僅被調(diào)用一次
  • never()的語(yǔ)義:該方法未被調(diào)用過(guò)
  • verifyZeroInteractions(...)的語(yǔ)義:mock對(duì)象沒有任何方法調(diào)用
  • verifyNoMoreInteractions(...):驗(yàn)證沒有其他的調(diào)用(除了此前驗(yàn)證的方法)
  • 對(duì)多次調(diào)用進(jìn)行stub,最后一次將一直有效
  • doReturn()|doThrow()| doAnswer()|doNothing()|doCallRealMethod() family of methods
  • spy,對(duì)真實(shí)對(duì)象進(jìn)行spy,部分mock。但是spy對(duì)象的操作和原有真實(shí)對(duì)象的操作是獨(dú)立的
  • Capturing arguments for further assertions,在verify中可以捕獲調(diào)用的參數(shù),后續(xù)進(jìn)行驗(yàn)證
  • reset mock,不建議使用
  • BDD,given, when, then
  • mock對(duì)象可以序列化
  • Verification with timeout
  • (new) Better generic support with deep stubs (Since 1.10.0)
  • How to mock dependencies in Unit, Integration and Functional tests; Dagger, Robolectric and Instrumentation
  • Testing made sweet with a Mockito

Assertion框架

單元測(cè)試:The Square Way

  • 單元測(cè)試是方法級(jí)別的測(cè)試,需要測(cè)試的是一個(gè)類的公開接口/方法,測(cè)試其邏輯正確性, 如果發(fā)現(xiàn)一個(gè)類的某個(gè)方法所使用的依賴難以mock,it's a smell,重構(gòu)吧
  • 基礎(chǔ)理論部分
    • The three steps of a unit test: arrange, act, and assert
    • check the return value of the method
    • get a reference to some publicly accessible property of the object being tested
    • check the state of the object’s injected dependencies
    • 所以編碼時(shí),應(yīng)該盡量將代碼邏輯的依賴通過(guò)注入的方式(或提供public setter, 或?qū)⒈粶y(cè)函數(shù)的依賴作為參數(shù)傳入)提供,以便于測(cè)試
    • post-act-state的驗(yàn)證要注意單元測(cè)試與集成測(cè)試的區(qū)別:?jiǎn)卧獪y(cè)試只驗(yàn)證 一個(gè)方法的邏輯正確性,不驗(yàn)證多個(gè)方法(模塊)一起工作的邏輯正確性;
    • static方法對(duì)測(cè)試非常不利,因?yàn)槠鋵?duì)象依賴、方法依賴無(wú)法mock, 而其post-act-state也通常無(wú)法assert,開發(fā)過(guò)程中應(yīng)盡量避免
  • 實(shí)踐部分
    架構(gòu)圖
    http://wiki.jikexueyuan.com/project/notes/images/androidstack-02.png" alt="androidstack-02.png" />
    Remove all business logic from app component classes (e.g., Activitys, Fragments, Services) and place that logic into "business objects", POJO objects whose dependencies are injected, android-specific implementations of android-agnostic interfaces.
    Delegate all application specific behavior to POJO objects whose dependencies are Android-specific implementations of Android-agnostic interfaces.
    • Non-UI App Components
      • 把業(yè)務(wù)邏輯(比如根據(jù)數(shù)據(jù)類型執(zhí)行不同操作、檢查數(shù)據(jù)合法性等)從組件類中 抽離出來(lái),業(yè)務(wù)邏輯類對(duì)于組件類的依賴也不要直接使用,而是通過(guò)定義接口來(lái) 進(jìn)行轉(zhuǎn)發(fā)調(diào)用,這樣就能使得業(yè)務(wù)邏輯類與SDK解耦。
      • 業(yè)務(wù)邏輯類的依賴通過(guò)依賴注入框架注入,便于測(cè)試時(shí)mock。
      • 而剩下的組件類工作簡(jiǎn)單,只負(fù)責(zé)轉(zhuǎn)發(fā)業(yè)務(wù)邏輯類的功能請(qǐng)求,就沒必要進(jìn)行測(cè)試了。
    • UI App Component Classes
      • 通過(guò)MVP模式,將UI組件類和業(yè)務(wù)邏輯類解耦,同時(shí)移除對(duì)SDK組件類的依賴;
      • pre-act-state,post-act-state,測(cè)試對(duì)象的依賴中,如果mock框架 (如Mockito)可以mock,OK;如果不能mock(例如Activity,BroadcastReceiver) ,則可以通過(guò)定義接口的形式替換這些依賴,而接口的實(shí)現(xiàn)則是簡(jiǎn)單直接的轉(zhuǎn)發(fā),無(wú)需測(cè)試; pre-act-state便可以設(shè)置完畢,調(diào)用被測(cè)函數(shù)后,驗(yàn)證post-act-state即可。
    • Dependency Inject
      • 可以使用Constructor inject的類就不要使用Field inject。前者更利于單元測(cè)試。 其實(shí)除了SDK組件類,其他的類基本上都可以使用Constructor inject。
    • 無(wú)需依賴第三方框架(Robolectric,Dagger)
  • 單元測(cè)試的目標(biāo)
    • 在非安卓系統(tǒng)組件相關(guān)的代碼,直接每個(gè)方法進(jìn)行測(cè)試,很好理解
    • 系統(tǒng)組件相關(guān)的代碼,主要測(cè):試依賴于生命周期函數(shù)的邏輯;由簡(jiǎn)單UI交互引發(fā)的邏輯; 自定義接口的邏輯(如MVP中的View);
  • 與其他框架/工具的整合

    • RxJava

      • Rx為異步而生,但測(cè)試往往需要同步進(jìn)行驗(yàn)證
      • 可通過(guò)myObservable.toBlocking().first();進(jìn)行同步
      • 也可通過(guò)官方的TestSubscriber,該類提供了眾多實(shí)用的方法,例如同步獲取 Observable發(fā)射的所有對(duì)象,斷言沒有onError,等待onComplete等
      • 處理生產(chǎn)代碼中的異步問(wèn)題,可以在測(cè)試時(shí)hook Schedulers.io()Schedulers.immediate(),但在hook之前需要reset RxJavaPlugins, 在RxJava中這個(gè)方法是package private,所以做到這點(diǎn)有點(diǎn)hack,在RxAndroid中則 無(wú)需如此麻煩,因?yàn)榛蛘逺xAndroid提供了很好的hook支持。

            package rx.plugins;
        
            public class RxJavaTestPlugins extends RxJavaPlugins {
                RxJavaTestPlugins() {
                    super();
                }
        
                public static void resetPlugins(){
                    getInstance().reset();
                }
            }
        
            ...
            RxJavaTestPlugins.resetPlugins();
            RxJavaPlugins.getInstance().registerSchedulersHook(new RxJavaSchedulersHook() {
                @Override
                public Scheduler getIOScheduler() {
                    return Schedulers.immediate();
                }
            });

        另外有一點(diǎn)需要指出的是,要想RxJava的hook起作用,必須要在Schedulers 類初始化之前進(jìn)行hook,那么在測(cè)試的時(shí)候,只能通過(guò)實(shí)現(xiàn)自定義的TestRunner來(lái)做到了 ,在TestRunner的構(gòu)造函數(shù)中進(jìn)行reset和hook就OK了。而RxAndroid的hook則沒這 么麻煩,在測(cè)例的setUp函數(shù)中進(jìn)行就OK。

      • RxJava還能設(shè)置ObservableExecutionHook,示例: RxJavaPlugins.getInstance().registerObservableExecutionHook(new DebugHook(new DebugNotificationListener() {...}
    • 網(wǎng)絡(luò)庫(kù):Retrofit,OkHttp

集成測(cè)試

  • 集成測(cè)試的級(jí)別是什么?wiki定義為:把各個(gè)經(jīng)過(guò)單元測(cè)試的模塊組合起來(lái),作為一個(gè) 整體進(jìn)行測(cè)試,是驗(yàn)證測(cè)試的前一步。
  • 那么需要組合多少個(gè)unit呢?這個(gè)應(yīng)該視具體情況和實(shí)際操作來(lái)決定,目前來(lái)看,對(duì)于 安卓開發(fā)來(lái)說(shuō),以Activity作為集成測(cè)試的單位比較合適,但是也不盡然,例如需要測(cè)試不 同Activity之間的狀態(tài)同步時(shí),Activity1進(jìn)入Activity2,并在其中進(jìn)行了操作, 改變了應(yīng)用的狀態(tài),回到Activity1也希望能夠響應(yīng)該變化,那么測(cè)試范圍就涉及多個(gè)Activity了。
  • 測(cè)試框架

  • 和一些其他框架的整合
    • Dagger2
      • 生產(chǎn)代碼的依賴都是通過(guò)依賴注入框架注入,本應(yīng)是有利于測(cè)試的,但是如何通過(guò)依 賴注入框架把mock的依賴注入進(jìn)去呢?
      • 總的來(lái)說(shuō),都是通過(guò)使得main和test使用不同的module,test的module provide mock的依賴,main的module provide真實(shí)的依賴
      • 思路1:利用flavor/build variant,專門創(chuàng)建一個(gè)用于注入測(cè)試依賴的variant, 其中維護(hù)測(cè)試依賴的component;不用打破生產(chǎn)代碼的封裝特性;但是增加了維護(hù)成本, 有兩套component需要維護(hù),而且這兩套component必須切換AS的build variant才能切換,不能同時(shí)維護(hù);
      • 思路2:修改生產(chǎn)代碼的component創(chuàng)建/獲取途徑,使得測(cè)試時(shí)可以設(shè)置測(cè)試用的 component(能夠注入測(cè)試依賴);后期不用切換AS的build variant就能進(jìn)行重構(gòu); 一定程度上打破了封裝性;
      • 思路3:集成測(cè)試代碼使用測(cè)試專用的Application類(生產(chǎn)代碼app的子類), 自定義test runner,使得測(cè)試運(yùn)行時(shí)使用測(cè)試app類,在其中初始化dagger component,完美。
      • http://blog.sqisland.com/2015/12/mock-application-in-espresso.html
      • http://blog.egorand.me/reliable-functional-tests-with-espresso-and-dagger/
      • DaggerMock,將mockito和dagger結(jié)合起來(lái)
    • StorIO

回歸測(cè)試

  • 驗(yàn)證功能無(wú)回退
  • 對(duì)于視覺檢查來(lái)說(shuō),screenshot-tests-for-android似乎不錯(cuò)
    • 首先需要確認(rèn),當(dāng)前版本是正確的(通過(guò)了單元測(cè)試與集成測(cè)試)
    • 在此基礎(chǔ)上,對(duì)渲染數(shù)據(jù)的靜態(tài)場(chǎng)景,生成截屏
    • 以后在相同場(chǎng)景下(測(cè)例),再次截屏,并進(jìn)行對(duì)比