تست WebGL و WebGPU بدون کروم
خلاصهٔ کاملتر
نویسنده میگه تست کد گرافیکی همیشه دردسر بوده. اگه کدت به WebGL یا WebGPU دست میزنه، راه معمول اینه که یه کروم headless با Puppeteer یا Playwright بالا بیاری، صفحه رو لود کنی، رندر بگیری و اسکرینشات رو برگردونی به تسترانر. کار میکنه، ولی کنده، نصبش تو CI سنگینه و تستهای رندر رو از جریان عادی یونیتتست بقیهٔ تیم جدا میکنه. راه دوم هم mock بوده که اصلاً چیزی رندر نمیکنه و بهت نمیگه شیدرت کامپایل میشه یا نه.
جوابی که نویسنده ساخته دو مجموعه محیط تسته: vitest-gpu و jest-gpu. کافیه تو کانفیگ، environment رو بذاری روی webgpu-node یا webgl-node؛ بعدش document.createElement('canvas').getContext('webgl2') و navigator.gpu.requestAdapter() همونطور که انتظار داری کار میکنن و Three.js، Babylon.js و کد خام WebGL و WebGPU بدون هیچ تغییری اجرا میشن.
نکتهای که به گفتهٔ نویسنده مهمه: این شبیهسازی یا پیادهسازی دوباره نیست. WebGL روی ANGLE سوار میشه و WebGPU روی Dawn، یعنی دقیقاً همون موتورهایی که خود کروم استفاده میکنه. پس تستت با همون کامپایلر شیدر و همون بکاند GPU کار میکنه که مرورگر کاربرت، بدون اینکه هزینهٔ بالا آوردن بقیهٔ مرورگر رو بدی.
سمت Vitest یه matcher به اسم toMatchScreenshot هم هست که خروجی رندر رو با یه baseline تصویری مقایسه میکنه:
const canvas = createCanvas(256, 256);
const renderer = new THREE.WebGPURenderer({ canvas: canvas.asElement() });
await renderer.init();
await renderer.renderAsync(scene, camera);
await expect(canvas).toMatchScreenshot('cube.png');اولین اجرای محلی فایل screenshots/cube.png رو کنار تست میسازه؛ کامیتش میکنی و اجراهای بعدی باهاش diff میگیرن. baseline گمشده تو CI تست رو fail میکنه و با vitest -u آپدیت میشه. وقتی مقایسه شکست بخوره، تصویر واقعی و تصویر diff هم کنار baseline نوشته میشن تا ببینی دقیقاً چی عوض شده.
ایدهٔ اولیه از یه PR به Three.js از Renaud Rohlinger اومده. حدود سهچهارم مثالهای Three.js حالا مستقیم تو Node رندر میشن و فقط اونهایی که واقعاً مرورگر لازم دارن (چیدمان DOM، کنواس دوبعدی، پخش مدیا) سراغ کروم میرن. نتیجهاش این بود که کندترین شارد CI (یعنی سنگینترین دستهٔ تستهای موازی) از حدود ۱۵ دقیقه رسید به زیر ۶ دقیقه، یعنی تقریباً ۲.۶ برابر سریعتر.
نکات کلیدی:
- بستههای Vitest: vitest-environment-webgl-node، vitest-environment-webgpu-node و vitest-screenshot
- بستههای Jest: jest-environment-webgl-node و jest-environment-webgpu-node، هر دو با بیلد دوگانهٔ ESM و CommonJS
- سمت Jest matcher اسکرینشات نداره؛ با readPixels() پیکسلها رو میخونی و با jest-image-snapshot مقایسه میکنی
- WebGL روی ANGLE و WebGPU روی Dawn اجرا میشه، همون پیادهسازیهای داخل کروم
- کندترین شارد CI پروژهٔ Three.js از ۱۵ دقیقه به زیر ۶ دقیقه رسید




