وبلاگ / راهنمای مسیر یادگیری و فناوری
راهنمای مسیر یادگیری و فناوری

Playwright چیست؟ آموزش تست End-to-End با TypeScript از نصب تا Trace

در این آموزش Playwright را برای TypeScript نصب می‌کنید، یک تست واقعی ورود می‌نویسید، Locator و Assertion پایدار می‌سازید و شکست تست را با Trace و گزارش HTML بررسی می‌کنید.

· ۴۴ بازدید

تست دستی یک مسیر خرید یا ورود شاید بار اول چند دقیقه طول بکشد؛ اما با هر تغییر رابط، مرورگر و Pull Request تکرار آن پرهزینه و مستعد فراموشی می‌شود. تعامل واقعی کاربر با برنامه وب را در مرورگر اجرا می‌کند و نتیجه را با Assertionهای قابل انتظار می‌سنجد.

در این راهنما یک تست End-to-End کوچک اما واقعی می‌سازیم: نصب پروژه ، تعریف تنظیمات پایه، نوشتن سناریوی ورود، انتخاب Elementها با Locator معنایی و تحلیل شکست با Trace و گزارش HTML. هدف صرفاً سبزشدن تست نیست؛ می‌خواهیم تستی بسازیم که قابل خواندن، قابل تکرار و در برابر تغییرهای بی‌ربط UI مقاوم باشد.

چیست و چه اجزایی دارد؟

Test یک Framework تست End-to-End برای برنامه‌های مدرن وب است. Test Runner، Assertion، Isolation، Parallel Execution، Reporter و ابزارهای Debug در یک بسته قرار دارند. تست‌ها می‌توانند روی Chromium، Firefox و WebKit در ویندوز، لینوکس و macOS اجرا شوند.

هر تست یک Browser Context جدا می‌گیرد؛ این Context مانند Profile تازه مرورگر است. Cookie و Storage تست قبلی به تست بعدی نشت نمی‌کند، مگر اینکه آگاهانه State احراز هویت را ذخیره و استفاده کنید. این Isolation پایه مهمی برای جلوگیری از تست‌های وابسته به ترتیب اجراست.

چه چیزی را با تست E2E بسنجیم؟

  • مسیرهای حیاتی مانند ورود، ثبت سفارش، پرداخت آزمایشی و بازیابی حساب
  • قرارداد میان Frontend، Backend و Browser در یک سناریوی کامل
  • رفتار برنامه در Chromium، Firefox و WebKit
  • دسترسی‌پذیری پایه Elementهای تعاملی و نام‌های قابل فهم

تست E2E جای Unit Test و Integration Test را نمی‌گیرد. تعداد محدودی مسیر حیاتی را با E2E پوشش دهید و منطق ریز را در لایه‌های سریع‌تر آزمایش کنید.

vs Selenium و Cypress؛ تفاوت‌ها و انتخاب ابزار

معیارSeleniumCypress
مرورگرهاChromium، Firefox و WebKitاکوسیستم گسترده WebDriverمرورگرهای پشتیبانی‌شده پروژه
Auto-waitدر Locator و Assertion داخلیوابسته به API و طراحی تستRetry داخلی فرمان‌ها
IsolationBrowser Context برای هر تستبه طراحی Framework وابسته استIsolation داخلی Runner
TraceSnapshot، Network و گام‌های تستنیازمند ابزار و Integration جداRunner و Artifactهای اختصاصی
انتخاب مناسبپروژه مدرن با Tooling یکپارچهاکوسیستم قدیمی یا زبان‌های متعددتیم Frontend با Workflow آن ابزار

انتخاب فقط با جدول Feature انجام نمی‌شود. مهارت تیم، Browserهای هدف، محیط CI، نیاز به زبان برنامه‌نویسی دیگر و هزینه نگهداری تست‌ها را بسنجید. برای پروژه تازه ، مسیر شروع یکپارچه‌ای ارائه می‌دهد.

نصب در پروژه

یک پوشه خالی بسازید و Installer رسمی را اجرا کنید. Wizard درباره یا JavaScript، پوشه تست‌ها، Workflow مربوط به و نصب Browserها سؤال می‌کند. و نصب Browserها را انتخاب کنید.

setup-.shBash
mkdir web-e2ecd web-e2enpm init playwright@latestnpx playwright --versionnpx playwright testnpx playwright show-report
UTF-8Bash

علاوه بر Package، Binary مرورگرهای سازگار را دریافت می‌کند. در CI لینوکس از npx playwright install --with-deps استفاده می‌شود تا Browser و وابستگی‌های سیستم نصب شوند. Version فایل Lock را Commit کنید تا Runner تیم نسخه یکسانی بگیرد.

تنظیم baseURL، Browserها و Trace

فایل تنظیمات مرکز تصمیم‌های مشترک است. URL پایه را از متغیر محیطی بخوانید و برای اجرای محلی مقدار امن پیش‌فرض بگذارید. Trace را روی نخستین Retry فعال کنید تا اجرای عادی Artifact سنگین نسازد، ولی شکست قابل بازسازی باشد.

import { defineConfig, devices } from '@playwright/test'; export default defineConfig({  testDir: './tests',  fullyParallel: true,  forbidOnly: Boolean(process.env.CI),  retries: process.env.CI ? 2 : 0,  reporter: 'html',  use: {    baseURL: process.env.BASE_URL ?? 'http://127.0.0.1:3000',    trace: 'on-first-retry',    screenshot: 'only-on-failure',  },  projects: [    { name: 'chromium', use: { ...devices['Desktop Chrome'] } },    { name: 'firefox', use: { ...devices['Desktop Firefox'] } },  ],});

قرار دادن URL، نام کاربری یا Token محرمانه در Repository ممنوع است. آدرس محیط و Secretها را در CI از متغیر امن تزریق کنید. Artifact تست نیز ممکن است Screenshot، DOM و داده فرم را در خود داشته باشد؛ دسترسی و زمان نگهداری آن را محدود کنید.

نوشتن نخستین تست ورود

فرض کنید برنامه صفحه ورود با Labelهای «ایمیل» و «رمز عبور» و Button با نام «ورود» دارد. تست باید رفتاری را توصیف کند که کاربر می‌بیند، نه جزئیات پیاده‌سازی CSS را.

login.spec.ts
import { test, expect } from '@playwright/test'; test('کاربر معتبر وارد داشبورد می‌شود', async ({ page }) => {  await page.goto('/login');  await page.getByLabel('ایمیل').fill('student@example.test');  await page.getByLabel('رمز عبور').fill('local-test-password');  await page.getByRole('button', { name: 'ورود' }).click();   await expect(page).toHaveURL(//dashboard$/);  await expect(    page.getByRole('heading', { name: 'داشبورد' })  ).toBeVisible();});

Credential بالا فقط برای Fixture محلی و حساب آزمایشی است. برای Staging از Secret Store استفاده کنید و هرگز حساب Production واقعی را در تست عمومی قرار ندهید. بهتر است داده تست در هر اجرا ساخته و پاک‌سازی منطقی شود تا تست به وضعیت قبلی وابسته نباشد.

Locator پایدار چگونه انتخاب می‌شود؟

Locator قلب Auto-wait و Retry در است. اولویت معمول، انتخاب بر اساس نقشی است که کاربر یا فناوری کمکی می‌بیند: getByRole، سپس Label، Text و در نهایت Test ID. Selectorهای طولانی CSS یا وابسته به ترتیب DOM با کوچک‌ترین تغییر طراحی می‌شکنند.

Locatorزمان استفادهپایداری
getByRoleButton، Link، Heading و کنترل معناییزیاد و همسو با Accessibility
getByLabelورودی فرم دارای Label درستزیاد
getByTextمحتوای قابل مشاهده و نسبتاً یکتامتوسط
getByTestIdوقتی قرارداد تست مستقل لازم استزیاد، ولی مخصوص تست
CSS/XPathآخرین راه برای ساختار فاقد معنامعمولاً کم

اگر getByRole Element را پیدا نمی‌کند، ممکن است HTML از نظر دسترسی‌پذیری مشکل داشته باشد. اصلاح Markup معمولاً هم تجربه کاربر و هم تست را بهتر می‌کند. برای یکتایی Locator از گزینه name و Scope کردن در بخش مشخص استفاده کنید.

چرا Timeout ثابت ضدالگو است؟

دستورهای انتظار ثابت مانند چند ثانیه Sleep تست را هم کند و هم شکننده می‌کنند. پیش از Action شرایط Actionability را بررسی می‌کند و Web-First Assertion تا رسیدن وضعیت مورد انتظار Retry می‌شود. به‌جای صبر کور، همان نتیجه‌ای را Assert کنید که اهمیت دارد.

اجرای تست، UI Mode و Codegen

test-commands.shBash
npx playwright testnpx playwright test tests/login.spec.ts --project=chromiumnpx playwright test --headednpx playwright test --uinpx playwright codegen http://127.0.0.1:3000/loginnpx playwright show-report
UTF-8Bash

Codegen نقطه شروع Locator و Action را سریع می‌کند، ولی خروجی آن را بدون بازبینی Commit نکنید. نام تست، داده مستقل، Assertion معنادار و حذف Stepهای زائد همچنان به قضاوت مهندس نیاز دارند. UI Mode برای مشاهده گام‌ها و Debug محلی مناسب است؛ اجرای CI معمولاً Headless باقی می‌ماند.

تحلیل شکست با Trace Viewer

Trace می‌تواند Timeline، Actionها، DOM Snapshot، Console، Network و Attachmentها را کنار هم نشان دهد. وقتی تست فقط در CI شکست می‌خورد، Trace بسیار ارزشمندتر از یک Screenshot نهایی است، چون وضعیت قبل و بعد هر گام را نمایش می‌دهد.

trace-debug.shBash
npx playwright test tests/login.spec.ts --trace onnpx playwright show-trace test-results/login-user-valid/trace.zipnpx playwright show-report
UTF-8Bash

نام پوشه Result به نام تست و پروژه بستگی دارد. Trace ممکن است داده صفحه، Headerها یا ورودی‌ها را ثبت کند؛ آن را Artifact حساس فرض کنید. Upload عمومی، نگهداری نامحدود و بازکردن Trace ناشناس روی سرویس بیرونی انتخاب مناسبی نیست.

اجرای در

Workflow زیر Dependencyها را از Lock File نصب می‌کند، Browserها و وابستگی سیستم را می‌گیرد، تست‌ها را اجرا می‌کند و فقط در شکست Report را برای مدت محدود نگه می‌دارد. برنامه مورد آزمون باید پیش از Step تست در دسترس باشد؛ می‌توانید آن را با تنظیم webServer در Config یا Step جدا اجرا کنید.

.ymlYAML
name: Playwright testson: [push, pull_request]jobs:  test:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4      - uses: actions/setup-node@v4        with:          node-version: 24          cache: npm      - run: npm ci      - run: npx playwright install --with-deps      - run: npm test      - uses: actions/upload-artifact@v4        if: failure()        with:          name: playwright-report          path: playwright-report/          retention-days: 7
UTF-8YAML

Actionها را در محیط حساس بر اساس سیاست Supply Chain سازمان به Commit SHA Pin کنید. Secret مربوط به محیط تست را فقط در Job مورد نیاز تزریق کنید و Workflow مربوط به Pull Requestهای Fork ناشناس را طوری طراحی کنید که Secret دریافت نکند.

خطاهای رایج و راه اصلاح

نشانهعلت رایجراه اصلاح
Timeout هنگام ClickLocator اشتباه یا Element غیرقابل ActionTrace، نام Accessible و Overlay را بررسی کنید
Strict mode violationLocator چند Element پیدا کرده استRole و Name یا Scope دقیق‌تر بدهید
فقط در CI شکستRace، داده مشترک یا تفاوت محیطTrace و Report را ببینید و Fixture را مستقل کنید
Browser executable missingBinary مرورگر نصب نشده استفرمان install --with-deps را اجرا کنید
تست گاهی سبز و قرمزSleep ثابت یا Assertion فوریWeb-First Assertion و انتظار نتیجه‌محور بنویسید
تست‌ها روی هم اثر دارندداده یا State مشترکداده یکتا و Browser Context مستقل استفاده کنید

چک‌لیست تست E2E قابل اعتماد

  1. سناریو یک رفتار مهم کاربر را با نام روشن توصیف می‌کند.
  2. تست به ترتیب اجرای تست دیگر وابسته نیست.
  3. Locatorها بر Role، Label یا قرارداد Test ID استوارند.
  4. انتظار ثابت با Assertion نتیجه‌محور جایگزین شده است.
  5. داده تست یکتا و قابل پاک‌سازی است.
  6. Retry برای پنهان‌کردن Flaky Test استفاده نمی‌شود.
  7. Trace و Screenshot فقط هنگام نیاز و با Retention محدود ذخیره می‌شوند.
  8. همان دستور CI روی محیط توسعه نیز قابل اجراست.

برای قرار دادن تست‌ها در چرخه تحویل، شناخت Pipeline اهمیت دارد. راهنمای CI/CD با GitHub Actions مسیر مکملی است. اگر برنامه روی کلاستر اجرا می‌شود، آموزش Kubernetes و Minikube به درک محیط تست و انتشار کمک می‌کند.

سوالات متداول

چیست؟

ابزار تست End-to-End برای برنامه‌های وب است و اجرای تست روی Chromium، Firefox و WebKit، Assertion، Trace و ابزارهای اشکال‌زدایی را در یک workflow فراهم می‌کند.

تفاوت و Selenium چیست؟

هر دو برای خودکارسازی مرورگر استفاده می‌شوند. امکاناتی مانند auto-waiting، context isolation و Trace را به‌صورت یکپارچه ارائه می‌کند؛ Selenium اکوسیستم قدیمی‌تر و گسترده‌ای برای WebDriver و زبان‌های مختلف دارد.

برای Locator پایدار در چه روشی بهتر است؟

Locatorهایی که بر نقش، label و رفتار قابل مشاهده کاربر تکیه می‌کنند معمولاً از selectorهای وابسته به ساختار CSS پایدارترند.

Trace در چه کاربردی دارد؟

Trace اطلاعات اجرای تست را برای بررسی مرحله‌به‌مرحله شکست‌ها ذخیره می‌کند و در تشخیص خطاهای timing، navigation و تعامل با عناصر مفید است.

مسیر یادگیری مرتبط با تست Front-End

برای تقویت پایه‌های این مسیر، JavaScript و React را ببینید. برای اجرای تست‌ها در محیط‌های قابل تکرار نیز راهنمای Docker برای توسعه‌دهندگان و Kubernetes و Minikube مرتبط هستند.

جمع‌بندی

بیش از یک ابزار Click خودکار است: Locatorهای قابل Retry، Assertionهای Web-First، Isolation، اجرای چندمرورگری و Trace کنار هم چرخه ساخت و عیب‌یابی تست را کامل می‌کنند. کیفیت نهایی همچنان به طراحی سناریو، داده مستقل و انتخاب Locator درست وابسته است.

همین امروز یک مسیر حیاتی برنامه را با Locator معنایی تست کن، یک شکست کنترل‌شده بساز و علت آن را در Trace Viewer پیدا کن.

منابع رسمی