Flutter Demo by KBTG: Flutter Integration Test สำหรับผู้เริ่มต้น

Amorn Apichattanakul
KBTG Life
Published in
3 min readJul 21, 2021

Flutter Integration Test เป็นการเทสระบบที่ผู้ใช้งานจะได้เห็นจริงๆ แบบ End-to-End ซึ่งถือเป็นส่วนหนึ่งของการพัฒนาซอฟต์แวร์ โดยปกติเราจะแบ่งการเทสออกเป็น 3 แบบ

  1. Unit Test โปรแกรมเมอร์จะเป็นคนเขียนส่วนนี้เอง
  2. Integration Tests หรือ API Testing ส่วนใหญ่จะเป็นหน้าที่ทีม Test Automation
  3. UI Tests คือการเทสการกดปุ่มและใช้งานจริง ยิง API จริงบนเครื่องจริง จะเป็นการเทสที่จะได้ผลลัพธ์สุดท้ายที่จะใช้งานได้จริงๆ
Credit: https://medium.com/android-testing-daily/the-3-tiers-of-the-android-test-pyramid-c1211b359acd

การเทสแบบปกตินั้นจะใช้เป็นรูปแบบปิรามิดที่จะมี Unit Test เป็นหลัก แต่หลังๆ ผมเจอบางบทความและบางบริษัทที่เริ่มใช้เป็นรูปแบบเพชรแทน ซึ่งอาจจะยังไม่แพร่หลายมากนักและยังอยู่ระหว่างการทดสอบ โดยการเทสนี้จะโฟกัสไปที่เรื่องของการเชื่อมต่อกับระบบมากกว่า ลงรายละเอียดว่าส่วนย่อยๆ ส่วนไหนที่มีปัญหา แล้วทำไมคนถึงเริ่มทำแบบนี้กันนะ?

Credit: http://testerstories.com/2020/09/test-shapes/

ปัญหาของแบบปิรามิดเก่าก็คือเจ้าตัว Unit Tests ที่มีค่าใช้จ่ายสูงในการบำรุงรักษา เดิมทีจุดประสงค์ของการเขียน Unit Test คือการหาปัญหาให้เจอก่อนที่จะไปถึงเทสเตอร์และบน Production ซึ่งมีค่าใช้จ่ายสูง แต่บางบริษัทได้ทำการศึกษาและพบว่า Unit Test นั้นมีค่าใช้จ่ายที่สูงกว่าปัญหาที่เจออีก เลยมีคอนเซ็ปต์ว่าเราเน้นเทสการเชื่อมต่อว่าทำงานได้ถูกต้องดีกว่าไหม ทั้งนี้การที่จะไปเทสระดับงานเล็กๆ ไม่ได้แปลว่าเราจะเลิกเขียน Unit Test นะครับ แค่ไม่ควรทำให้ถึงระดับ 100% โดยทาง Google แนะนำว่าให้เทส Unit: API: UI ในสัดส่วน 70: 20:10

เดี๋ยวๆ เรากำลังไปไหน … กลับมาเรื่อง Flutter ต่อเถอะ

ผมเองเคยทำ UI Test ตอนที่เขียน Native iOS ส่วนตัวชอบ UI Test นะครับ รู้สึกว่าการที่ระบบทำงานและทดสอบตัวเองได้โดยที่เราไม่ต้องไปทำอะไรนั้นเยี่ยมมาก เราสามารถเขียนด้วยโค้ด เติมใน Storyboard หรือว่าจะใช้แบบ Record Mode ก็ได้ที่ไม่ต้องเขียนโค้ดใดๆ แถมทำงานได้หลายอย่างด้วย เช่น เปิดบราวเซอร์หรือเปิด SMS แต่พอผมได้มาเขียน Flutter ผมก็นำความรู้จากการเขียน Swift มาใช้กับ Flutter ด้วยเหมือนกัน พอได้ลอง UI Test อยากจะบอกว่า

UI Test ของ Flutter แย่เหลือเกิน…

อาจจะมองว่าดีในตัวของมัน แต่เมื่อเทียบกับตอนที่ผมเขียน Native ผมพบข้อจำกัดต่างๆ ดังนี้

  1. ไม่สามารถสั่งงาน Native Components ใดๆ ได้ เช่น ปิด Permission Pop-up ไม่ได้เลย ทำให้ไม่สามารถเทสได้แบบที่แท้จริง ต้องมาทำการแฮกแก้ไขเพื่อให้ทำงานได้แบบติดขัด Push Notification Pop-up ที่ขออนุญาตส่งข้อมูลก็ปิดไม่ได้ ร้องไห้ 1 รอบ 😢
  2. ทำงานนอกแอปใดๆ ไม่ได้เลย ไม่สามารถสั่งเปิด Safari หรือ SMS ได้
  3. ทำงาน Record Mode ไม่ได้ ถ้าจะเทสต้องเขียนโค้ดเองเท่านั้น ทำไมละ จำเป็นเหรอ? ตอนสมัย iOS ผมก็แค่สอน Tester ทำ Record Mode แล้วผมค่อย Clean Up ตัว Record Mode ที่ iOS ทำขึ้นมาให้ เพราะบางอันอาจจะดูแปลกๆ แต่ว่างานประมาณ 70–80% Tester สามารถทำเองได้ ในขณะที่ Flutter โปรแกรมเมอร์จะเป็นคนเขียนเองเท่านั้น ร้องไห้ 2 รอบ 😢😢

ฟังแล้วแบบว่า โห… มีแต่ข้อเสีย แล้วเราได้อะไรล่ะ? สิ่งที่ได้กลับมาก็คือ Cross-Platform UI Testing ครับ! 👍

เคยได้ยินว่าเขียนโค้ดครั้งเดียว ลงได้หลายเครื่อง อันนี้จะเป็นการเขียนเทสครั้งเดียวลงได้หลายเครื่องเช่นกัน Flutter ได้ทำตัวอย่างวิธีการทำ UI Testing ไว้ที่นี่แล้ว

ตอนนี้ UI Test มี 2 แบบด้วยกัน แบบเก่าคือ Flutter Driver ซึ่งกำลังจะยกเลิกแล้ว และ Flutter Team ก็ดันใจดีไม่เอาออกจาก Document ให้อีก ผมทำไปจนเสร็จเรียบร้อย แล้วเพิ่งมารู้ทีหลังว่าเก่าแล้ว 😿

หลังจากทำตามที่บอกแล้ว ผมก็เจอปัญหาบางอย่าง ถ้าแอปของคุณมีการใช้ Animation ต่างๆ (ซึ่งต้องมีแน่นอนอยู่แล้ว) จำเป็นจะต้องมีเทคนิคบางอย่างที่ทำให้สามารถเทสได้ ปัญหาจะเป็นตามด้านล่างนี้ครับ

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

หลังจากที่ได้ทำ UI Test มาประมาณ 2–3 อาทิตย์ ก็ได้แนวทางมาแล้วว่าจะเทสยังไง ผมได้ทำ Shell Script ที่ไว้สร้าง Report หลังจากเทสเสร็จด้วย แนวทางที่ผมได้มาจากการทำ UI Test จะมีดังนี้ครับ

  1. ใส่ Key ลงไปใน Widget และค้นหาด้วย Key ผมไม่ค่อยแน่ใจว่าเป็นสิ่งที่ถูกไหม เพราะบางบทความบอกว่า Key ใช้สำหรับเก็บ State ของ Widget เท่านั้น แต่ผมทำตาม Documentation ของ Flutter จึงคิดว่าใช้แบบนี้น่าจะถูกต้องแล้ว
  2. ให้ใช้ pumpAndSettle และ pump ทุกครั้งหลังจากที่มี Interaction ต่างๆ ภายในแอป ไม่ว่าจะเป็น Tap, Drag, หรือ Swipe ตัว pumpAndSettle จะใช้สำหรับส่วนที่ไม่มี Animation ในขณะที่ Pump ใช้กับพวก Animation
  3. PumpUntilFound สำคัญมากสำหรับแอปที่มี Animation ตลอดเวลา
  4. ต้องเช็ค UI ตลอดเวลาด้วย expect ในทุกๆ ขั้นตอน เพื่อให้มั่นใจว่าแอปยังทำงานไปในทิศทางที่ถูกต้อง ทุกคนที่ทำ UI Testing ผมเชื่อว่าเป็นเพราะไม่อยากมาเทสด้วยมือเองหรือมานั่งเฝ้ามองการเทส เราจึงจะใช้ Expect เป็นตัวเช็คว่าแอปเรายังไปหน้าที่ถูกต้องอยู่ใช่ไหม

ผมได้เตรียม script ui-test.sh เอาไว้ สามารถดาวน์โหลดตัวอย่างด้านล่างเพื่อไปศึกษาและทดลองเล่นได้เลยครับ รัน Command นี้ที่ Terminal bash ui-test.sh จะได้เห็นภาพมากขึ้น

ผมได้ทำวิดีโอ Demo ด้านบนมาให้ดูครับ

UI Test ทั้งสนุกและทำให้ระบบดูมีความหล่อขึ้นมาทันที ในอนาคตข้างหน้าอีก 2–3 เดือน ผมมีแผนที่จะเชื่อม Flutter UI Test เข้ากับ Robot Framework ถ้าได้อะไรคืบหน้าหรือแปลกใหม่จะนำมาฝากครับ อย่าลืม เล่าสู่กันฟัง by P’🐦

สำหรับชาวเทคคนไหนที่สนใจเรื่องราวดีๆแบบนี้ หรืออยากเรียนรู้เกี่ยวกับ Product ใหม่ๆ ของ KBTG สามารถติดตามรายละเอียดกันได้ที่เว็บไซต์ www.kbtg.tech

--

--

KBTG Life
KBTG Life

Published in KBTG Life

At KBTG, we never cease to develop and innovate financial technologies on top of our “Customer First” mindset. We are the driving force behind KBank’s success as well as their navigator exploring the digital world beyond Thailand.

Amorn Apichattanakul
Amorn Apichattanakul

Written by Amorn Apichattanakul

Google Developer Expert for Flutter & Dart | Senior Flutter/iOS Software Engineer @ KBTG