برای CI در App Router اغلب Playwright؛ Cypress را اگر تیم داخل رانر زندگی میکند نگه دار
برای محصول Next.js با App Router، انتخاب E2E بین Playwright و Cypress مسابقه لوگو نیست. سؤال این است که پایپلاین PR منتظر اجرای سریال میماند یا نه، و ورود کاربر از دامنه تو خارج میشود یا نه. هر دو در راهنماهای تست Next.js جدی گرفته شدهاند. رأی مفید هزینه CI و شکل احراز هویت است.
اگر ورود با Clerk یا Auth0 یا OAuth مربوط به NextAuth از مبدأ تو خارج میشود، اگر میخواهی مجموعه را بدون محصول پولی روی چند job در GitHub Actions پخش کنی، یا اگر پوشش WebKit مهم است، Playwright Test را برای E2E در CI جلو بینداز. اگر اپ عملاً تکمبدأ است، تستهای سبز Cypress داری، و تیم با رانر تعاملی و حرکت در زمان خرابی را پیدا میکند، همان را نگه دار. بازنویسی یک مجموعه سالم برای تعویض برند، فصل را میسوزاند و پوشش را همانجا نگه میدارد.
هر کدام در ریپوی App Router چه چیزی را مالکاند
Playwright مرورگر را از بیرون صفحه میراند: Chromium، Firefox، و WebKit. مثال `with-playwright` در اکوسیستم Next.js هست و توصیه عملی این است که بیلد پروداکشن را تمرین کنی، یعنی `next build` و بعد `next start`، تا Server Component و Route Handler و middleware شبیه محیط واقعی باشند نه فقط حالت dev. در `playwright.config.ts` بلوک `webServer` میتواند همان سرور را در CI بالا بیاورد و منتظر `http://localhost:3000` بماند. worker موازی و `--shard` جزو CLI متنباز است. با ماشینی مقیاس میگیری که از قبل هزینهاش را میدهی.
Cypress برای E2E داخل مرورگر اجرا میشود و Component Testing هم دارد، با پیکربندی `devServer` برای Next.js. مسیر `with-cypress` و ترکیب `cypress run` با ابزاری مثل `start-server-and-test` برای CI شناختهشده است. دیباگ تعاملیاش هنوز برای خیلی تیمها بهترین حس «ببین کجا شکست» است. نکته رسمی را جدی بگیر: Component Testing در Cypress مسیر `async` Server Component را پوشش نمیدهد. آن مسیرها را با E2E بسنج، نه با mount کامپوننت کلاینت.
هیچکدام جایگزین Vitest یا Jest نیستند. منطق خالص و کامپوننت کلاینتِ تنها مال لایه واحد است. E2E مال ناوبری، کوکی، ریدایرکت middleware، و این سؤال است که باندل پروداکشن این مسیر را واقعاً نشان میدهد یا نه.
Playwright را وقتی قید، CI و احراز است
ورود از دامنه خارج میشود، چند تب یا چند مبدأ عادی است. مجموعه از حدود چند ده مشخصه گذشته و زمان دیوارساعتی CI بودجه است. شارد داخلی جلوی این را میگیرد که موازیسازی را فقط با پلن ابری بخری. WebKit را در همان پیکربندی میخواهی، نه با افزونه آزمایشی. از تست به Route Handler یا seed داده با fixture درخواست هم ضربه میزنی، کنار قدمهای UI. در GitHub Actions نصب مرورگر با وابستگی سیستم و آپلود گزارش HTML بهصورت artifact بخشی از کار است، نه ایده بعدی.
الگوی کمخطر را مکانیکی نگه دار. وقتی `CI` روشن است، `webServer` بیلد و start را اجرا کند. `reuseExistingServer` در CI خاموش بماند تا تست به سرور کهنه محلی نچسبد. retry در CI کم و محدود، محلی صفر. trace را روی تلاش مجدد بگیر نه روی هر اجرای سبز. محلی میتوانی `next dev` را برای حلقه سریع نگه داری، به شرطی که قبل از اطمینان انتشار حداقل یک بار مسیر بحرانی را روی start پروداکشن دیده باشی.
راهنمای CI خود Playwright هم محافظهکاری در تعداد worker روی رانر کوچک را جدی میگیرد. وقتی یک job کم آمد، شارد کن نه اینکه روی همان ماشین بینهایت موازی کنی و تستها را ناپایدار.
هزینه: دانلود مرورگر و وابستگی سیستم روی agent سرد چند دقیقه میگیرد مگر اینکه تصویر Docker مناسب Playwright را کش کرده باشی. تیمی که به API مبتنی بر locator عادت ندارد، تا وقتی Trace Viewer را یاد بگیرد دلش برای رانر تعاملی Cypress تنگ میشود. این دوره یادگیری را در برآورد بیاور.
Cypress را وقتی حلقه بازخورد تیم خود رانر است
محصول تکمبدأ است. ورود با کوکی نشست یا فرم داخل خود اپ است، بدون ریدایرکت ثالث. مهندسها روزشان را در `cypress open` میگذرانند. Component Testing برای کامپوننت کلاینت عادت روزانه است و قبول داری Server Component را جای دیگری با E2E بپوشانی. یا از قبل برای موازیسازی ابری هزینه میکنی، یا مجموعه آنقدر کوچک است که دقیقه CI گلوگاه نیست.
این حالت شکست را دستکم نگیر: اصرار که یک مجموعه چندصدتایی را بدون هزینه موازیسازی، ارزان و سریع مثل شارد متنباز پخش کنی. Cypress برای «شکست را زنده ببین» قوی است. برای «چهارصد فایل را روی PR هر بار سریال نگردان» باید نقشه ظرفیت داشته باشی، چه با تقسیم مشخصه چه با سرویس ابری. اگر این نقشه را نداری، سبز محلی و قرمز صف CI تناقض عجیبی نیست.
محدودیت مبدأ قدیمی را با شعار دور نزن. اگر محصول فردا OAuth چند دامنه اضافه کرد، همان روز تست ورود Cypress ممکن است از فرض تکمبدأ بشکند در حالی که کنترل مرورگر بیرون از صفحه در Playwright همان جریان را عادی میبیند. آن وقت مهاجرت هدفمند همان مسیر ورود عاقلانهتر از تعصب به ابزار فعلی است.
چه چیزی را در هر دو یکی نگه دار
داده را seed کن. به سرویس زنده بیرون در هر PR تکیه نکن. انتخابگر را به نقش و نام قابل دسترس بده. `sleep` ثابت ننویس. تست ناپایدار را یا درست کن یا از مسیر بحرانی خارج کن. و E2E را برای هر تابع خالص اضافه نکن چون «آنجا واقعیتر است». واقعیتر است و گرانتر. گرانی باید حق مسیر کاربر را داده باشد.
گزارش شکست باید به درد کسی بخورد که PR را باز کرده، نه فقط به درد کسی که محلی همان رانر را دارد. trace، ویدیو، یا اسکرین در artifact، وگرنه CI فقط چراغ قرمز است.
پرسشهای کوتاه
میشود هر دو را داشت؟ میشود و اغلب شلوغی است. اگر مرز روشن باشد، مثلاً E2E پروداکشن با Playwright و چند تست کامپوننت قدیمی در Cypress، قابل دفاع است. دو مجموعه E2E برای همان مسیرها را نگه ندار.
حتماً باید WebKit را در هر PR روشن کنم؟ فقط اگر کاربر Safari برایت واقعی است. پوشش اضافه بدون کاربر، دقیقه CI است که از هرس تستهای تکراری بهتر خرج نمیشود.
dev را در CI تست کنم یا start را؟ حلقه محلی dev. اطمینانی که به درد انتشار بخورد، نزدیک بیلد پروداکشن. این دو را یکی ندان.