![]()
![]()
จดบันทึกไว้นิดหน่อยสำหรับการเขียน Unit test
สำหรับทดสอบ Android app ที่พัฒนาด้วย
Reactive for Java 2.x (RxJava)
ซึ่งมีโครงสร้างง่าย ๆ คือ
- Presenter สำหรับควบคุมการทำงานหลักของระบบ
- Repository สำหรับจัดการการดึงข้อมูลจาก REST APIs
โดยนำ RxJava มาใช้ในส่วนของ Presenter
เพื่อทำงานกับการดึงข้อมูลจาก Repository
คำถามที่ตั้งไว้คือ
จะทำการทดสอบในส่วนของ Presenter อย่างไรดี ?
เพราะว่ามีการใช้งานทั้ง Repository
หนักกว่านั้นคือ RxJava นั่นเอง
ดังนั้นมาเขียนชุดทดสอบกันดีกว่า
ปล.
ถ้าไม่ทดสอบใน Layer นี้ ก็ต้องไปทดสอบ Layer ที่สูงกว่านี้
ไม่ว่าจะเป็น UI testing และ Manual testing ต่อไป
แต่จะใช้เวลาในการทดสอบสูง !!
มาดู code ในส่วนของ Presenter ก่อนดีกว่า
[gist id="f86f43eaf629ef7e29df05686fb3ad9a" file="LoginPresenter.kt"]
คำอธิบาย
การทำงานง่ายมาก ๆ คือ
เรียกใช้งานการ authenication ผ่าน Repository
จากนั้นก็รอผลลัพธกลับมา
ซึ่งมีทั้งสำเร็จและไม่สำเร็จ
ดังนั้นเราต้องทดสอบทั้ง 2 กรณีด้วยนะ
การทดสอบมีความยุ่งยากนิดหน่อย
เนื่องจากมีหลายสิ่งอย่างต้องควบคุม
สิ่งที่เลือกใช้คือ
- Mockito สำหรับการทำ Stub และ Mock ทั้ง class และ interface ที่ Presenter ต้องใช้งาน
- class RxAndroidPlugin มาจาก Rx Android ใช้สำหรับการกำหนดค่าเริ่มต้นของการทำงาน
เรื่องของเครื่องมือนั้น จำเป็นต้องลงไปอ่านเอกสารของ library ที่นำมาใช้งานด้วย
ทั้ง RxJava และ Rx Android มันสำคัญมาก ๆ นะ
ได้เวลาการเขียน Unit test แล้ว
ขั้นตอนที่ 1 ทำการกำหนดค่าต่าง ๆ ที่ต้องใช้งานในการทดสอบ
ทั้งการสร้าง stub และ mock ของ class และ interface ที่ Presenter ใช้งาน
โดยสร้าง stub ของ class Repository สำหรับการกำหนดการทำงานตามชุดการทดสอบ
และสร้าง mock ของ interface View เพื่อใช้ตรวจสอบพฤติกรรมการทำงาน
รวมทั้งการกำหนดค่าต่าง ๆ
สำหรับจัดการทดสอบทั้ง Rx Android และ Mockito
แสดงดัง code
[gist id="f86f43eaf629ef7e29df05686fb3ad9a" file="LoginPresenterTest.kt"]
ขั้นตอนที่ 2 เขียนชุดการทดสอบแรกคือ กรณีทำงานสำเร็จ
สิ่งที่คาดหวังคือ function หรือ method ใน interface View จะต้องถูกเรียกใช้งาน 1 ครั้ง
เป็นการตรวจสอบพฤติกรรมการทำงานของ Presenter ว่าทำงานตามที่ต้องการหรือไม่ ?
โดยสิ่งที่ต้องทำคือ
การสร้าง stub ของ Repository ขึ้นมา
และกำหนดผลจากการทำงานของ Repository ให้ทำงานได้อย่างถูกต้อง
เขียนได้ดังนี้
[gist id="f86f43eaf629ef7e29df05686fb3ad9a" file="test_success.kt"]
ขั้นตอนที่ 3 เขียนชุดการทดสอบที่สองคือ กรณีทำงานไม่สำเร็จ
ในกรณีนี้มีเหตุการณ์มากมาย
ที่ทำให้การทำงานไม่ถูกต้อง
โดยสิ่งที่เลือกคือ กำหนดให้เกิด error เรื่องของ Network กลับมา
ผลที่คาดหวังคือ function หรือ method ใน interface View จะต้องไม่ถูกเรียก
เขียนได้ดังนี้
[gist id="f86f43eaf629ef7e29df05686fb3ad9a" file="test_error.kt"]
เพียงเท่านี้เราก็สามารถเขียนชุดการทดสอบแบบง่าย ๆ ได้แล้ว
ซึ่งน่าจะทำให้เรามั่นใจใน code ได้มากขึ้นมาบ้าง
เมื่อไปดูค่า code coverage ก็ได้ออกมาดังนี้
อย่าลืมว่า เมื่อเลือกอะไรมาใช้แล้ว
ใช้เป็นอย่างเดียวไม่พอ
จำเป็นต้องทดสอบมันได้ด้วย
ขอให้สนุกกับการเขียน code ครับ