摘要:在世界級的安卓測試開發(fā)流第一部分,作者開始了安卓測試開發(fā)流的討論。這個測試用例的測試對象是,部分指令集僅涉及執(zhí)行的指令和。測試的粒度則應(yīng)當(dāng)和測試范圍相當(dāng)。一旦我們能夠測試產(chǎn)品需求是否正確實(shí)現(xiàn),我們必須繼續(xù)測試開發(fā)流。
在「世界級的安卓測試開發(fā)流?—?第一部分」,作者開始了安卓測試開發(fā)流的討論。我們探討了一個軟件工程師開始編寫測試,到發(fā)現(xiàn)測試開發(fā)中的相關(guān)問題的不斷變化。 最后,得到了以下結(jié)論:
測試自動化對于軟件開發(fā)的成功是至關(guān)重要的
可測試性代碼對編寫某些特定類型的測試是必須的
有些開發(fā)者在不確定測試內(nèi)容和測試方法的情況下,就開始編寫測試
測試的質(zhì)量和可靠度通常達(dá)不到我們的期望
一個測試開發(fā)流對于定義測試內(nèi)容和方法是必要的
因此,任何應(yīng)用程序中測試的關(guān)鍵部分是:
業(yè)務(wù)邏輯的測試要獨(dú)立于框架或庫
測試服務(wù)器端的API集成
從用戶的角度,使用黑盒測試驗(yàn)收標(biāo)準(zhǔn)
在本文中,我們將探討涉及這幾個部分的幾種測試方案,以確保一個穩(wěn)固的測試開發(fā)流。
業(yè)務(wù)邏輯的測試要獨(dú)立于框架或庫:首先,檢查業(yè)務(wù)邏輯是不是真的實(shí)現(xiàn)預(yù)定的產(chǎn)品需求,是必不可少的。我們需要將想要測試的代碼隔離出來,然后模擬出不同的初始場景,以配置某些組件在運(yùn)行時的行為。然后,我們選擇想要執(zhí)行的代碼部分進(jìn)行測試。之后,我們需要在執(zhí)行完測試對象后檢查軟件的狀態(tài)是否正確。
這個測試方案的關(guān)鍵在于依賴反轉(zhuǎn)原則。通過編寫只依賴于抽象的代碼,我們就可以把軟件分離成不同的層級。為了獲得依賴的實(shí)例,我們只需要向某個對象發(fā)出請求。 或者,一旦實(shí)例生成,我們也能獲得之。 我們的軟件有很多部分需要創(chuàng)建代碼來獲得合作者的實(shí)例。這時,我們會使用測試替身來模擬初始場景,或編寫不同的行為程序來設(shè)計(jì)我們的測試。通過使用測試替身,我們能同時模擬產(chǎn)品代碼的行為和狀態(tài)。 同時,它幫助我們選擇測試的范圍,也即需要測試的代碼量。沒有依賴反轉(zhuǎn),所有的類需要獨(dú)自獲取自己的依賴。結(jié)果會導(dǎo)致類實(shí)現(xiàn)和依賴實(shí)現(xiàn)相耦合,這樣就沒有辦法借用測試替身來切割產(chǎn)品代碼的執(zhí)行流程。
通常,在構(gòu)造時傳遞類依賴是使用依賴反轉(zhuǎn)的最有效機(jī)制。這個機(jī)制對采用測試替身已經(jīng)足夠。在構(gòu)造時傳遞類依賴將幫助我們創(chuàng)建相應(yīng)的測試替身來替換依賴的實(shí)例。要謹(jǐn)記,使用服務(wù)定位器或依賴反轉(zhuǎn)框架將有助于減少在應(yīng)用依賴反轉(zhuǎn)時所需要的樣板, 雖然這并不是強(qiáng)制的。
我們將用一個具體例子(該測試和筆者幾個月前開始開發(fā)的 Android GameBoy 模擬器有關(guān))來演示如何測試我們的業(yè)務(wù)需求。
以下測試是關(guān)于 GameBoy 內(nèi)存管理單元(MMU)和 GameBoy BIOS 執(zhí)行單元的。 我們將檢查產(chǎn)品需求(硬件模擬)是否正確實(shí)現(xiàn)。
public class MMUTest { private static final int MMU_SIZE = 65536; private static final int ANY_ADDRESS = 11; private static final byte ANY_BYTE_VALUE = 0x11; @Test public void shouldInitializeMMUFullOfZeros() { MMU mmu = givenAMMU(); assertMMUIsFullOfZeros(mmu); } @Test public void shouldFillMMUWithZerosOnReset() { MMU mmu = givenAMMU(); mmu.writeByte(ANY_ADDRESS, ANY_BYTE_VALUE); mmu.reset(); assertMMUIsFullOfZeros(mmu); } @Test public void shouldWriteBigBytesValuesAndRecoverThemAsOneWord() { MMU mmu = givenAMMU(); mmu.writeByte(ANY_ADDRESS, (byte) 0xFA); mmu.writeByte(ANY_ADDRESS +1, (byte) 0xFB); assertEquals(0xFBFA, mmu.readWord(ANY_ADDRESS)); } }
前三個測試是檢查 GameBoy 的 MMU 實(shí)現(xiàn)是否正確。 成功的關(guān)鍵是總在測試執(zhí)行完成后,檢查 MMU 的狀態(tài)是否正確。 所有測試都會檢查 MMU 是否正確初始化。如果重置后MMU 是整潔的,寫入2個字節(jié)后讀出的是一個字符,那么最終讀取就是正確的。為了測試模擬器軟件的這個部分,我們將測試范圍縮小為一個類。
public class GameBoyBIOSExecutionTest { @Test public void shouldIndicateTheBIOSHasBeenLoadedUnlockingTheRomMapping() { GameBoy gameBoy = givenAGameBoy(); tickUntilBIOSLoaded(gameBoy); assertEquals(1, mmu.readByte(UNLOCK_ROM_ADDRESS) & 0xFF); } @Test public void shouldPutTheNintendoLogoIntoMemoryDuringTheBIOSThirdStage() { GameBoy gameBoy = givenAGameBoy(); tickUntilThirdStageFinished(gameBoy); assertNintendoLogoIsInVRAM(); } private GameBoy givenAGameBoy() { z80 = new GBZ80(); mmu = new MMU(); gpu = new GPU(mmu); GameLoader gameLoader = new GameLoader(new FakeGameReader()); GameBoy gameBoy = new Gameboy(z80, mmu, gpu, gameLoader); return gameboy; } }
在這兩個測試中,我們檢查 BIOS 是否在不同階段都正確執(zhí)行。BIOS執(zhí)行結(jié)束后,在具體內(nèi)存位置的一個字節(jié)必須被初始化為一個具體的值。然后,在第三階段的最后,任天堂的logo必須已經(jīng)加載到 VRAM。由于全套的BIOS執(zhí)行是任何模擬器開發(fā)的關(guān)鍵部分,我們決定采用更大的測試范圍。這個測試用例的測試對象是 CPU,部分 CPU 指令集(僅涉及 BIOS執(zhí)行的指令)和 MMU。 要檢查執(zhí)行的狀態(tài)是否正確,我們必須對 MMU的狀態(tài)使用斷言(assert)。要想顯著的提升測試質(zhì)量,一個關(guān)鍵就是檢查軟件執(zhí)行后的最終狀態(tài),同時避免驗(yàn)證和其他組件之間的交互。因?yàn)榧词购推渌M件之間的交互都是正確的,最終狀態(tài)依然可能是錯的。還要明確,這些測試的某些部分同樣可以獨(dú)立進(jìn)行,如 CPU指令。
這些測試的另一個主要亮點(diǎn)是使用測試替身來模擬和 Android SDK 相關(guān)的部分代碼。在執(zhí)行 BIOS 前,GameBoy 游戲必須加載進(jìn) GameBoy 的 MMU。然而,在測試期間,沒有 Android SDK 可用,因而就不得不將其替換,轉(zhuǎn)而從測試環(huán)境中加載 GameBoy的 rom。我們使用依賴反轉(zhuǎn)原則不僅用于隱藏實(shí)現(xiàn)細(xì)節(jié),或者定義邊界,還用測試替身 FakeGameReader 來替代 AndroidGameReader 的產(chǎn)品代碼,這意味著完全不依賴框架和庫進(jìn)行代碼測試。通過這樣做,我們創(chuàng)建了隔離的測試環(huán)境,同時調(diào)整了測試范圍。
范圍:調(diào)整測試的范圍是非常重要的。 開始編寫測試前,我們應(yīng)當(dāng)牢記測試范圍可以幫助識別代碼錯誤(取決于測試的規(guī)模)。縮小測試規(guī)模能帶給我們更豐富的錯誤反饋,而放大規(guī)模的測試則不能提供錯誤位置的精確信息。測試的粒度則應(yīng)當(dāng)和測試范圍相當(dāng)。
基礎(chǔ)設(shè)施:編寫這些測試的基礎(chǔ)設(shè)施相當(dāng)明了。 我們必須在依賴反轉(zhuǎn)原則下編寫可測試代碼,并結(jié)合使用一個測試框架和一個模擬庫。 模擬庫用來生成模擬場景中需要的測試替身,或者用于替代部分產(chǎn)品代碼的測試替身。請注意,這些框架和庫不是強(qiáng)制使用的,但是非常推薦。
結(jié)果:這個方案的結(jié)果很有趣。 當(dāng)遵循依賴反轉(zhuǎn)原則時,我們能獨(dú)立于框架和庫測試我們產(chǎn)品代碼中的業(yè)務(wù)邏輯。通過可重復(fù)的,易于編寫和設(shè)計(jì)的測試,我們可以創(chuàng)建隔離的測試環(huán)境。此外,我們能夠方便選擇要測試的產(chǎn)品代碼數(shù)量,并使用測試替身代替這部分代碼,來模擬行為和不同的場景。
一旦我們能夠測試產(chǎn)品需求是否正確實(shí)現(xiàn),我們必須繼續(xù)測試開發(fā)流。接下來要測試的,就是在前一階段使用測試替身替換的外部組件集成后是否執(zhí)行正確。我們將在下一篇博文中討論,敬請期待!
原文地址:http://blog.karumi.com/world-class-testing-development-pipeline-for-android-part-2/
OneAPM Mobile Insight ,監(jiān)控網(wǎng)絡(luò)請求及網(wǎng)絡(luò)錯誤,提升用戶留存。訪問 OneAPM 官方網(wǎng)站感受更多應(yīng)用性能優(yōu)化體驗(yàn),想閱讀更多技術(shù)文章,請?jiān)L問 OneAPM 官方技術(shù)博客。
本文轉(zhuǎn)自 OneAPM 官方博客
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/8709.html
摘要:不過細(xì)想想,我郵只有前端的選修課啥的,課程也不是那么就業(yè)導(dǎo)向。至少目前,很少有大公司完全把作為前后端通用的技術(shù)棧。不能把簡單看做是在服務(wù)端的延展。編譯這個思想在前端領(lǐng)域很重要不改變現(xiàn)有的語言環(huán)境同時進(jìn)行最佳的工程實(shí)踐。 P.S. 噴神請繞道,大神勿噴,不引戰(zhàn),不攻擊,不鉆牛角尖。 大二時第一次接觸前端。許多同學(xué)估計(jì)都想過要做一個網(wǎng)站,大部分又是從PHP開始的(誰讓它是世界上最好的語言呢...
閱讀 1969·2021-10-25 09:48
閱讀 2798·2021-09-22 14:59
閱讀 1761·2019-08-29 16:52
閱讀 866·2019-08-29 16:07
閱讀 2308·2019-08-29 12:38
閱讀 1760·2019-08-26 13:23
閱讀 883·2019-08-26 11:49
閱讀 3277·2019-08-26 10:56