เพราะคำว่า test แต่ละคนไม่เท่ากันและไม่เหมือนกันด้วย บางทีคุยกันใช้ศัพท์เดียวกัน แต่เอาจริงแล้วไม่ได้เข้าใจตรงกัน เช่น นาย a บอก unit test นาย b ก็คุย unit test แต่เอาเข้าจริงสิ่งที่นาย b ทำเป็น integration test เป็นต้น ไหนจะเทรนด์ของ microservice เข้ามาอีกด้วย
ซึ่งในวันนี้ที่ได้มาเรียน อ้างอิงการทดสอบแต่ละระดับของบล็อกนี้
ในบทความเขาได้แบ่งออกเป็น 6 ระดับ
ในความเข้าใจของแต่ละระดับ แต่ละคนเข้าใจไม่ตรงกัน แต่ทางที่ดีที่สุด ทีมเดียวกันหรือองค์กร ควรจะเข้าใจให้ตรงกันจะดีที่สุด
มาต่อกันเถอะ ในที่นี้จะขอใช้ระดับการ test ตามของ martin fowler’s microservice นะคะ
1. Unit test
การทดสอบในส่วนของ function/method ที่มีขนาดเล็กที่สุดใน application เพื่อตรวจสอบว่าได้ค่าตามที่เราคาดหวังไว้หรือไม่ และถ้ามีส่วนที่เริ่มมี dependencies เข้ามาเกี่ยวข้อง เราสามารถใช้ test double เข้ามาช่วยได้
2. Integration test
การทดสอบกับ external service / data source ที่คุมไม่ได้ เช่น database, network ขอบเขตของมันคือการต่อจริง (ควรจะลองต่อจริงกันก่อนที่จะ deploy service ขึ้นไป)
3. Component test
การทดสอบกับ internal service (ทดสอบตาม scenarios ภายใน service เลย) แต่จะไม่แตะ network ใดๆเลย (กรณีที่มีต่อกับเพื่อนบ้านเราก็จะ stub / mock ไว้นั่นเอง)
4. Contract test
(ในที่สุดเราก็มาถึงเรื่อง contract test สักที ฮ่าๆๆ) การทดสอบแบบรวมระบบด้วยกัน
ถ้าภายใน project เดียวกันก็ใช้ interface เพราะถ้ามีการเปลี่ยนแปลงต้องมาเปลี่ยนที่ interface ป้องกันกรณีเปลี่ยนแปลง เช่น function B มีการเปลี่ยนการรับ parameter จาก 1 เป็น 2 และ function A มีการเรียกใช้ function B A จะพังทันทีเนื่องจากส่ง parameter ไปให้ B ไม่ครบ
ถ้าภายนอก (กรณีเรื่อง service อื่น) ใช้ API ซึ่งเราคงคุ้นเคยกันดี และการใช้ API ของใน contract test จะต้องดูที่มุมมองด้วยว่าเราเป็นผู้ให้บริการ หรือเป็นผู้ขอรับบริการ
Contract test ยังแบ่งเป็นหัวข้อย่อยๆ ไปอีกด้วยนะ
- Provider Contract ฝั่งของ Provider (ผู้ให้บริการหรือคนสร้าง) จะทำการสร้าง specification ของ API ขึ้นมาและให้ Consumer (ผู้รับบริการหรือผู้ใช้งาน)
Provider Contract เป็นแบบไหน ก็เหล่า OpenAPI ทั้งหลายนั้นแหละและถ้า Provider มีการเปลี่ยนแปลง specification ของ API ขึ้นมาจะต้องแจ้งให้กับ Consumer ด้วย ซึ่งเราก็ไม่รู้อีกว่า Consumer ไหนบ้างที่ได้รับผลกระทบนี้ ซึ่งอาจจะมารู้อีกทีคือตอน production แล้วก็ได้นะ :’)
- Consumer Contract ฝั่งของ Consumer (ผู้รับบริการหรือผู้ใช้งาน) จะเป็นคนออกแบบ specification ของ API เอง (ออกแบบตามคนใช้งาน ตามมุมมองของ consumer) และฝั่งของ Provider (ผู้ให้บริการหรือคนสร้าง) ต้องคอย support ตาม Consumer
เมื่อ Consumer ส่ง specification ให้ Provider แล้วจะทำการ stub / mock เอาไว้ก่อน และทาง Provider ก็เอาไป implement ต่อ โดยจะต้องสร้าง Contract test ไว้สำหรับให้ตัวเองทดสอบด้วย เช่น ถ้ามีการเปลี่ยนแปลงจะได้มาทดสอบกับของใน contract test ว่ามีผลกระทบกับ consumer ไหนหรือป่าว
Consumer ยิงหา Provider = Integration test
Consumer ยิงหา stub/mock ที่จำลองของ provider = Contract test
- Consumer Driven Contract เป็นส่วนของการบริหารจัดบรรดา Contract ที่มี ที่ Provider กับ Consumer มีการ interaction กันยังไง
ทำไมถึงได้มี Contract เข้ามา?
ถ้าเอาความเป็นเรามีเรื่องนี้กันอยู่แล้ว เพียงแต่เราไม่รู้ตัวกันแค่นั้นเอง คำๆนี้มันเกิดขึ้นมา เพราะเราขาดการ Communication ระหว่างกัน ทั้งในทีมเองหรือ provider/consumer จึงเป็นที่มาของ Contract test เพื่อเป็นข้อตกลงระหว่างกันว่าเราจะทำตามข้อตกลงนี้ เนื่องจากเจอปัญหา เช่น มีการเปลี่ยนชื่อ endpoint, เพิ่ม parameter, เปลี่ยน validation ของ input parameter เป็นต้น
มีแล้วดียังไง?
สำหรับตัวกาดเองเลย ถ้ามีเนี้ย จะลดความเสี่ยงตอนที่จะ integration test และ cost ที่ไม่จำเป็นได้นะ เพราะเคยเจอ integration test แล้วไม่ผ่านต้องรอไปอีก 1–2 อาทิตย์เลยทีเดียว
ถ้ามีการสื่อสารที่ดีกันอยู่ตลอดอยู่แล้ว contract test ก็ไม่จำเป็นต้องมีก็ได้นะ ><
Reference :