การกำหนดเป้าหมายตัวอย่างแอปพลิเคชัน

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

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

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

  • กรอบงาน/ฐาน/แพ็คเกจ/เชลล์/การทดสอบ

ขอแนะนำให้เรียกดูรหัสก่อนเพื่อรับความประทับใจก่อนดำเนินการต่อ

การตัดสินใจเลือกตำแหน่งต้นทาง

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

ดูการสนทนาเพิ่มเติมเกี่ยวกับตำแหน่งแหล่งที่มาใน ตัวอย่างแบบ end-to-end สำหรับการทดสอบการใช้อุปกรณ์ด้วยตนเอง

ไฟล์รายการ

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

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

android:targetPackage="com.android.shell"

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

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

โมดูลทดสอบใหม่แต่ละโมดูลต้องมีไฟล์การกำหนดค่าเพื่อสั่งระบบบิลด์ด้วยข้อมูลเมตาของโมดูล การพึ่งพาเวลาคอมไพล์ และคำแนะนำในการบรรจุ ในกรณีส่วนใหญ่ ตัวเลือกไฟล์พิมพ์เขียวที่ใช้ 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>

สิ่งนี้บอกให้ 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() {
    ...

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

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

        Context context = InstrumentationRegistry.getTargetContext();

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

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

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

สำหรับกรณีการใช้งานทั่วไป ให้จ้าง Atest

สำหรับกรณีที่ซับซ้อนมากขึ้นและต้องการการปรับแต่งที่หนักขึ้น ให้ทำตาม คำแนะนำการใช้เครื่องมือ