Data Driven

วิธีการทดสอบหนึ่งที่ ได้รับความนิยมมาก คือ Data Driven Testing
โดยใช้สำหรับทดสอบขั้นตอนการทำงานเดิมๆ ด้วยข้อมูลที่แตกต่างกัน
ซึ่งใน JUnit สามารถทำการทดสอบลักษณะนี้ได้เช่นกัน
ดังนั้น มาดูกันว่าจะใช้งานอย่างไร

เริ่มจากตัวอย่างที่เราต้องการก่อน

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

ระดับสมาชิกปัจจุบันจำนวนแต้มสะสมผลการปรับระดับสมาชิก
Regular0Regular
Regular50Bronze
Regular200Silver
Regular500Gold
Regular1000Platinum

จากรูปแบบนี้ เราสามารถเขียน unit test แยกออกมาได้อย่างน้อยๆ ก็ 5  test case
ซึ่งหลายๆ คนก็ชอบ เนื่องจากมันแต่ละ test case แยกกันอย่างชัดเจน อ่านง่าย และ เข้าใจง่าย

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

การพัฒนาตามแนวคิด Data Driven นั้นก็ไม่ยากเลย
เนื่องจากมันคือการนำข้อมูลมาใส่โครงสร้างข้อมูลแบบ Array หรือ List
แล้วนำมาวนเพื่อทดสอบ เท่านั้นเอง
แต่ในบทความนี้ ผมขอยกตัวอย่างการพัฒนาด้วย JUnit
มาเริ่มกันเลยดีกว่า

รูปแบบการเขียนมีหลายแบบ แต่จะยกตัวอย่างมาอธิบาย 3 แบบ ดังต่อไปนี้

1. การใช้ Parameterized ของ JUnit

เป็นความสามารถพื้นฐานที่มาพร้อมกับ JUnit  มีการใช้งานดังนี้

  • ในการทดสอบจะต้อง run ผ่าน Parameterized สามารถประกาศผ่าน @RunWith(Parameterized.class)
  • method สำหรับสร้างข้อมูลทดสอบ จะต้องใส่ @Parameters
  • class ทดสอบจะต้องสร้าง constructor ที่มีจำนวน arguments เท่ากับข้อมูลที่ต้องการทดสอบ

มาดู code กันดีกว่า

จากการใช้งานพบว่า ต้องเขียน code ขึ้นมามากพอสมควร
รวมทั้งมีข้อจำกัดในการใช้งาน คือ จะผูกกับ class ไม่ใช่ test case
ซึ่งเป็นข้อจำกัดที่ส่งผลให้ในแต่ละ class มีข้อมูลเพียงชุดเดียวเท่านั้น

ซึ่งอาจจะไม่สะดวกในการใช้งานมากนัก ดังนั้นจึงมีคนสร้าง library มาใช้กัน
หนึ่งในนั้น ผมขอแนะนำ JUnit Params

2. การใช้ JUnitParams

เป็น library สร้างขึ้นมา เพื่อให้เขียน unit test ได้สะดวกมากยิ่งขึ้น
โดย library อยู่ที่ Google code  :: junitparams

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

  • เป็นตัว Runner ใหม่ก็คือ JUnitParamsRunner
  • ในแต่ละ test case สามารถระบุ Parameters ซึ่งเป็นคนละตัวจากแบบแรกนะ

มาดู code กันดีกว่า

มาถึงตอนนี้ เราสามารถกำหนดข้อมูลสำหรับการทดสอบแต่ละ test case ได้แล้ว
แถมไม่ต้องไปสร้าง constructor มา ให้ปวดหัวกันแล้ว

3. การใช้ JUnitParams  โดยดึงข้อมูลจาก class/method อื่นๆ

จากการใช้งานแบบที่ 2 นั้น อาจจะไม่คำถามว่า ถ้าข้อมูลที่ทำการทดสอบอยู่ในไฟล์ เช่น CSV, Excel เป็นต้น
จะทำอย่างไรดีล่ะ ?

ปัญหานี้ทาง JUnit Params ก็ได้เตรียมวิธีการไว้ให้ 2 แบบ คือ

3.1 ระบุข้อมูลที่ต้องการทดสอบ ไปยัง method

จากตัวอย่างจะสังเกตเห็นว่า JUnit Params ได้เตรียม method $ มาให้
สำหรับการแปลงข้อมูลที่ต้องการทดสอบ ไปยัง  array ของ object

3.2 ระบุข้อมูลที่ต้องการทดสอบ ไปยัง class
มีข้อกำหนดนิดหน่อยว่า method ใน class จะต้องมี signature ดังนี้ public static Object[] provideXXX() { }
และชื่อ method ต้องขึ้นต้นด้วยคำว่า provide และ return เป็น array ของ Object

สุดท้าย

แนวทางการพัฒนา unit test ด้วย JUnit ตามแนวคิด Data Driven ทั้ง 3 แบบ
น่าจะพอช่วยให้การเขียน unit test สนุกสนานมากยิ่งขึ้น

แต่ถ้าอยากให้ code การทดสอบนั้นสวยๆ แนะนำให้ลองใช้งาน testing framework อื่นๆ เช่น

  • Spock พัฒนาด้วยภาษา Groovy
  • Spec2 พัฒนาด้วยภาษา Scala

Source code ตัวอย่างอยู่ที่ Github :: Demo JUnit Data Driven