กำหนดเป้าหมายแอปตัวอย่าง

การทดสอบเครื่องมือประเภทนี้ไม่แตกต่างจากการทดสอบที่กำหนดเป้าหมายไปยังแอปพลิเคชัน Android ปกติมากนัก โปรดทราบว่าแอปพลิเคชันทดสอบ ที่มีการวัดผลต้องได้รับการลงนามด้วยใบรับรองเดียวกัน กับแอปพลิเคชันที่กำหนดเป้าหมาย

โปรดทราบว่าคำแนะนำนี้มีสมมติฐานว่าคุณมีความรู้เกี่ยวกับ เวิร์กโฟลว์ของโครงสร้างแหล่งที่มาของแพลตฟอร์มอยู่แล้ว หากยังไม่ได้ โปรดดูข้อกำหนด ตัวอย่างที่กล่าวถึงในที่นี้คือการเขียนการทดสอบเครื่องมือใหม่โดยตั้งค่าแพ็กเกจเป้าหมาย ที่แพ็กเกจแอปพลิเคชันทดสอบของตัวเอง หากคุณไม่คุ้นเคยกับแนวคิดนี้ โปรดอ่านข้อมูลเบื้องต้นเกี่ยวกับการทดสอบแพลตฟอร์ม

คู่มือนี้ใช้การทดสอบการติดตามเป็นตัวอย่าง

  • frameworks/base/packages/Shell/tests

เราขอแนะนำให้คุณเรียกดูโค้ดก่อนเพื่อดูภาพรวมคร่าวๆ ก่อนดำเนินการต่อ

กำหนดตำแหน่งต้นทาง

เนื่องจาก Instrumentation Test จะกำหนดเป้าหมายเป็นแอปพลิเคชัน ดังนั้นธรรมเนียมปฏิบัติ คือการวางซอร์สโค้ดของเทสต์ไว้ในไดเรกทอรี tests ภายใต้รูทของ ไดเรกทอรีแหล่งที่มาของคอมโพเนนต์ในโครงสร้างแหล่งที่มาของแพลตฟอร์ม

ดูการสนทนาเพิ่มเติมเกี่ยวกับตำแหน่งแหล่งที่มาในตัวอย่างแบบครบวงจรสำหรับ การทดสอบที่ใช้การวัดด้วยตนเอง

ไฟล์ Manifest

เช่นเดียวกับแอปพลิเคชันปกติ โมดูลการทดสอบเครื่องมือแต่ละโมดูลต้องมี ไฟล์ Manifest หากคุณตั้งชื่อไฟล์เป็น AndroidManifest.xml และวางไว้ข้าง Android.mk สำหรับโมดูลทดสอบ ระบบจะรวมไฟล์ดังกล่าวโดยอัตโนมัติด้วย Makefile หลักของ BUILD_PACKAGE

ก่อนดำเนินการต่อ เราขอแนะนำอย่างยิ่งให้คุณอ่านภาพรวมของไฟล์ Manifest ของแอป ก่อน

ซึ่งจะแสดงภาพรวมของคอมโพเนนต์พื้นฐานของไฟล์ Manifest และฟังก์ชันการทำงานของคอมโพเนนต์เหล่านั้น

คุณเข้าถึงไฟล์ Manifest เวอร์ชันล่าสุดสำหรับการเปลี่ยนแปลง Gerrit ตัวอย่างได้ที่ https://android.googlesource.com/platform/frameworks/base/+/android16-release/packages/Shell/tests/AndroidManifest.xml

เราได้รวมสแนปชอตไว้ที่นี่เพื่อความสะดวก

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.shell.tests">

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

        <activity
            android:name="com.android.shell.ActionSendMultipleConsumerActivity"
            android:label="ActionSendMultipleConsumer"
            android:theme="@android:style/Theme.NoDisplay"
            android:noHistory="true"
            android:excludeFromRecents="true">
            <intent-filter>
                <action android:name="android.intent.action.SEND_MULTIPLE" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="*/*" />
            </intent-filter>
        </activity>
    </application>

    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
        android:targetPackage="com.android.shell"
        android:label="Tests for Shell" />

</manifest>

ข้อสังเกตบางประการเกี่ยวกับไฟล์ Manifest

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.shell.tests">

แอตทริบิวต์ package คือชื่อแพ็กเกจแอปพลิเคชัน ซึ่งเป็นตัวระบุที่ไม่ซ้ำกัน ที่เฟรมเวิร์กแอปพลิเคชัน Android ใช้เพื่อระบุแอปพลิเคชัน (หรือในบริบทนี้คือแอปพลิเคชันทดสอบของคุณ) ผู้ใช้แต่ละรายในระบบ จะติดตั้งแอปพลิเคชันที่มีชื่อแพ็กเกจนั้นได้เพียงแอปเดียว

เนื่องจากนี่คือแพ็กเกจแอปพลิเคชันทดสอบซึ่งแยกจากแพ็กเกจแอปพลิเคชันภายใต้การทดสอบ จึงต้องใช้ชื่อแพ็กเกจอื่น โดยธรรมเนียมทั่วไปอย่างหนึ่งคือการเพิ่มคำต่อท้าย .test

นอกจากนี้ แอตทริบิวต์ package นี้ยังเหมือนกับที่ ComponentName#getPackageName() ส่งคืน และยังเหมือนกับที่คุณใช้เพื่อโต้ตอบกับคำสั่งย่อย pm ต่างๆ ผ่าน adb shell

โปรดทราบด้วยว่าแม้ว่าโดยทั่วไปแล้วชื่อแพ็กเกจจะมีรูปแบบเดียวกับชื่อแพ็กเกจ Java แต่จริงๆ แล้วชื่อแพ็กเกจไม่ได้เกี่ยวข้องกับชื่อแพ็กเกจ Java มากนัก กล่าวอีกนัยหนึ่ง แพ็กเกจแอปพลิเคชัน (หรือการทดสอบ) อาจมีคลาสที่มีชื่อแพ็กเกจใดก็ได้ ในทางกลับกัน คุณอาจเลือกใช้ความเรียบง่ายและมีชื่อแพ็กเกจ Java ระดับบนสุดในแอปพลิเคชันหรือการทดสอบที่เหมือนกับชื่อแพ็กเกจแอปพลิเคชัน

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

การทดสอบเครื่องมือทั้งหมดต้องมีข้อกำหนดนี้ เนื่องจากคลาสที่เกี่ยวข้องจะ รวมอยู่ในไฟล์ไลบรารี JAR ของเฟรมเวิร์กแยกต่างหาก จึงต้องมีรายการ classpath เพิ่มเติมเมื่อเฟรมเวิร์กแอปพลิเคชันเรียกใช้แพ็กเกจการทดสอบ

android:targetPackage="com.android.shell"

ซึ่งจะตั้งค่าแพ็กเกจเป้าหมายของการวัดผลเป็น com.android.shell เมื่อเรียกใช้การวัดคุมผ่านคำสั่ง am instrument เฟรมเวิร์กจะรีสตาร์ทกระบวนการ com.android.shell และแทรกโค้ดการวัดคุมลงในกระบวนการเพื่อดำเนินการทดสอบ ซึ่งหมายความว่าโค้ดทดสอบจะมีสิทธิ์เข้าถึงอินสแตนซ์ของคลาสทั้งหมดที่ทำงานในแอปพลิเคชันภายใต้การทดสอบ และอาจจัดการสถานะได้ขึ้นอยู่กับฮุกทดสอบที่เปิดเผย

ไฟล์การกำหนดค่าอย่างง่าย

โมดูลทดสอบใหม่แต่ละโมดูลต้องมีไฟล์กำหนดค่าเพื่อสั่งให้ ระบบบิลด์มีข้อมูลเมตาของโมดูล การขึ้นต่อกันในเวลาคอมไพล์ และคำสั่ง การแพ็กเกจ ในกรณีส่วนใหญ่ ตัวเลือกไฟล์ Blueprint ที่อิงตาม Soong จะเพียงพอ ดูรายละเอียดได้ที่การกำหนดค่าการทดสอบอย่างง่าย

ไฟล์การกำหนดค่าที่ซับซ้อน

สำหรับการทดสอบที่ซับซ้อนมากขึ้น คุณจะต้องเขียนไฟล์การกำหนดค่าการทดสอบสำหรับเครื่องมือทดสอบของ Android ซึ่งก็คือ Trade Federation ด้วย

การกำหนดค่าการทดสอบสามารถระบุตัวเลือกการตั้งค่าอุปกรณ์พิเศษและอาร์กิวเมนต์เริ่มต้นเพื่อจัดหาคลาสการทดสอบ

เข้าถึงไฟล์การกำหนดค่าเวอร์ชันล่าสุดสำหรับการเปลี่ยนแปลง Gerrit ตัวอย่างได้ที่ frameworks/base/packages/Shell/tests/AndroidTest.xml

เราได้รวมสแนปชอตไว้ที่นี่เพื่อความสะดวก

<configuration description="Runs Tests for Shell.">
    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
        <option name="test-file-name" value="ShellTests.apk" />
    </target_preparer>

    <option name="test-suite-tag" value="apct" />
    <option name="test-tag" value="ShellTests" />
    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
        <option name="package" value="com.android.shell.tests" />
        <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="ShellTests.apk"/>
</target_preparer>

ซึ่งจะบอกให้สหพันธ์การค้าติดตั้ง ShellTests.apk ลงในอุปกรณ์เป้าหมาย โดยใช้ target_preparer ที่ระบุ นักพัฒนาแอปใน Trade Federation สามารถใช้ตัวเตรียมเป้าหมายหลายตัวเพื่อตรวจสอบว่า ตั้งค่าอุปกรณ์อย่างถูกต้องก่อนการทดสอบ

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

ซึ่งจะระบุคลาสการทดสอบของ Trade Federation ที่จะใช้ในการเรียกใช้การทดสอบและ ส่งผ่านในแพ็กเกจบนอุปกรณ์ที่จะเรียกใช้ รวมถึงเฟรมเวิร์ก Test Runner ซึ่งในกรณีนี้คือ JUnit

ดูข้อมูลเพิ่มเติมเกี่ยวกับการกำหนดค่าโมดูลทดสอบได้ที่นี่

ฟีเจอร์ JUnit4

การใช้ไลบรารี android-support-test เป็นตัวเรียกใช้การทดสอบจะช่วยให้ใช้คลาสการทดสอบรูปแบบ JUnit4 ใหม่ได้ และการเปลี่ยนแปลง Gerrit ตัวอย่างมีการใช้ฟีเจอร์พื้นฐานบางอย่าง

คุณเข้าถึงซอร์สโค้ดล่าสุดสำหรับการเปลี่ยนแปลง Gerrit ตัวอย่างได้ที่ frameworks/base/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java

แม้ว่ารูปแบบการทดสอบมักจะเฉพาะเจาะจงสำหรับทีมคอมโพเนนต์ แต่ก็มีรูปแบบการใช้งานบางอย่างที่ มีประโยชน์โดยทั่วไป

@SmallTest
@RunWith(AndroidJUnit4.class)
public final class FeatureFactoryImplTest {

ความแตกต่างที่สำคัญใน JUnit4 คือไม่จำเป็นต้องให้การทดสอบสืบทอดจากคลาสการทดสอบฐานทั่วไปอีกต่อไป แต่คุณจะเขียนการทดสอบในคลาส Java ธรรมดาและใช้คำอธิบายประกอบเพื่อระบุการตั้งค่าและการจำกัดการทดสอบบางอย่างแทน ใน ตัวอย่างนี้ เรากำลังสั่งให้คลาสนี้ทำงานเป็นการทดสอบ JUnit4 ของ Android

คำอธิบายประกอบ @SmallTest ระบุขนาดการทดสอบสำหรับคลาสการทดสอบทั้งหมด: วิธีการทดสอบทั้งหมดที่เพิ่มลงในคลาสการทดสอบนี้จะรับช่วงคำอธิบายประกอบขนาดการทดสอบนี้ การตั้งค่าคลาสการทดสอบก่อนหน้า การล้างข้อมูลหลังการทดสอบ และการล้างข้อมูลหลังการทดสอบคลาส: คล้ายกับวิธีการ setUp และ tearDown ใน JUnit4 Test ใช้เพื่อใส่คำอธิบายประกอบในการทดสอบจริง

    @Before
    public void setup() {
    ...
    @Test
    public void testGetProvider_shouldCacheProvider() {
    ...

JUnit4 ใช้หมายเหตุ @Before ในเมธอดเพื่อทำการตั้งค่าก่อนการทดสอบ แม้ว่าจะไม่ได้ใช้ในตัวอย่างนี้ แต่ก็มี @After สำหรับการล้างข้อมูลหลังการทดสอบด้วย ในทำนองเดียวกัน JUnit4 สามารถใช้หมายเหตุประกอบ @BeforeClass และ @AfterClass กับเมธอดเพื่อทำการตั้งค่าก่อนที่จะเรียกใช้การทดสอบทั้งหมดในคลาสการทดสอบ และทำการล้างข้อมูลภายหลัง โปรดทราบว่าเมธอดการตั้งค่าและการล้างข้อมูลระดับคลาส ต้องเป็นแบบคงที่

สำหรับเมธอดทดสอบนั้น ไม่เหมือนกับ JUnit เวอร์ชันก่อนหน้า ซึ่งไม่จำเป็นต้องขึ้นต้นชื่อเมธอดด้วย test อีกต่อไป แต่เมธอดแต่ละรายการต้องมีคำอธิบายประกอบ @Test ตามปกติแล้ว เมธอดทดสอบต้องเป็นแบบสาธารณะ ไม่ประกาศค่าที่ส่งคืน ไม่รับพารามิเตอร์ และอาจส่งข้อยกเว้น

        Context context = InstrumentationRegistry.getTargetContext();

เนื่องจากการทดสอบ JUnit4 ไม่จำเป็นต้องใช้คลาสฐานทั่วไปอีกต่อไป จึงไม่จำเป็นต้องรับอินสแตนซ์ Context ผ่าน getContext() หรือ getTargetContext() ผ่านเมธอดคลาสฐานอีกต่อไป แต่โปรแกรมเรียกใช้การทดสอบใหม่จะจัดการอินสแตนซ์เหล่านั้นผ่าน InstrumentationRegistry ซึ่งจะจัดเก็บการตั้งค่าตามบริบทและสภาพแวดล้อมที่สร้างขึ้นโดยเฟรมเวิร์กการวัด นอกจากนี้ คุณยังเรียกใช้สิ่งต่อไปนี้ผ่านคลาสนี้ได้ด้วย

  • getInstrumentation(): อินสแตนซ์ไปยังคลาส Instrumentation
  • getArguments(): อาร์กิวเมนต์บรรทัดคำสั่งที่ส่งไปยัง am instrument ผ่าน -e <key> <value>

สร้างและทดสอบในเครื่อง

สำหรับกรณีการใช้งานที่พบบ่อยที่สุด ให้ใช้ Atest

สำหรับกรณีที่ซับซ้อนมากขึ้นซึ่งต้องมีการปรับแต่งที่หนักกว่า ให้ทำตามวิธีการติดตั้งเครื่องมือ