android-testing
คำถามที่น่าสนใจคือ

ถ้าต้องการทำทดสอบส่วนการติดต่อผ่าน Network
เช่นเรียกใช้งาน RESTful API, WebService เป็นต้น
ไม่ว่าจะใช้ library ใด ๆ ก็ตาม
เช่น HttpURLConnection และ Retrofit เป็นต้น
เราจะเขียนชุดการทดสอบอย่างไรดี ?

เนื่องจากมีหลายวิธีเหลือเกิน
ดังนั้นจึงขอสรุปง่าย ๆ คือ มีการทดสอบ 2 แบบคือ

  1. ทำการทดสอบผ่าน Emulator/device
  2. ทำการทดสอบโดยไม่ใช้ Emulator/device

แบบที่ 1 ทำการทดสอบผ่าน Emulator/device

มีเป้าหมายเพื่อทดสอบว่า
app ยังสามารถทำงานได้จริงบน Emulator/device จริง
ซึ่งเป็นการทดสอบมุมมองของผู้ใช้งาน (Customer testing)
เนื่องจากต่อให้ app ดีเพียงใด
แต่ถ้าผู้ใช้งานไม่สามารถติดตั้งได้
แต่ถ้าผู้ใช้งานไม่สามารถใช้งานได้
มันก็คือ app กาก ๆ เท่านั้นเอง !!

แต่ข้อเสียของการทดสอบแบบนี้คือ
ใช้เวลาในการทดสอบนาน
เนื่องจากต้องทำการติดตั้ง และ ทดสอบผ่าน app จริง ๆ นั่นเอง
ดังนั้นจำนวน test case ของ End-to-End test จะต้องไม่เยอะจนเกินไป
หรือให้มีเท่าที่ครอบคลุมในระดับ feature นั่นเอง

คำถาม แล้วทดสอบอย่างไร ต้องใช้เครื่องมือ framework และ library อะไรบ้าง ?

ในปัจจุบันมีเครื่องมือมากมายให้ใช้งาน
บางครั้งเยอะจนเลือกไม่ถูก
แต่สิ่งที่ผมใช้งานคือ Espresso
ใช้งานคู่กับ MockWebServer สำหรับจำลอง Web Server ขึ้นมา

มาดูตัวอย่างการทดสอบด้วย Espresso + MockWebServer
มีขั้นตอนและแนวคิดในการทดสอบดังนี้

  • ก่อนทำการทดสอบแต่ละ test case ต้องทำการสร้างและ start MockWebServer
  • ในแต่ละ test case ทำการจำลองข้อมูลที่ส่งกลับมาจาก server ทั้ง success และ failure
  • ทำการทดสอบผ่าน UI ด้วย Espresso
  • เมื่อจบการทดสอบในแต่ละ test case จะปิด server ลงไป

เขียน code สำหรับการทดสอบได้แบบนี้

ข้อดีของวิธีการนี้คือ
เราสามารถทดสอบในกรณีต่าง ๆ ได้ง่าย ตาม HTTP Code
เช่น 200, 404 และ 501 เป็นต้น
รวมทั้ง code ที่เขียนขึ้นมาไม่เยอะเท่าไร

แต่ข้อเสียหลักคือ ถ้าต้องการให้ response มันเป็นแบบ dynamic
หรือเปลี่ยนแปลงไปตาม parameter ที่ส่งไปให้
จะต้องเขียน code เพิ่มอีกเยอะเลย

ยังไม่พอนะ Retrofit ยังมี Retrofit Mock ให้ใช้อีก 
ซึ่งสามารถกำหนดพฤติกรรมการทำงานของ network ได้เลย เช่น

  • Delay ของระบบ network
  • จำนวน error rate ของการทำงาน

แต่ถ้าไม่อยากเขียน code ให้ยุ่งยาก
ก็มีเครื่องมืออื่น ๆ ให้ใช้งานสำหรับจำลอง Web Server
เช่น WireMock และ Stubby เป็นต้น
แนะนำให้ใช้งานร่วมกับ BuildConfig

แบบที่ 2 ทำการทดสอบโดยไม่ใช้ Emulator/device

รวมทั้งไม่ต้อง start server เช่น MockWebServer
เนื่องจากใช้เวลาในการทดสอบที่นานเกินไป

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

เมื่อแยกส่วนการทำงานต่าง ๆ ออกจากกัน
แล้วนำมาเชื่อมด้วย Dependency Injection framework เช่น Dagger
หรืออาจจะเขียนเองก็ได้
ส่งผลทำให้โครงสร้างของระบบดูเป็นระเบียบมากยิ่งขึ้น
ทำให้มีแนวคิดที่ดีเกิดขึ้นมามากมายเช่น

  • MVC
  • MVP
  • MVVM
  • VIPER

สุดท้ายแล้ว

อย่าไปทดสอบ Retrofit แบบตรง ๆ ด้วยการ mock นะ
เพราะว่า มันไม่ได้มีคุณค่าอะไรต่อคุณและ app เลย
ให้ทดสอบในระดับ service การทำงานของระบบเลยดีกว่า

แต่ถ้าต้องการความมั่นใจกว่า
ก็แนะนำให้ใช้ตามแบบที่ 1
ซึ่งแน่นอนว่า มีทั้งข้อดีและข้อเสีย

ดังนั้นจึงต้องคิด วิเคราะห์ แยกแยะ ด้วยนะ
ว่าสิ่งที่เราทำอยู่นั้น มันมีคุณค่าต่อคุณ และ app หรือไม่ ?
ถ้าไม่ หรือ ไม่คุ้มต่อการลงทุน ก็ไม่ควรทำ !!

ปล. อย่าลืมทำหน้า monitoring ของระบบต่าง ๆ ที่เกี่ยวข้องด้วยนะ
เช่น RESTful API แต่ละตัวมีสถานะอย่างไรบ้าง ?
รวมถึงข้อมูลของการเรียกใช้งานอีกด้วย