自儀器測試示例

當儀器測試開始時,它的目標包會重新啟動並註入儀器代碼並啟動執行。一個例外是,這裡的目標包不能Android應用程序框架本身,即包android ,因為這樣做會導致矛盾的情況Android框架需要重新啟動,這是支持的系統功能,包括儀器儀表本身。

這意味著儀器測試無法將自身注入 Android 框架(也稱為系統服務器)以執行。為了測試Android框架,測試代碼可以調用僅公共API的表面,或那些通過Android的接口定義語言暴露AIDL ,可以在平台源樹。對於此類測試,針對任何特定包沒有意義。因此,要被聲明它的常規用於此控制儀表靶向它自己的測試應用程序包,在其自己的定義<manifest>的標籤AndroidManifest.xml

根據要求,此類別中的測試應用程序包還可能:

  • 捆綁測試所需的活動。
  • 與系統共享用戶 ID。
  • 使用平台密鑰進行簽名。
  • 針對框架源而不是公共 SDK 進行編譯。

此類儀器測試有時稱為自儀器測試。以下是平台源中的一些自儀器測試示例:

此處涵蓋的示例是編寫一個新的儀器測試,目標包設置在其自己的測試應用程序包中。本指南以以下測試為例:

建議在繼續之前先瀏覽代碼以獲得粗略的印象。

確定源位置

通常,您的團隊已經有一個既定的代碼檢入位置和添加測試位置的模式。大多數團隊擁有一個單獨的 git 存儲庫,或者與其他團隊共享一個,但有一個包含組件源代碼的專用子目錄。

假設根位置為組件源是在<component source root> ,大多數元件具有srctests其下的文件夾,以及一些其他文件如Android.mk (或分解成附加.mk文件),清單文件AndroidManifest.xml ,和測試配置文件'AndroidTest.xml'。

既然你要添加一個全新的測試,你可能需要創建tests目錄旁邊的組件src ,並與內容填充它。

在某些情況下,你的團隊可能有進一步下目錄結構tests由於需要封裝測試到單獨的APK不同的套件。在這種情況下,你需要在創建一個新的子目錄tests

不管結構,你最終會填充tests目錄或相似的什麼在文件中的新創建的子目錄instrumentation目錄中的樣本格里特變化。下面的部分將詳細解釋每個文件。

清單文件

就像常規應用程序一樣,每個儀器測試模塊都需要一個清單文件。如果命名文件AndroidManifest.xml ,並提供它旁邊Android.mk為您的測試模塊,它會自動獲得由包括BUILD_PACKAGE核心的makefile。

在進一步討論之前,強烈建議去通過應用清單概述第一。

這給出了清單文件的基本組件及其功能的概述。見例如在platform_testing /測試/例子/儀表/ AndroidManifest.xml中

為方便起見,此處包含快照:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="android.test.example.helloworld" >

    <uses-sdk android:minSdkVersion="21" android:targetSdkVersion="21" />

    <application>
        <uses-library android:name="android.test.runner" />
    </application>

    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
                     android:targetPackage="android.test.example.helloworld"
                     android:label="Hello World Test"/>

</manifest>

清單文件上的一些選擇說明:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="android.test.example.helloworld" >

package的屬性是應用程序包名稱:這是唯一的標識符,Android應用程序框架使用,以確定應用程序(或在這種情況下:測試應用程序)。系統中的每個用戶只能安裝一個具有該軟件包名稱的應用程序。

此外,該package的屬性是一樣的什麼ComponentName#getPackageName()返回時,也應該使用與各種互動同pm通過子命令adb shell

另請注意,雖然包名通常與 Java 包名具有相同的風格,但實際上與它無關。換句話說,您的應用程序(或測試)包可能包含具有任何包名稱的類,但另一方面,您可以選擇簡單並在應用程序中使用頂級 Java 包名稱或測試與應用程序包名稱相同。

android:sharedUserId="android.uid.system"

這聲明在安裝時,該 apk 應被授予與核心平台相同的用戶 ID,即運行時標識。請注意,這是依賴於APK使用相同的證書為核心的平台進行簽名(見LOCAL_CERTIFICATE以上部分),但它們是不同的概念:

  • 某些權限或 API 受簽名保護,需要相同的簽名證書
  • 一些權限或API需要的system調用程序,這需要調用包來分享用戶ID與用戶身份system ,如果它是來自核心平台本身就是一個單獨的包
<uses-library android:name="android.test.runner" />

這是所有 Instrumentation 測試所必需的,因為相關類被打包在單獨的框架 jar 庫文件中,因此當應用程序框架調用測試包時需要額外的類路徑條目。

android:targetPackage="android.test.example.helloworld"

你可能已經注意到, targetPackage這裡聲明一樣的package屬性在聲明manifest文件的標籤。正如提到的測試基礎,儀器儀表測試的這一類通常用於測試框架的API,所以它不是非常有意義他們有一個具體的有針對性的應用程序包,然後其他本身。

簡單的配置文件

每個新的測試模塊都必須有一個配置文件,以使用模塊元數據、編譯時依賴項和打包指令來指導構建系統。在大多數情況下,基於 Soong 的藍圖文件選項就足夠了。有關詳細信息,請參閱簡單的測試配置

複雜的配置文件

對於這些更複雜的情況下,還需要編寫Android的測試工具,測試配置文件貿易聯合會

測試配置可以指定特殊的設備設置選項和默認參數來提供測試類。看到的例子/platform_testing/tests/example/instrumentation/AndroidTest.xml

為方便起見,此處包含快照:

<configuration description="Runs sample instrumentation test.">
  <target_preparer class="com.android.tradefed.targetprep.TestFilePushSetup"/>
  <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
    <option name="test-file-name" value="HelloWorldTests.apk"/>
  </target_preparer>
  <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer"/>
  <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer"/>
  <option name="test-suite-tag" value="apct"/>
  <option name="test-tag" value="SampleInstrumentationTest"/>

  <test class="com.android.tradefed.testtype.AndroidJUnitTest">
    <option name="package" value="android.test.example.helloworld"/>
    <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
  </test>
</configuration>

對測試配置文件的一些選擇說明:

<target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
  <option name="test-file-name" value="HelloWorldTests.apk"/>
</target_preparer>

這會告訴 Trade Federation 使用指定的 target_preparer 將 HelloWorldTests.apk 安裝到目標設備上。 Trade Federation 中有許多目標準備器可供開發人員使用,這些可用於確保在測試執行之前正確設置設備。

<test class="com.android.tradefed.testtype.AndroidJUnitTest">
  <option name="package" value="android.test.example.helloworld"/>
  <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
</test>

這指定了用於執行測試的 Trade Federation 測試類,並傳入要執行的設備上的包和測試運行器框架,在本例中為 JUnit。

欲了解更多信息,請參見測試模塊CONFIGS

JUnit4 特性

使用android-support-test庫作為測試運行器能夠通過新JUnit4風格測試類,和樣品格里特變化包含了一些非常基本的使用其功能。看到的例子/platform_testing/tests/example/instrumentation/src/android/test/example/helloworld/HelloWorldTest.java

雖然測試模式通常特定於組件團隊,但有一些通常有用的使用模式。

@RunWith(JUnit4.class)
public class HelloWorldTest {

JUnit4 的一個顯著區別是測試不再需要從一個公共的基礎測試類繼承;相反,您在純 Java 類中編寫測試並使用註釋來指示某些測試設置和約束。在這個例子中,我們指示這個類應該作為 JUnit4 測試運行。

    @BeforeClass
    public static void beforeClass() {
    ...
    @AfterClass
    public static void afterClass() {
    ...
    @Before
    public void before() {
    ...
    @After
    public void after() {
    ...
    @Test
    @SmallTest
    public void testHelloWorld() {
    ...

@Before@After註解用於由JUnit4方法來進行預測試設置和測試後拆除。類似地, @BeforeClass@AfterClass註解用於由JUnit4方法在測試類執行的所有測試之前執行設置和拆除之後。請注意,類範圍設置和拆卸方法必須是靜態的。至於測試方法,不像JUnit中的早期版本,他們不再需要與啟動的方法名稱test ,相反,他們每個人都必須有註釋@Test 。像往常一樣,測試方法必須是公共的,沒有聲明返回值,沒有參數,並且可能會拋出異常。

重要提示:測試方法本身都標註有@Test註釋;並注意,對於經由APCT被執行的測試中,必須將它們與測試大小註釋:該示例註釋的方法testHelloWorld作為@SmallTest 。註釋可以應用於方法範圍或類範圍。

訪問instrumentation

雖然在基本的hello world例子不是蓋的,這是很常見的一個Android測試需要訪問Instrumentation實例:這是核心API接口,提供應用程序環境中,活動的生命週期相關的測試API和更多的訪問。

由於JUnit4測試不再需要一個共同的基類,它不再需要獲得Instrumentation通過實例InstrumentationTestCase#getInstrumentation()相反,新的測試運行通過對其進行管理InstrumentationRegistry其中通過儀表框架創建上下文和環境設置被儲存。

要訪問的實例Instrumentation類,只需調用靜態方法getInstrumentation()InstrumentationRegistry類:

Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation()

在本地構建和測試

對於最常見的使用情況,應用ATEST

對於需要重定制更複雜的情況,按照儀器說明書