หัวข้อนี้อธิบายวิธีรวม API ที่ได้จากเฟรมเวิร์กในการทดสอบ ที่ใช้ประเมินพฤติกรรมของแต่ละส่วนย่อย
Fragment จะทำหน้าที่เป็นคอนเทนเนอร์ที่ใช้ซ้ำได้ภายในแอปของคุณ ซึ่งช่วยให้คุณทำสิ่งต่อไปนี้ได้ นำเสนอเลย์เอาต์อินเทอร์เฟซผู้ใช้ชุดเดียวกันในหลายๆ กิจกรรมและ และการกำหนดค่าเลย์เอาต์ทั้งหมด เนื่องจากส่วนย่อยมีความอเนกประสงค์ จึงมีความสำคัญ เพื่อมอบประสบการณ์การใช้งานที่สม่ำเสมอและประหยัดทรัพยากร ข้อควรทราบ
- ส่วนย่อยของคุณไม่ควรขึ้นอยู่กับกิจกรรมหลักที่เจาะจงหรือ ส่วนย่อย
- คุณไม่ควรสร้างลำดับชั้นการดูของส่วนย่อยนอกเสียจากว่าส่วนย่อย แสดงต่อผู้ใช้
ในการช่วยกำหนดเงื่อนไขสำหรับการทดสอบเหล่านี้ AndroidX
ไลบรารี fragment-testing
ให้บริการ
FragmentScenario
เพื่อสร้างส่วนย่อยและเปลี่ยนส่วน
Lifecycle.State
การประกาศทรัพยากร Dependency
หากต้องการใช้ FragmentScenario
ให้กำหนดอาร์ติแฟกต์ fragment-testing-manifest
ใน
ไฟล์ build.gradle
ของแอปที่ใช้ debugImplementation
และอาร์ติแฟกต์ fragment-testing
ที่ใช้ androidTestImplementation
ตามที่แสดงใน
ตัวอย่างต่อไปนี้
ดึงดูด
dependencies { def fragment_version = "1.8.3" debugImplementation "androidx.fragment:fragment-testing-manifest:$fragment_version" androidTestImplementation "androidx.fragment:fragment-testing:$fragment_version" }
Kotlin
dependencies { val fragment_version = "1.8.3" debugImplementation("androidx.fragment:fragment-testing-manifest:$fragment_version") androidTestImplementation("androidx.fragment:fragment-testing:$fragment_version") }
ตัวอย่างการทดสอบในหน้านี้ใช้การยืนยันจาก Espresso และ ไลบรารี Truth สำหรับข้อมูลเกี่ยวกับ ไลบรารีการทดสอบและการยืนยันอื่นๆ ที่มีอยู่ โปรดดู ตั้งค่าโปรเจ็กต์สำหรับ AndroidX Test
สร้างส่วนย่อย
FragmentScenario
มีเมธอดต่อไปนี้สำหรับการเปิดใช้ Fragment
ในการทดสอบ:
launchInContainer()
เพื่อทดสอบอินเทอร์เฟซผู้ใช้ของ FragmentFragmentScenario
แนบ ไปยังตัวควบคุมมุมมองรูทของกิจกรรม กิจกรรมนี้มีกิจกรรมอยู่ หรือว่างเปล่าlaunch()
สำหรับการทดสอบโดยไม่มีอินเทอร์เฟซผู้ใช้ของ FragmentFragmentScenario
แนบส่วนย่อยประเภทนี้กับกิจกรรมเปล่าซึ่งไม่ มีมุมมองรูท
หลังจากเปิดใช้งานหนึ่งในประเภทส่วนย่อยเหล่านี้ FragmentScenario
จะขับเคลื่อน
ส่วนย่อยภายใต้การทดสอบเป็นสถานะที่ระบุ โดยค่าเริ่มต้น สถานะนี้คือ RESUMED
แต่คุณสามารถลบล้างได้ด้วยอาร์กิวเมนต์ initialState
รัฐRESUMED
บ่งบอกว่าส่วนย่อยกำลังทำงานและแสดงต่อผู้ใช้ คุณสามารถประเมิน
ข้อมูลเกี่ยวกับองค์ประกอบ UI โดยใช้ Espresso UI
การทดสอบ
ตัวอย่างโค้ดต่อไปนี้แสดงวิธีเปิดใช้งานส่วนย่อยโดยใช้แต่ละวิธี
ตัวอย่างlaunchInContainer()
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
// The "fragmentArgs" argument is optional.
val fragmentArgs = bundleOf(“selectedListItem” to 0)
val scenario = launchFragmentInContainer<EventFragment>(fragmentArgs)
...
}
}
ตัวอย่างlaunch()
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
// The "fragmentArgs" arguments are optional.
val fragmentArgs = bundleOf("numElements" to 0)
val scenario = launchFragment<EventFragment>(fragmentArgs)
...
}
}
ระบุทรัพยากร Dependency
หาก Fragment มีทรัพยากร Dependency คุณระบุเวอร์ชันทดสอบของ
ทรัพยากร Dependency เหล่านี้ด้วยการระบุ FragmentFactory
ที่กำหนดเองให้กับเมธอด
launchInContainer()
หรือ launch()
เมธอด
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val someDependency = TestDependency()
launchFragmentInContainer {
EventFragment(someDependency)
}
...
}
}
หากต้องการข้อมูลเพิ่มเติมเกี่ยวกับการใช้ FragmentFactory
เพื่อให้
การอ้างอิงกับส่วนย่อย โปรดดู
ตัวจัดการส่วนย่อย
ขับเคลื่อนส่วนย่อยไปยังสถานะใหม่
ในการทดสอบ UI ของแอป ตามปกติแล้วการเรียกใช้ Fragment ก็เพียงพอแล้ว
อยู่ระหว่างทดสอบ และเริ่มทดสอบจากสถานะ RESUMED
แบบละเอียด
อย่างไรก็ดี คุณอาจประเมินลักษณะการทำงานของส่วนย่อยด้วย
เมื่อเปลี่ยนจากวงจรหนึ่งไปเป็นอีกวงจรหนึ่ง คุณสามารถระบุ
สถานะเริ่มต้นโดยการส่งอาร์กิวเมนต์ initialState
ไปยัง
launchFragment*()
ฟังก์ชัน
หากต้องการขับเคลื่อนส่วนย่อยไปยังสถานะวงจรอื่น ให้เรียกใช้
moveToState()
เมธอดนี้รองรับสถานะต่อไปนี้เป็นอาร์กิวเมนต์: CREATED
,
STARTED
, RESUMED
และ DESTROYED
วิธีนี้จำลองสถานการณ์
ส่วนที่ส่วนย่อยหรือกิจกรรมที่มีส่วนย่อยเปลี่ยนแปลง
ด้วยเหตุผลใดก็ตาม
ตัวอย่างต่อไปนี้จะเปิดส่วนย่อยการทดสอบในสถานะ INITIALIZED
และ
จากนั้นย้ายไปยังสถานะ RESUMED
:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val scenario = launchFragmentInContainer<EventFragment>(
initialState = Lifecycle.State.INITIALIZED
)
// EventFragment has gone through onAttach(), but not onCreate().
// Verify the initial state.
scenario.moveToState(Lifecycle.State.RESUMED)
// EventFragment moves to CREATED -> STARTED -> RESUMED.
...
}
}
สร้างส่วนย่อยใหม่
หากแอปของคุณกำลังทำงานบนอุปกรณ์ที่มีทรัพยากรต่ำ ระบบจะ
อาจทำลายกิจกรรมที่มีส่วนย่อยของคุณ สถานการณ์นี้
กำหนดให้แอปสร้างส่วนย่อยอีกครั้งเมื่อผู้ใช้ย้อนกลับ
หากต้องการจำลองสถานการณ์นี้ โปรดโทรหา recreate()
:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val scenario = launchFragmentInContainer<EventFragment>()
scenario.recreate()
...
}
}
FragmentScenario.recreate()
ทำลายส่วนย่อยและโฮสต์ของส่วนนั้น แล้วจึงสร้างใหม่ เมื่อ
คลาส FragmentScenario
จะสร้างส่วนย่อยอีกครั้งภายใต้การทดสอบ ซึ่งก็คือส่วนย่อย
จะกลับสู่สถานะของวงจรการใช้งานก่อนที่จะถูกทำลาย
การดำเนินการกับส่วนย่อยของ UI
หากต้องการทริกเกอร์การทำงานของ UI ในส่วนย่อยของคุณภายใต้การทดสอบ ให้ใช้ ตัวจับคู่มุมมองเอสเพรสโซ โต้ตอบกับองค์ประกอบในมุมมองของคุณ
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val scenario = launchFragmentInContainer<EventFragment>()
onView(withId(R.id.refresh)).perform(click())
// Assert some expected behavior
...
}
}
ถ้าคุณต้องการเรียกเมธอดในส่วนนั้น เช่น การตอบกลับ
ไปยังตัวเลือกในเมนูตัวเลือก คุณสามารถทำได้อย่างปลอดภัยโดย
อ้างอิงไปยังส่วนย่อยโดยใช้
FragmentScenario.onFragment()
และการผ่านใน
FragmentAction
:
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testEventFragment() {
val scenario = launchFragmentInContainer<EventFragment>()
scenario.onFragment { fragment ->
fragment.myInstanceMethod()
}
}
}
ทดสอบการทำงานของกล่องโต้ตอบ
FragmentScenario
ยังรองรับการทดสอบ
ส่วนย่อยของกล่องโต้ตอบ แม้ว่าส่วนย่อยของกล่องโต้ตอบ
มีองค์ประกอบ UI การจัดวางจะปรากฏในหน้าต่างแยกต่างหาก
มากกว่าในตัวกิจกรรมเอง ด้วยเหตุนี้ ให้ใช้
FragmentScenario.launch()
เพื่อทดสอบส่วนย่อยของกล่องโต้ตอบ
ตัวอย่างต่อไปนี้จะทดสอบกระบวนการปิดกล่องโต้ตอบ
@RunWith(AndroidJUnit4::class)
class MyTestSuite {
@Test fun testDismissDialogFragment() {
// Assumes that "MyDialogFragment" extends the DialogFragment class.
with(launchFragment<MyDialogFragment>()) {
onFragment { fragment ->
assertThat(fragment.dialog).isNotNull()
assertThat(fragment.requireDialog().isShowing).isTrue()
fragment.dismiss()
fragment.parentFragmentManager.executePendingTransactions()
assertThat(fragment.dialog).isNull()
}
}
// Assumes that the dialog had a button
// containing the text "Cancel".
onView(withText("Cancel")).check(doesNotExist())
}
}