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

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

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

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

  • frameworks/base/packages/Shell/tests

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

เลือกตำแหน่งของแหล่งที่มา

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

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

ไฟล์ Manifest

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

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

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

คุณสามารถเข้าถึงไฟล์ Manifest เวอร์ชันล่าสุดสำหรับการเปลี่ยนแปลงตัวอย่างใน Gerrit ได้ที่ https://android.googlesource.com/platform/frameworks/base/+/main/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 ระดับบนสุดในแอปพลิเคชันหรือการทดสอบให้เหมือนกับชื่อแพ็กเกจแอปพลิเคชัน

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

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

android:targetPackage="com.android.shell"

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

ไฟล์การกําหนดค่าแบบง่าย

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

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

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

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

ไฟล์การกําหนดค่าเวอร์ชันล่าสุดสําหรับตัวอย่างการเปลี่ยนแปลงใน 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>

ซึ่งจะบอกให้ Trade Federation ติดตั้ง 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 ที่จะใช้ในการทดสอบ และส่งผ่านแพ็กเกจในอุปกรณ์ที่จะทำการทดสอบและเฟรมเวิร์กโปรแกรมรันทดสอบ ซึ่งในกรณีนี้คือ 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 ธรรมดาและใช้คำอธิบายประกอบเพื่อระบุการตั้งค่าการทดสอบและข้อจำกัดบางอย่าง ในตัวอย่างนี้ เรากําลังสั่งให้เรียกใช้คลาสนี้เป็น Android JUnit4

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

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

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

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

        Context context = InstrumentationRegistry.getTargetContext();

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

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

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

สําหรับ Use Case ที่พบบ่อยที่สุด ให้ใช้ Atest

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