ส่วนขยาย Chrome: เส้นทางการทดสอบการระงับการทำงานของ Service Worker

เรื่องนี้เกี่ยวกับอะไร

การเปลี่ยนจาก Manifest V2 เป็น Manifest V3 มาพร้อมกับการเปลี่ยนแปลงพื้นฐาน ใน Manifest V2 ส่วนขยายจะอยู่ในหน้าเบื้องหลัง หน้าพื้นหลังจัดการการสื่อสารระหว่างส่วนขยายกับหน้าเว็บ Manifest V3 ใช้ Service Worker แทน

ในโพสต์นี้ เราจะเจาะลึกปัญหาการทดสอบเจ้าหน้าที่ฝ่ายสนับสนุนทางเทคนิค โดยเฉพาะอย่างยิ่ง เราจะดูวิธีตรวจสอบว่าผลิตภัณฑ์ทำงานได้อย่างถูกต้องในกรณีที่ Service Worker ถูกระงับ

เราคือใคร

eyeo เป็นบริษัทที่มุ่งมั่นที่จะส่งเสริมให้เกิดการเปลี่ยนมูลค่าออนไลน์ที่สมดุลและยั่งยืนสำหรับผู้ใช้ เบราว์เซอร์ ผู้ลงโฆษณา และผู้เผยแพร่โฆษณา เรามีผู้ใช้ทั่วโลกที่กรองโฆษณามากกว่า 300 ล้านคนที่อนุญาตให้แสดงโฆษณาที่ยอมรับได้ ซึ่งเป็นมาตรฐานโฆษณาที่พัฒนาขึ้นโดยอิสระซึ่งจะกำหนดว่าโฆษณานั้นยอมรับได้และไม่เป็นการรบกวนหรือไม่

ทีมเครื่องมือส่วนขยายของเราให้บริการเทคโนโลยีการกรองโฆษณาที่ขับเคลื่อนส่วนขยายเบราว์เซอร์ที่บล็อกโฆษณาซึ่งได้รับความนิยมมากที่สุดบางรายการในตลาด เช่น AdBlock และ Adblock Plus ซึ่งมีผู้ใช้มากกว่า 110 ล้านคนทั่วโลก นอกจากนี้ เรายังนำเสนอเทคโนโลยีนี้เป็นคลังโอเพนซอร์สเพื่อให้ส่วนขยายเบราว์เซอร์อื่นๆ ที่กรองโฆษณาใช้งานได้

เวิร์กเกอร์บริการคืออะไร

เวิร์กเกอร์บริการส่วนขยายคือตัวแฮนเดิลเหตุการณ์ส่วนกลางของส่วนขยายเบราว์เซอร์ โดยทำงานอิสระในเบื้องหลัง โดยทั่วไปแล้ว ไม่เป็นไร เราทําสิ่งต่างๆ ส่วนใหญ่ที่ต้องทำในหน้าเบื้องหลังได้ใน Service Worker ใหม่ แต่มีการเปลี่ยนแปลงบางอย่างเมื่อเทียบกับหน้าเบื้องหลัง ดังนี้

  • Service Worker จะหยุดทำงานเมื่อไม่ได้ใช้งาน ซึ่งทำให้เราต้องเก็บสถานะแอปพลิเคชันไว้แทนที่จะใช้ตัวแปรส่วนกลาง ซึ่งหมายความว่าต้องเตรียมจุดแรกเข้าระบบของเราให้พร้อมเรียกใช้ก่อนที่จะเริ่มต้นระบบ
  • ต้องแนบ Listener เหตุการณ์ก่อนรอการเรียกกลับแบบแอสซิงค์ Service Worker ที่ถูกระงับจะยังคงรับเหตุการณ์ที่สมัครรับข้อมูลไว้ได้ หากไม่ได้ลงทะเบียนตัวรับฟังเหตุการณ์ในรอบแรกของลูปเหตุการณ์ ตัวรับฟังจะไม่ได้รับการแจ้งเตือนหากเหตุการณ์ดังกล่าวปลุก Service Worker
  • การสิ้นสุดการทำงานที่ไม่ได้ใช้งานอาจขัดจังหวะตัวจับเวลาก่อนที่ตัวจับเวลาจะทำงานเสร็จ

กรณีใดบ้างที่ Service Worker จะถูกระงับ

สำหรับ Chrome 119 สิ่งที่เราพบคือ Service Worker ถูกระงับในกรณีต่อไปนี้

  • หลังจากไม่ได้รับเหตุการณ์หรือการเรียก API ของส่วนขยายเป็นเวลา 30 วินาที
  • ไม่เคย หากเครื่องมือสําหรับนักพัฒนาซอฟต์แวร์เปิดอยู่หรือคุณใช้คลังการทดสอบที่อิงตาม ChromeDriver (ดูคําขอฟีเจอร์)
  • หากคุณคลิกหยุดใน chrome://serviceworker-internals

ดูข้อมูลล่าสุดได้ที่วงจรชีวิตของ Service Worker

เหตุใดการทดสอบจึงมีปัญหา

การมีคําแนะนําอย่างเป็นทางการเกี่ยวกับ "วิธีทดสอบ Service Worker อย่างมีประสิทธิภาพ" หรือตัวอย่างการทดสอบที่ใช้งานได้จะเป็นประโยชน์อย่างยิ่ง ในระหว่างการทดสอบผู้ให้บริการ เราพบปัญหาบางอย่างดังนี้

  • เรามีสถานะในส่วนขยายทดสอบ เมื่อ Service Worker หยุดทำงาน เราจะสูญเสียสถานะและเหตุการณ์ที่ลงทะเบียนไว้ เราจะเก็บข้อมูลในขั้นตอนการทดสอบได้อย่างไร
  • หาก Service Worker ถูกระงับได้ทุกเมื่อ เราจะต้องทดสอบว่าฟีเจอร์ทั้งหมดทำงานได้หากถูกขัดจังหวะ
  • แม้ว่าเราจะแนะนำกลไกในการทดสอบที่ระงับ Service Worker แบบสุ่ม แต่เบราว์เซอร์ก็ไม่มี API ที่จะระงับ Service Worker ได้อย่างง่ายดาย เราได้ขอให้ทีม W3C เพิ่มฟีเจอร์นี้ แต่เรายังอยู่ระหว่างการพูดคุยกัน

การทดสอบการระงับ Service Worker

เราได้ลองใช้แนวทางต่างๆ เพื่อทริกเกอร์การระงับ Service Worker ในระหว่างการทดสอบ ดังนี้

แนวทาง ปัญหาเกี่ยวกับแนวทาง
รอตามระยะเวลาที่ต้องการ (เช่น 30 วินาที) ซึ่งทําให้การทดสอบช้าและไม่น่าเชื่อถือ โดยเฉพาะอย่างยิ่งเมื่อทำการทดสอบหลายรายการ การดำเนินการนี้จะไม่ทำงานเมื่อใช้ WebDriver เนื่องจาก WebDriver ใช้ DevTools API ของ Chrome และระบบจะไม่ระงับ Service Worker เมื่อ DevTools เปิดอยู่ แม้ว่าจะข้ามได้ แต่เราก็ยังต้องตรวจสอบว่า Service Worker ถูกระงับหรือไม่ และเราไม่มีวิธีตรวจสอบ
เรียกใช้ลูปแบบไม่รู้จบใน Service Worker ข้อมูลจำเพาะระบุว่าการดำเนินการนี้อาจนำไปสู่การสิ้นสุดการใช้งาน ทั้งนี้ขึ้นอยู่กับวิธีที่เบราว์เซอร์ใช้ฟังก์ชันการทำงานนี้ Chrome จะไม่สิ้นสุดการทำงานของ Service Worker ในกรณีนี้ เราจึงทดสอบสถานการณ์เมื่อ Service Worker ถูกระงับไม่ได้
มีข้อความใน Service Worker เพื่อตรวจสอบว่าถูกระงับหรือไม่ การส่งข้อความจะปลุก Service Worker ข้อมูลนี้สามารถใช้เพื่อตรวจสอบว่า Service Worker อยู่ในสถานะ "หยุดทำงาน" หรือไม่ แต่จะทำให้ผลการทดสอบที่จำเป็นต้องตรวจสอบทันทีหลังจากระงับ Service Worker ใช้งานไม่ได้
หยุดกระบวนการของ Service Worker โดยใช้ chrome.processes.terminate() Service Worker ของส่วนขยายจะแชร์กระบวนการกับส่วนอื่นๆ ของส่วนขยาย ดังนั้นการสิ้นสุดกระบวนการนี้โดยใช้ chrome.process.terminate() หรือ GUI ของตัวจัดการกระบวนการของ Chrome จะไม่เพียงแต่สิ้นสุด Service Worker เท่านั้น แต่ยังสิ้นสุดหน้าส่วนขยายด้วย

สุดท้ายเราทำการทดสอบเพื่อตรวจสอบว่าโค้ดของเราตอบสนองอย่างไรเมื่อ Service Worker ถูกระงับโดยให้ Selenium WebDriver เปิด chrome://serviceworker-internals/ แล้วคลิกปุ่ม "หยุด" สำหรับ Service Worker

นี่เป็นตัวเลือกที่ดีที่สุดเท่าที่มีมา แต่ก็ยังไม่ใช่ตัวเลือกที่ดีที่สุด เนื่องจากการทดสอบ Mocha (ซึ่งทำงานในหน้าส่วนขยาย) ทําเช่นนี้ด้วยตนเองไม่ได้ จึงต้องสื่อสารกลับไปที่โปรแกรมโหนด WebDriver ซึ่งหมายความว่าการทดสอบเหล่านี้จะทํางานโดยใช้เพียงส่วนขยายไม่ได้ แต่จะต้องมีการเรียกให้แสดงโดยใช้ Selenium WebDriver

แผนภาพต่อไปนี้แสดงวิธีที่เราสื่อสารกับเบราว์เซอร์ API ผ่านขั้นตอนต่างๆ และผลกระทบที่การเพิ่มกลไก "การระงับ Service Worker" มีต่อ API

แผนภาพแสดงขั้นตอนการทดสอบ
ขั้นตอนการทดสอบด้วยการระงับ Service Worker

ในขั้นตอนใหม่ที่ระงับ Service Worker (สีน้ำเงิน) เราได้เพิ่ม Selenium WebDriver เพื่อ "คลิก" ระงับผ่าน UI ซึ่งจะทริกเกอร์การดำเนินการในเบราว์เซอร์ API

โปรดทราบว่ามีข้อบกพร่องของ Chrome ที่ทำให้การดําเนินการนี้กับ Selenium WebDriver ทําให้ Service Worker เริ่มทํางานอีกครั้งไม่ได้ ปัญหานี้ได้รับการแก้ไขแล้วใน Chrome 116 และโชคดีที่มีวิธีแก้ปัญหาชั่วคราวด้วย โดยการตั้งค่าให้ Chrome เปิดเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์โดยอัตโนมัติในทุกแท็บจะทำให้ Service Worker เริ่มทำงานอย่างถูกต้อง

นี่เป็นแนวทางที่เราใช้เมื่อทำการทดสอบ แม้ว่าจะไม่ใช่แนวทางที่ดีที่สุดเนื่องจากการคลิกปุ่มอาจไม่ใช่ API ที่เสถียร และการเปิดเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ (สําหรับเบราว์เซอร์รุ่นเก่า) ดูเหมือนว่าจะมีต้นทุนด้านประสิทธิภาพ

เราจะครอบคลุมฟังก์ชันการทำงานทั้งหมดได้อย่างไร การทดสอบ Fuzz

เมื่อเรามีกลไกในการทดสอบการระงับแล้ว เราจะต้องตัดสินใจว่าจะนำไปใช้กับชุดทดสอบการทำงานอัตโนมัติอย่างไร เราทำการทดสอบมาตรฐานในสภาพแวดล้อมที่ก่อนการโต้ตอบกับหน้าเบื้องหลังแต่ละครั้ง Service Worker ถูกระงับโดย WebDriver คลิกหยุดในหน้า chrome://serviceworker-internals/

ตัวอย่างการเรียกใช้การดำเนินการทดสอบแบบ Fuzz
รูปภาพที่แสดงการตั้งค่าการทดสอบปัจจุบัน

เราทำการทดสอบส่วนใหญ่แต่ไม่ได้ทำการทดสอบทั้งหมด เนื่องจากกลไกการระงับยังไม่เสถียรมากนักและบางครั้งอาจทำให้เกิดความผิดพลาด นอกจากนี้ การรันชุดทดสอบทั้งหมดในโหมด Fuzz ยังใช้เวลานานมาก ดังนั้น เราจึงเลือกเส้นทางที่สำคัญที่สุดมาทดสอบในโหมด Fuzz แทนที่จะครอบคลุมกรณี "คล้ายกัน" ทั้งหมด โปรดทราบว่าการเรียกใช้การทดสอบฟังก์ชันการทำงานในโหมด "Fuzz" หมายความว่าเราต้องเพิ่มการหมดเวลาของการทดสอบเนื่องจากการระงับและเริ่ม Service Worker อีกครั้งจะใช้เวลาเพิ่มเติม

การทดสอบเหล่านี้มีประโยชน์ในการเรียกใช้ครั้งแรกแบบหยาบๆ ซึ่งจะไฮไลต์ตำแหน่งต่างๆ ที่โค้ดทำงานไม่สำเร็จ แต่อาจไม่พบวิธีทั้งหมดที่ละเอียดอ่อนซึ่งการระงับ Service Worker อาจทําให้ระบบขัดข้อง

เรียกการทดสอบประเภทนี้ว่า "การทดสอบ Fuzz" โดยทั่วไปแล้ว การทดสอบแบบ Fuzz คือการนำอินพุตที่ไม่ถูกต้องไปป้อนโปรแกรมและตรวจสอบว่าโปรแกรมตอบสนองอย่างสมเหตุสมผล หรืออย่างน้อยก็ไม่ขัดข้อง ในกรณีของเรา "อินพุตที่ไม่ถูกต้อง" คือ Service Worker ถูกระงับได้ทุกเมื่อ และ "ลักษณะการทำงานที่สมเหตุสมผล" ที่เราคาดหวังคือฟังก์ชันการกรองโฆษณาต้องทํางานต่อไปได้เหมือนเดิม อินพุตนี้ไม่ใช่อินพุตที่ไม่ถูกต้องเนื่องจากเป็นลักษณะการทำงานปกติใน Manifest V3 แต่จะเป็นอินพุตที่ไม่ถูกต้องใน Manifest V2 จึงดูเหมือนเป็นคำศัพท์ที่เหมาะสม

สรุป

Service Worker เป็นหนึ่งในการเปลี่ยนแปลงที่สำคัญที่สุดในไฟล์ Manifest V3 (นอกเหนือจากกฎ declarativeNetRequest) การย้ายข้อมูลไปยัง Manifest V3 อาจต้องมีการเปลี่ยนโค้ดหลายรายการในส่วนขยายเบราว์เซอร์และแนวทางใหม่ในการทดสอบ นอกจากนี้ ยังกำหนดให้นักพัฒนาส่วนขยายที่มีสถานะถาวรต้องเตรียมส่วนขยายให้รับมือกับการระงับ Service Worker ที่ไม่คาดคิดอย่างราบรื่น

ขออภัย ไม่มี API สำหรับจัดการการระงับด้วยวิธีที่ง่ายและเหมาะกับ Use Case ของเรา เนื่องจากเราต้องการทดสอบความเสถียรของโค้ดเบสของส่วนขยายกับกลไกการระงับในระยะแรก เราจึงต้องหาวิธีแก้ปัญหา นักพัฒนาส่วนขยายรายอื่นๆ ที่พบปัญหาคล้ายกันสามารถใช้วิธีแก้ปัญหานี้ได้ แม้ว่าจะใช้เวลานานในขั้นตอนการพัฒนาและการบำรุงรักษา แต่เราก็มั่นใจว่าส่วนขยายจะทํางานได้อย่างสําเร็จในสภาพแวดล้อมที่มีการระงับ Service Worker เป็นประจํา

แม้ว่าจะมีการสนับสนุนขั้นพื้นฐานสำหรับการทดสอบการระงับ Service Worker อยู่แล้ว แต่เราต้องการเห็นการรองรับแพลตฟอร์มที่ดีขึ้นสำหรับการทดสอบ Service Worker จากภายในส่วนขยายในอนาคต เนื่องจากอาจช่วยลดเวลาในการทดสอบและความพยายามในการบำรุงรักษาได้อย่างมาก