ใช้การทดสอบแบบทวีคูณใน Android

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

อย่างไรก็ตาม หัวข้อทดสอบอาจขึ้นอยู่กับหัวข้ออื่นๆ จึงจะทํางานได้ ตัวอย่างเช่น ViewModel อาจต้องใช้ที่เก็บข้อมูลจึงจะทํางานได้

เมื่อต้องระบุการพึ่งพาให้กับเรื่องที่อยู่ภายใต้การทดสอบ แนวทางปฏิบัติทั่วไปคือการสร้าง test double (หรือ test object) Test Doubles คือออบเจ็กต์ที่มีลักษณะและทํางานเหมือนคอมโพเนนต์ในแอป แต่สร้างขึ้นในการทดสอบเพื่อให้ลักษณะการทํางานหรือข้อมูลหนึ่งๆ ข้อดีหลักๆ คือช่วยให้การทดสอบเร็วและง่ายขึ้น

ประเภทของ Test Double

Test Double มีหลายประเภท ได้แก่

ปลอม Test Double ที่มีการใช้งานคลาสที่ "ทํางาน" แต่ติดตั้งใช้งานในลักษณะที่เหมาะสําหรับการทดสอบแต่ไม่เหมาะสําหรับเวอร์ชันที่ใช้งานจริง

ตัวอย่างเช่น ฐานข้อมูลที่เก็บไว้ในหน่วยความจำ

ข้อมูลจำลองไม่จําเป็นต้องใช้เฟรมเวิร์กการจําลองและเป็นแบบเบา แนะนำ

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

ตัวอย่างเช่น ยืนยันว่ามีการเรียกใช้เมธอดในฐานข้อมูลเพียงครั้งเดียว

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

ตัวอย่าง: ฟังก์ชันว่างที่ส่งเป็น Callback การคลิก

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

ตัวอย่างการใช้

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

object FakeUserRepository : UserRepository {
    fun getUsers() = listOf(UserAlice, UserBob)
}

val const UserAlice = User("Alice")
val const UserBob = User("Bob")

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

Dependency ปลอมสามารถแสดงข้อมูลที่ทราบโดยไม่ต้องอาศัยแหล่งข้อมูลระยะไกล
รูปที่ 1: Dependency จําลองใน Unit Test

การทดสอบต่อไปนี้จะยืนยันว่า ViewModel แสดงชื่อผู้ใช้แรกต่อมุมมองอย่างถูกต้อง

@Test
fun viewModelA_loadsUsers_showsFirstUser() {
    // Given a VM using fake data
    val viewModel = ViewModelA(FakeUserRepository) // Kicks off data load on init

    // Verify that the exposed data is correct
    assertEquals(viewModel.firstUserName, UserAlice.name)
}

การแทนที่ UserRepository ด้วยค่าจำลองนั้นทำได้ง่ายในการทดสอบหน่วย เนื่องจากผู้ทดสอบเป็นผู้สร้าง ViewModel อย่างไรก็ตาม การแทนที่องค์ประกอบที่กำหนดเองในการทดสอบขนาดใหญ่อาจเป็นเรื่องยาก

การเปลี่ยนคอมโพเนนต์และการฉีด Dependency

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

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

รูปที่ 2: การทดสอบครั้งใหญ่ที่ครอบคลุมแอปส่วนใหญ่และข้อมูลระยะไกลจำลอง

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

ขั้นตอนถัดไป

หน้ากลยุทธ์การทดสอบจะแสดงวิธีปรับปรุงประสิทธิภาพโดยใช้การทดสอบประเภทต่างๆ