พื้นฐานการทดสอบแอป Android

หน้านี้สรุปหลักการสำคัญของการทดสอบแอป Android ซึ่งรวมถึงแนวทางปฏิบัติแนะนำหลักและประโยชน์ของแนวทางดังกล่าว

สิทธิประโยชน์ของการทดสอบ

การทดสอบเป็นส่วนสำคัญของกระบวนการพัฒนาแอป การทดสอบแอปอย่างสม่ำเสมอช่วยยืนยันความถูกต้อง ลักษณะการทำงาน และความสามารถในการใช้งานของแอปก่อนที่จะเผยแพร่ต่อสาธารณะได้

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

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

ประเภทของการทดสอบใน Android

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

เรื่อง

เช่น มีการทดสอบหลายประเภทขึ้นอยู่กับ เรื่อง ดังนี้

  • การทดสอบฟังก์ชันการทำงาน: แอปของฉันทำงานตามที่ควรจะเป็นหรือไม่
  • การทดสอบประสิทธิภาพ: แอปทำงานได้อย่างรวดเร็วและมีประสิทธิภาพหรือไม่
  • การทดสอบการช่วยเหลือพิเศษ: แอปทำงานได้ดีกับบริการการช่วยเหลือพิเศษหรือไม่
  • การทดสอบความเข้ากันได้: แอปทำงานได้ดีในอุปกรณ์ทุกเครื่องและระดับ API ทุกระดับหรือไม่

ขอบเขต

การทดสอบยังแตกต่างกันไปตาม ขนาด หรือ ระดับการแยก ดังนี้

  • Unit Test หรือ การทดสอบขนาดเล็ก จะตรวจสอบเฉพาะส่วนเล็กๆ ของแอป เช่น เมธอดหรือคลาส
  • การทดสอบแบบ End-to-End หรือ การทดสอบขนาดใหญ่ จะตรวจสอบส่วนที่ใหญ่ขึ้นของแอปในเวลาเดียวกัน เช่น ทั้งหน้าจอหรือขั้นตอนของผู้ใช้
  • การทดสอบขนาดกลาง จะอยู่ระหว่างการทดสอบขนาดเล็กและขนาดใหญ่ และตรวจสอบการผสานรวม ระหว่างหน่วย 2 หน่วยขึ้นไป
การทดสอบอาจมีขนาดเล็ก ปานกลาง หรือใหญ่ก็ได้
รูปที่ 1: ขอบเขตการทดสอบในแอปพลิเคชันทั่วไป

การทดสอบสามารถจำแนกได้หลายวิธี อย่างไรก็ตาม สิ่งที่สำคัญที่สุดสำหรับนักพัฒนาแอปคือตำแหน่งที่การทดสอบทำงาน

การทดสอบแบบมีเครื่องมือเทียบกับการทดสอบในเครื่อง

คุณสามารถทำการทดสอบในอุปกรณ์ Android หรือในคอมพิวเตอร์เครื่องอื่นได้ ดังนี้

  • การทดสอบแบบมีเครื่องมือ จะทำงานในอุปกรณ์ Android ไม่ว่าจะเป็นอุปกรณ์จริงหรืออุปกรณ์จำลอง ระบบจะสร้างและติดตั้งแอปควบคู่ไปกับ แอปทดสอบ ที่แทรกคำสั่งและอ่านสถานะ โดยปกติแล้วการทดสอบแบบมีเครื่องมือจะเป็นการทดสอบ UI ซึ่งจะเปิดแอปแล้วโต้ตอบกับแอป
  • การทดสอบในเครื่อง จะทำงานในคอมพิวเตอร์สำหรับการพัฒนาซอฟต์แวร์หรือเซิร์ฟเวอร์ จึงเรียกอีกอย่างว่า การทดสอบฝั่งโฮสต์ โดยปกติแล้วการทดสอบเหล่านี้จะมีขนาดเล็กและรวดเร็ว ซึ่งจะแยกเรื่องที่ทดสอบออกจากส่วนอื่นๆ ของแอป
การทดสอบสามารถทำงานเป็นการทดสอบการวัดคุมบนอุปกรณ์ หรือการทดสอบในเครื่องบนคอมพิวเตอร์สำหรับการพัฒนาซอฟต์แวร์
รูปที่ 2: การทดสอบประเภทต่างๆ ขึ้นอยู่กับตำแหน่งที่การทดสอบทำงาน

ไม่ใช่ว่า Unit Test ทั้งหมดจะเป็นการทดสอบในเครื่อง และไม่ใช่ว่าการทดสอบแบบ End-to-End ทั้งหมดจะทำงานในอุปกรณ์ ตัวอย่างเช่น

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

ตัวอย่าง

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

Espresso

// When the Continue button is clicked
onView(withText("Continue"))
    .perform(click())

// Then the Welcome screen is displayed
onView(withText("Welcome"))
    .check(matches(isDisplayed()))

Compose UI

// When the Continue button is clicked
composeTestRule.onNodeWithText("Continue").performClick()

// Then the Welcome screen is displayed
composeTestRule.onNodeWithText("Welcome").assertIsDisplayed()

ข้อมูลโค้ดนี้แสดงส่วนหนึ่งของ Unit Test สำหรับ ViewModel (การทดสอบในเครื่อง ฝั่งโฮสต์)

// Given an instance of MyViewModel
val viewModel = MyViewModel(myFakeDataRepository)

// When data is loaded
viewModel.loadData()

// Then it should be exposing data
assertTrue(viewModel.data != null)

สถาปัตยกรรมที่ทดสอบได้

สถาปัตยกรรมของแอปที่ทดสอบได้คือโค้ดเป็นไปตามโครงสร้างที่ช่วยให้คุณทดสอบส่วนต่างๆ ของโค้ดได้อย่างง่ายดายโดยแยกกัน สถาปัตยกรรมที่ทดสอบได้มีข้อดีอื่นๆ เช่น อ่านง่ายขึ้น บำรุงรักษาได้ง่ายขึ้น ปรับขนาดได้ง่ายขึ้น และนำกลับมาใช้ใหม่ได้ง่ายขึ้น

สถาปัตยกรรมที่ ทดสอบไม่ได้ จะทำให้เกิดสิ่งต่อไปนี้

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

ดูข้อมูลเพิ่มเติมเกี่ยวกับหลักเกณฑ์ด้านสถาปัตยกรรมได้ที่คู่มือสถาปัตยกรรมของแอป

แนวทางในการแยกส่วนประกอบ

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

เทคนิคการแยกส่วนประกอบที่ใช้กันโดยทั่วไปมีดังนี้

  • แบ่งแอปออกเป็น เลเยอร์ เช่น การนำเสนอ โดเมน และข้อมูล นอกจากนี้ คุณยังแบ่งแอปออกเป็น โมดูล ได้ด้วย โดยโมดูลหนึ่งโมดูลต่อฟีเจอร์
  • หลีกเลี่ยงการเพิ่มตรรกะลงในเอนทิตีที่มีการพึ่งพาจำนวนมาก เช่น กิจกรรมและ Fragment ใช้คลาสเหล่านี้เป็นจุดเริ่มต้นของเฟรมเวิร์ก และย้าย UI และตรรกะทางธุรกิจ ไปไว้ที่อื่น เช่น ไปไว้ใน Composable, ViewModel หรือเลเยอร์โดเมน
  • หลีกเลี่ยง การพึ่งพาเฟรมเวิร์ก โดยตรงในคลาสที่มีตรรกะทางธุรกิจ เช่น อย่าใช้บริบท Android ใน ViewModel
  • ทำให้ การแทนที่ การพึ่งพาง่ายขึ้น เช่น ใช้ อินเทอร์เฟซแทนการติดตั้งใช้งานที่เป็นรูปธรรม ใช้ การแทรกทรัพยากร Dependencyแม้ว่าคุณจะไม่ได้ใช้เฟรมเวิร์ก DI ก็ตาม

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

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

หรือหากต้องการสร้างการทดสอบแรกและเรียนรู้จากการลงมือทำ โปรดดู Codelab การทดสอบ