เมื่อการทดสอบเครื่องมือเริ่มต้นขึ้น แพ็คเกจเป้าหมายจะถูกรีสตาร์ทด้วยโค้ดเครื่องมือวัดที่แทรกและเริ่มต้นสำหรับการดำเนินการ ข้อยกเว้นประการหนึ่งคือแพ็กเกจเป้าหมายที่นี่ไม่สามารถเป็นเฟรมเวิร์กของแอปพลิเคชัน Android เอง เช่น แพ็กเกจ android
เนื่องจากการทำเช่นนั้นจะนำไปสู่สถานการณ์ที่ขัดแย้งกันซึ่งเฟรมเวิร์ก Android จะต้องเริ่มต้นใหม่ ซึ่งเป็นสิ่งที่สนับสนุนการทำงานของระบบ รวมถึงเครื่องมือวัด นั่นเอง
ซึ่งหมายความว่าการทดสอบเครื่องมือไม่สามารถแทรกตัวเองเข้าไปในเฟรมเวิร์กของ Android หรือที่เรียกว่าเซิร์ฟเวอร์ระบบสำหรับการดำเนินการ ในการทดสอบเฟรมเวิร์ก Android โค้ดทดสอบสามารถเรียกใช้ได้เฉพาะพื้นผิว API สาธารณะ หรือที่เปิดเผยผ่าน AIDL ภาษาคำจำกัดความของอินเทอร์เฟซ Android ที่มีอยู่ในโครงสร้างต้นทางของแพลตฟอร์ม สำหรับการทดสอบประเภทนี้ การกำหนดเป้าหมายแพ็คเกจใดแพ็คเกจหนึ่งไม่ได้มีความหมาย ดังนั้นจึงเป็นเรื่องปกติที่เครื่องมือดังกล่าวจะถูกประกาศให้กำหนดเป้าหมายแพ็กเกจแอปพลิเคชันทดสอบของตนเอง ตามที่กำหนดไว้ในแท็ก <manifest>
ของ AndroidManifest.xml
แพ็คเกจแอปพลิเคชันทดสอบในหมวดหมู่นี้อาจ:
- กิจกรรมบันเดิลที่จำเป็นสำหรับการทดสอบ
- แชร์รหัสผู้ใช้กับระบบ
- ลงนามด้วยรหัสแพลตฟอร์ม
- รวบรวมกับแหล่งที่มาของเฟรมเวิร์กแทนที่จะเป็น SDK สาธารณะ
การทดสอบเครื่องมือประเภทนี้บางครั้งเรียกว่าการทดสอบด้วยตนเอง ต่อไปนี้คือตัวอย่างการทดสอบเครื่องมือวัดด้วยตนเองในแหล่งที่มาของแพลตฟอร์ม:
ตัวอย่างที่กล่าวถึงในที่นี้คือการเขียนการทดสอบเครื่องมือวัดใหม่ด้วยชุดเป้าหมายที่ชุดแอปพลิเคชันทดสอบของตัวเอง คู่มือนี้ใช้การทดสอบต่อไปนี้เพื่อเป็นตัวอย่าง:
ขอแนะนำให้เรียกดูรหัสก่อนเพื่อรับความประทับใจก่อนดำเนินการต่อ
การตัดสินใจเลือกตำแหน่งต้นทาง
โดยทั่วไปแล้ว ทีมของคุณจะมีรูปแบบของสถานที่สำหรับตรวจสอบรหัสและสถานที่สำหรับเพิ่มการทดสอบอยู่แล้ว ทีมส่วนใหญ่มีที่เก็บ git เดียว หรือแชร์กับทีมอื่น แต่มีไดเร็กทอรีย่อยเฉพาะที่มีซอร์สโค้ดคอมโพเนนต์
สมมติว่าตำแหน่งรูทสำหรับแหล่งที่มาของคอมโพเนนต์ของคุณอยู่ที่ <component source root>
คอมโพเนนต์ส่วนใหญ่มีโฟลเดอร์ src
และ tests
อยู่ข้างใต้ และไฟล์เพิ่มเติมบางไฟล์ เช่น Android.mk
(หรือแตกเป็นไฟล์ .mk
เพิ่มเติม) ไฟล์รายการ AndroidManifest.xml
และไฟล์กำหนดค่าการทดสอบ 'AndroidTest.xml'
เนื่องจากคุณกำลังเพิ่มการทดสอบใหม่ล่าสุด คุณอาจต้องสร้างไดเร็กทอรี tests
ถัดจากคอมโพเนนต์ src
ของคุณ และใส่เนื้อหาลงในนั้น
ในบางกรณี ทีมของคุณอาจมีโครงสร้างไดเร็กทอรีเพิ่มเติมภายใต้ tests
เนื่องจากจำเป็นต้องรวมชุดการทดสอบต่างๆ ลงใน apk แต่ละรายการ และในกรณีนี้ คุณจะต้องสร้างไดเรกทอรีย่อยใหม่ภายใต้ tests
โดยไม่คำนึงถึงโครงสร้าง คุณจะลงเอยด้วยการเติมไดเร็กทอรี tests
หรือไดเร็กทอรีย่อยที่สร้างขึ้นใหม่ด้วยไฟล์ที่คล้ายกับสิ่งที่อยู่ในไดเร็กทอรี instrumentation
ในการเปลี่ยนแปลง gerrit ตัวอย่าง ส่วนด้านล่างจะอธิบายรายละเอียดเพิ่มเติมของแต่ละไฟล์
ไฟล์รายการ
เช่นเดียวกับแอปพลิเคชันทั่วไป โมดูลทดสอบเครื่องมือวัดแต่ละโมดูลต้องมีไฟล์รายการ หากคุณตั้งชื่อไฟล์เป็น AndroidManifest.xml
และระบุไฟล์ถัดจาก Android.mk
สำหรับโมดูลทดสอบของคุณ ไฟล์นั้นจะถูกรวมโดยอัตโนมัติโดย makefile หลักของ BUILD_PACKAGE
ก่อนดำเนินการต่อ ขอแนะนำให้อ่าน ภาพรวมของ App Manifest ก่อน
สิ่งนี้ให้ภาพรวมของส่วนประกอบพื้นฐานของไฟล์รายการและฟังก์ชันการทำงาน ดูตัวอย่างได้ที่ platform_testing/tests/example/instrumentation/AndroidManifest.xml
ภาพรวมอยู่ที่นี่เพื่อความสะดวก:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="android.test.example.helloworld" >
<application/>
<instrumentation android:name="androidx.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 นี้ควรได้รับรหัสผู้ใช้เดียวกัน ซึ่งก็คือรหัสประจำตัวรันไทม์ เป็นแพลตฟอร์มหลัก โปรดทราบว่าสิ่งนี้ขึ้นอยู่กับ apk ที่ลงนามด้วยใบรับรองเดียวกันกับแพลตฟอร์มหลัก (ดู LOCAL_CERTIFICATE
ในส่วนด้านบน) แต่แนวคิดต่างกัน:
- สิทธิ์หรือ API บางอย่างได้รับการปกป้องด้วยลายเซ็น ซึ่งต้องมีใบรับรองการลงนามเดียวกัน
- การอนุญาตหรือ API บางอย่างต้องการข้อมูลประจำตัวผู้ใช้
system
ของผู้โทร ซึ่งต้องใช้แพ็กเกจการโทรเพื่อแชร์ ID ผู้ใช้กับsystem
หากเป็นแพ็กเกจแยกต่างหากจากแพลตฟอร์มหลัก
<uses-library android:name="android.test.runner" />
สิ่งนี้จำเป็นสำหรับการทดสอบเครื่องมือวัดทั้งหมด เนื่องจากคลาสที่เกี่ยวข้องถูกบรรจุในไฟล์ไลบรารีเฟรมเวิร์ก jar ที่แยกต่างหาก ดังนั้นจึงต้องมีรายการพาธคลาสเพิ่มเติมเมื่อเรียกใช้แพ็คเกจการทดสอบโดยแอปพลิเคชันเฟรมเวิร์ก
android:targetPackage="android.test.example.helloworld"
คุณอาจสังเกตเห็นว่า targetPackage
ที่นี่ถูกประกาศเหมือนกับแอตทริบิวต์ของ package
ที่ประกาศในแท็ก manifest
ของไฟล์นี้ ดังที่กล่าวไว้ใน การทดสอบพื้นฐาน การ ทดสอบเครื่องมือประเภทนี้โดยทั่วไปมีไว้สำหรับการทดสอบเฟรมเวิร์ก API ดังนั้นจึงไม่มีความหมายมากนักสำหรับพวกเขาที่จะมีแพ็คเกจแอปพลิเคชันที่กำหนดเป้าหมายเฉพาะ นอกเหนือจากตัวมันเอง
ไฟล์การกำหนดค่าอย่างง่าย
โมดูลทดสอบใหม่แต่ละโมดูลต้องมีไฟล์การกำหนดค่าเพื่อสั่งระบบบิลด์ด้วยข้อมูลเมตาของโมดูล การพึ่งพาเวลาคอมไพล์ และคำแนะนำในการบรรจุ ในกรณีส่วนใหญ่ ตัวเลือกไฟล์พิมพ์เขียวที่ใช้ Soong ก็เพียงพอแล้ว สำหรับรายละเอียด โปรดดู การกำหนดค่าการทดสอบอย่างง่าย
ไฟล์การกำหนดค่าที่ซับซ้อน
สำหรับกรณีที่ซับซ้อนกว่านี้ คุณต้องเขียนไฟล์การกำหนดค่าการทดสอบสำหรับชุดทดสอบของ Android, Trade Federation
การกำหนดค่าการทดสอบสามารถระบุตัวเลือกการตั้งค่าอุปกรณ์พิเศษและอาร์กิวเมนต์เริ่มต้นเพื่อจัดหาคลาสการทดสอบ ดูตัวอย่างที่ /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 ติดตั้ง HelloWorldTests.apk ลงในอุปกรณ์เป้าหมายโดยใช้ target_preparer ที่ระบุ มีตัวเตรียมเป้าหมายมากมายสำหรับนักพัฒนาใน 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 ในกรณีนี้
สำหรับข้อมูลเพิ่มเติม โปรดดู การกำหนดค่าโมดูลทดสอบ
คุณสมบัติ JUnit4
การใช้ไลบรารี android-support-test
เรียกใช้การทดสอบทำให้สามารถใช้คลาสทดสอบสไตล์ JUnit4 ใหม่ได้ และการเปลี่ยนแปลง gerrit ตัวอย่างมีการใช้งานคุณสมบัติพื้นฐานบางอย่าง ดูตัวอย่างที่ /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 ไม่จำเป็นต้องใช้คลาสพื้นฐานทั่วไปอีกต่อไป จึงไม่จำเป็นต้องขอรับอินสแตนซ์เครื่องมือวัดผ่าน InstrumentationRegistry
InstrumentationTestCase#getInstrumentation()
อีกต่อไป แต่ Instrumentation
ทดสอบใหม่จะจัดการผ่าน
หากต้องการเข้าถึงอินสแตนซ์ของคลาส Instrumentation
ให้เรียกเมธอดแบบคงที่ getInstrumentation()
ในคลาส InstrumentationRegistry
:
Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation()
สร้างและทดสอบในพื้นที่
สำหรับกรณีการใช้งานทั่วไป ให้จ้าง Atest
สำหรับกรณีที่ซับซ้อนมากขึ้นและต้องการการปรับแต่งที่หนักขึ้น ให้ทำตาม คำแนะนำการใช้เครื่องมือ