簡體   English   中英

Robolectric 與 Android 測試框架

[英]Robolectric vs Android Test Framework

Android 測試框架相比, Robolectric是否提供任何明顯的優勢? 我已經閱讀了關於這兩個框架的文檔,但據我所知Robolectric唯一明確的好處是它運行在 JVM 而不是 DalvikVM 上,使其比 Android 框架更快。

還有其他突出的主要好處嗎?

2015 年 4 月更新:Gradle 構建工具和 Android Studio現在正式支持單元測試並防止 android.jar 拋出存根(沒有真正實現)錯誤。 所以,是的,當存根被適當地模擬時,它可以在 Java VM 上運行測試。 它是一個開始,但仍然無法與 Robolectric 的力量相提並論。 還有第三種選擇,滾動到這個答案的底部。

現在,關於 Robolectric :

優點:這里有一些關於它如何被證明在單元測試中有用的要點:

  1. 您不需要運行模擬器,因此您可以測試項目的一些非 UI 部分,而無需模擬器或設備。 這也適用於在持續集成/構建服務器上運行測試,不需要啟動模擬器實例。

  2. 使用 Android Studio,您可以在執行實現以滿足測試用例時快速運行一個特定的測試類。 您可以在編寫代碼時進行調試。 這是一個巨大的生產力提升。

  3. 可以將幾乎所有與 android 相關的東西都偽裝成影子對象,甚至是 SQLite。 此外,每個 shadow 對象都公開了許多它們的普通 android 對應物不提供的有用功能。 使用 android 對象的影子對應物,您可以進行內部檢查或調用特殊方法。

  4. 在測試多線程代碼(如AsyncTaskLoopersHandlers等)時真的很AsyncTask 。您可以暫停和快進線程 Loopers,甚至主線程。 非常適合基於 Handler 的回調測試。

  5. 支持 JUnit 4 格式。 上次我檢查時,Android 仍然堅持使用 JUnit 3。

  6. 可以與其他測試工具結合使用,如 Mockito、Espresso 等。

  7. 支持模擬 Activity 實例創建Robolectric.buildActivity()並通過ActivityController對其進行控制。 片段/視圖操作也適用於此類模擬活動實例。

  8. 現在提供的附加模塊涵蓋了多 dex、v4 支持、播放服務、地圖和 http 客戶端。 因此,現在也可以輕松地使用這些庫函數來測試代碼。

缺點:我發現它不太好:

  1. Robolectric 擅長輔助單元測試,但並未涵蓋真實設備或模擬器可以提供的所有功能。 例如傳感器、gps、open-gl 等。

  2. 在進行集成或 UI 測試時,您將需要模擬器或真實設備,以便活動和服務可以與完整的 android 環境(其他應用程序,例如使用相機應用程序為您的應用程序獲取圖片)交互,而不是有限的。 在這里,您需要使用默認測試框架,因為它也具有測試 UI 的功能。

  3. 似乎不支持 JNI 加載。 因此無法測試具有本機依賴項的代碼。

  4. 到目前為止,Robolectric 對谷歌地圖 jar 的工作有一個硬連線依賴。 並將從 maven 下載另一個 android.jar。 因此,項目設置可能需要一些修補。 更新:從 v3 開始,它似乎毫不費力地通過 Gradle 拉取所有依賴項。

  5. 較新的 Android 工具支持覆蓋率和報告生成等,但僅限於在設備上運行測試時。 因此,使用 Robolectric,您必須創建額外的 Gradle 任務(運行 Jacoco)來為您完成。 更新:Gradle 2.9 + 附帶 jacoco 插件。

  6. 由於 gradle 和 android 構建工具都在快速發布更新的構建版本,穩定的 Robolectric 版本有時會開始遇到更改構建工具的問題。 最典型的問題包括:sdk 版本不兼容、找不到清單、構建輸出路徑不匹配、資源未加載、構建配置問題等。一些問題也與 android 工具中的錯誤有關。 有時您甚至可能需要編寫自己的自定義測試運行程序或應用變通方法,直到下一個版本修復這些問題。 檢查未解決的問題並相應地配置測試。


另一種選擇是你自己模擬東西,不涉及框架。 它是“艱難的方式”,但也是最可定制的方式。 它帶有JMockit 的普通 JUnit :

@RunWith(JMockit.class)
public class OtherTest {
    public void testHandlerCallback(@Mocked final FragmentTransaction transaction,
                                    @Mocked final FragmentManager manager,
                                    @Mocked final Activity activity,
                                    @Mocked final LayoutInflater inflater,
                                    @Mocked final ViewGroup parent) {

        final List<Fragment> fragments = new ArrayList<>();
        new Expectations() {{
            activity.getFragmentManager(); result = manager;
            manager.beginTransaction(); result = transaction;
            transaction.add(withCapture(fragments), anyString);
            transaction.commit(); result = new Delegate<Void>() {
                public int commit() {
                    View v = fragments.get(0).onCreateView(inflater,parent,null);
                    Deencapsulation.invoke(v,"onMeasure",0,0);
                  return  0;  
                }
            };
        }};
    }
}

以上是一個粗略的內聯示例。 您實際上可以創建適當的可重用類(例如FragmentTestHarness ), FragmentTestHarness將接受測試的組件(例如Fragment )並將其包裝在完全隔離的環境中,為測試做好准備。

分享我是怎么做的...

Robolectric 對於 SQL,活動流,對於那些需要上下文的對象。

用於 api 的 java 模塊的 JUnit4 以確保數據正確返回。

Espresso 用於檢查 ui 顯示是否正確。

當我修改 api...我只運行 jUnit4。

當我修改了api和UI或Sqlite之間的數據綁定時,那么我只會運行Robolectric。

當我修改 UI 時,我只運行 Espresso。

有時我會一起運行 Robolectric 和 espresso,但非常罕見。

但我會在發布到 Play 商店之前運行所有內容。

因為我認為目前沒有真正的好處。 但是看看你如何使用它來加快你的產品質量和開發速度。

如果我錯了,請糾正我。

僅在需要模擬或偽造Android 框架的情況下才使用Robolectric ,例如,如果您需要上下文。 使用Android 測試框架時,您必須為超慢的測試運行儀器測試

如果您編寫測試是為了讓它們頻繁運行,例如因為您遵循 tdd 方法,這不是一個選擇。 所以在這種情況下, Robolectric就派上用場了。

因此, Robolectric的主要好處是它比一般的EspressoInstrumented 測試要快得多。

缺點是它偽造了您應該注意的 Android 環境。 要驗證現實世界中的問題,最好使用經典的 Android 框架方法。

最好的方式仍然是編寫您的代碼,您可以對其進行單元測試,並且不需要上下文或任何其他 Android 框架依賴項

自 I/O 2018 以來, Robolectric已被集成到 Android 測試框架中 - 在官方 Robolectric 頁面上查看更多信息並觀看來自 I/O 2018 的視頻

Robolectric 的主要優點是速度。 使用 Robolectric 進行單元測試不需要正在運行的模擬器或設備來運行測試,因此速度要快得多。

您可能仍然希望擁有一套針對真實設備運行的集成測試,只是一個小得多的套件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM