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

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

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

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

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

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

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

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

เรื่อง

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

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

ขอบเขต

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

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

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

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

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

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

การทดสอบ 1 หน่วยบางรายการไม่ได้ทำในเครื่อง และการทดสอบจากต้นทางถึงปลายทางบางรายการไม่ได้ทําในอุปกรณ์ สำหรับ ตัวอย่าง:

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

ตัวอย่าง

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

เอสเพรสโซ

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

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

UI การเขียน

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

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

ข้อมูลโค้ดนี้แสดงส่วนหนึ่งของการทดสอบ 1 หน่วยสําหรับ 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)

การกำหนดกลยุทธ์การทดสอบ

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

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

การทดสอบที่ไม่น่าเชื่อถือ

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

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

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

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

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

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

แนวทางการแยก

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

เทคนิคการแยกที่พบบ่อยมีดังนี้

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

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

เมื่อคุณได้ทราบเหตุผลที่คุณควรทดสอบ และการทดสอบหลักๆ 2 ประเภทแล้ว คุณก็สามารถ อ่านสิ่งที่ต้องทดสอบ

หรือถ้าคุณต้องการสร้างการทดสอบแรกแล้วเรียนรู้โดยทำ Testing Codelab