برنامه نویسی

تست اجزای وب با @web/test-runner

بنابراین، شما مؤلفه های وب را می نویسید و علاقه مندید کارهایی را که برای آزمایش واحد انجام می دهید گسترش دهید؟ خوب، شما به جای درست آمده اید. این تازه شروع است، اما تست اجزای وب: سری قرار است برای شما توضیح دهد که چگونه Open Web Components و Modern Web به شما در انجام این کار کمک می کند. ما با این شروع می کنیم که چگونه مولد Open Web Components می تواند شما را در کوتاه ترین زمان راه اندازی کند @web/test-runner درست از جعبه

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

  • قابلیت‌ها (و محدودیت‌های) تست UI از رشته JS
  • چگونه می توانید بیشتر آزمایش کنید، مانند اینکه یک کاربر جزء شما را مصرف می کند، چه با ماوس، یک صفحه کلید، یا کمی کندتر از زمان اجرای JS معمولی.
  • چه نوع دسترسی تضمین می کند که می توانید در زمان واحد آزمایش کنید
  • و بیشتر…

قبل از اینکه شروع کنیم

برای آماده سازی، اجازه دهید نگاهی به کامپوننت ارائه شده به همراه مولد Open Web Components و تست هایی که قبلا برای آن نوشته شده است بیاندازیم. برای شروع اجرا کنید npm init @open-wc@latest در ترمینال شما آگاه باش که npm init کش بسیار چسبناکی دارد. اگر قبلاً دستور را اجرا کرده اید، شامل @latest اطمینان حاصل می کند که بیشترین خروجی را دریافت می کنید. به خوبی می شود داربست پروژه جدید، که در آن یک را خواهیم ساخت جزء وب، که می خواهیم به آن اضافه کنیم آزمایش کردن، همه آنها را انجام خواهیم داد تایپ اسکریپت، و جزء ما را فراخوانی می کند testing-components. اگر به مولد اجازه می دهید این محتوا را روی دیسک بنویسد و وابستگی ها را با NPM نصب کند، خروجی ترمینال باید به شکل زیر باشد:

npm init @open-wc@latest
Need to install the following packages:
  @open-wc/create@0.38.69
Ok to proceed? (y) y

        _.,,,,,,,,,._
     .d''           ``b.       Open Web Components Recommendations
   .p'      Open       `q.
 .d'    Web Components  `b.    Start or upgrade your web component project with
 .d'                     `b.   ease. All our recommendations at your fingertips.
 ::   .................   ::
 `p.                     .q'
  `p.    open-wc.org    .q'
   `b.     @openWc     .d'
     `q..            ..,'      See more details at https://open-wc.org/init/
        '',,,,,,,,,,''


Note: you can exit any time with Ctrl+C or Esc
✔ What would you like to do today? › Scaffold a new project
✔ What would you like to scaffold? › Web Component
✔ What would you like to add? › Testing (web-test-runner)
✔ Would you like to use typescript? › Yes
✔ What is the tag name of your web component? … testing-components

./
├── testing-components/
│   ├── .vscode/
│   │   └── extensions.json
│   ├── demo/
│   │   └── index.html
│   ├── src/
│   │   ├── index.ts
│   │   ├── testing-components.ts
│   │   └── TestingComponents.ts
│   ├── test/
│   │   └── testing-components.test.ts
│   ├── .editorconfig
│   ├── .gitignore
│   ├── LICENSE
│   ├── package.json
│   ├── README.md
│   ├── tsconfig.json
│   ├── web-dev-server.config.mjs
│   └── web-test-runner.config.mjs

✔ Do you want to write this file structure to disk? › Yes
Writing..... done
✔ Do you want to install dependencies? › Yes, with npm
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

حالا اگر بدوید cd testing-components برای ورود به پروژه تولید شده و باز کردن دایرکتوری در ویرایشگر انتخابی خود، به آنچه برای شما ایجاد شده است می پردازیم.

پروژه تولید شده

اولین چیزی که متوجه خواهید شد، انتخاب هایی از مولد Open Web Components است که ما آن را قبول نکردیم. Linting (Eslint & Prettier) و Demoing (کتاب داستان). از آنجایی که آنها به طور خاص برای آزمایش مؤلفه وب ما مناسب نیستند، من آنها را از مخزن تولید شده برای این مقاله کنار گذاشته ام، اما این بدان معنا نیست که شما باید این کار را انجام دهید. چه در حال حاضر آن‌ها را بگنجانید، چه بعداً «به‌روزرسانی یک پروژه موجود» را انتخاب کنید، این چیزها به‌طور خاص مانعی نمی‌شوند، اما در دنیایی که همه چیز با سرعت 90 مایل در دقیقه اتفاق می‌افتد، می‌تواند مفید باشد. مقداری تمرکز

سپس، خواهید دید که چه کاری انجام دادیم شامل:

  • را demo دایرکتوری بسیار ساده است index.html که توسط @web/dev-server از طریق npm start اگر می‌خواهید مؤلفه وب را که با ژنراتور در حال کار موجود است، بررسی کنید
  • را dist دایرکتوری خروجی JS را از اجرا نگه می دارد tsc برخلاف منبع Typescript ما، این دستور تقریباً قبل از همه اسکریپت‌های دیگری که می‌توانید اجرا کنید گنجانده شده است، بنابراین هرگز نیازی به انجام مستقیم این کار ندارید.
  • را src دایرکتوری مؤلفه وب ما را نگه می دارد که به یک شکسته شده است index.js صادرات مجدد تعریف کلاس صادر شده از TestingComponents.ts همچنین testing-components.ts که به طور خاص همان کلاس را ثبت می کند testing-component نام عنصر سفارشی
  • را test دایرکتوری با یک فایل آزمایشی، testing-components.test.ts، که می تواند از طریق اجرا شود npm test فرمان

حالا اجازه نده جلوت رو بگیرم می دانم که می خواهید خودتان ببینید، “آیا ترکیب می شود؟”. دادن npm start یک دویدن… چیزی شبیه به:

خروجی اولیه <testing-components>  عنصر، گفتن

خروجی اولیه عنصر “ ما با گفتن “Hello owc World! Nr. 5!” با دکمه ای که می گوید “افزایش”

همچنین می توانید آزمایش ها را با آن ترکیب کنید npm test فرمان اگر همه چیز طبق برنامه پیش رفته باشد، خروجی باید به صورت زیر باشد:

npm test

> testing-components@0.0.0 test
> tsc && wtr --coverage


dist/test/testing-components.test.js:

 🚧 Browser logs:
      Lit is in dev mode. Not recommended for production! See https://lit.dev/msg/dev-mode for more information.

Chrome: |██████████████████████████████| 1/1 test files | 4 passed, 0 failed

Code coverage: 100 %
View full coverage report at coverage/lcov-report/index.html

Finished running tests in 9s, all tests passed! 🎉
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

بنابراین، ما یک کامپوننت وب بسیار کم و چهار تست با موفقیت داریم. بیایید کمی بیشتر بگردیم تا ببینیم برای مشکلمان چه چیزی به دست آورده‌ایم و واقعاً چه چیزی در اینجا به طور پیش‌فرض تحت آزمایش است.

این <testing-components> عنصر

چیز زیادی برای ما وجود ندارد <testing-component> عنصر، اما اینجا در تمام شکوه خود است:

import { html, css, LitElement } from 'lit';
import { property } from 'lit/decorators.js';

export class TestingComponents extends LitElement {
  static styles = css`
    :host {
      display: block;
      padding: 25px;
      color: var(--testing-components-text-color, #000);
    }
  `;

  @property({ type: String }) header = 'Hey there';

  @property({ type: Number }) counter = 5;

  __increment() {
    this.counter += 1;
  }

  render() {
    return html`
      <h2>${this.header} Nr. ${this.counter}!</h2>
      <button @click=${this.__increment}>increment</button>
    `;
  }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

تایپ اسکریپت تولید شده در بالا به شدت به Lit متکی است تا جزء وب شما را سریع و ساده نگه دارد. در اینجا برخی از حقایق مهم وجود دارد که باید از این کد در مورد آزمایشاتی که در ادامه بررسی خواهیم کرد حذف کنید:

  • تعریف کلاس از اهرم استفاده می کند LitElement کلاس پایه، بنابراین برای اطلاعات بیشتر در مورد اینکه وقتی می‌خواهیم قابلیت‌های جدید را در اقساط بعدی اضافه کنیم، به lit.dev مراجعه کنید.
  • را property دکوراتور برای ارتقاء چند ویژگی استفاده می شود تا هم واکنش پذیر باشند و هم به ویژگی های عنصر وابسته باشند.
  • را html الگوی تحت اللفظی از در حال اهرمی برای ارائه عملکردی از الگو است
  • را @ از sigil برای گوش دادن به رویدادهای عناصر درون قالب ما استفاده می شود

تست ها

در آزمایشات ما، یک مؤلفه وب توسط ما تعریف شده است TestingComponents کلاس دارای ویژگی های زیر است:

  1. دارای هدر پیش فرض “Hey there” و شمارنده 5 است
  2. شمارنده کلیک روی دکمه را افزایش می دهد
  3. می تواند هدر را از طریق ویژگی لغو کند
  4. حسابرسی a11y را ارزیابی می کند

پیش‌فرض‌ها، تعامل، سفارشی‌سازی و دسترسی، پایه‌ای عالی برای آزمایش اکثر رابط‌های کاربری وب تشکیل می‌دهند، بنابراین بیایید به نحوه انجام این کار برای ما دقیق‌تر نگاه کنیم. &lt;testing-components&gt; عنصر، و چه چیز دیگری ممکن است در این زمینه ها مفید باشد.

پیش فرض ها

همانطور که در بالا دیدیم، @property decorator برای ایجاد ویژگی های واکنشی در تعریف کلاس ما استفاده می شود. header در حال تزئین است type: string به این معنی که مقدار آن از صفت پذیرفته شود header مقدار به یک رشته اجباری خواهد شد. به طور مشابه، counter تزئین شده است type: number، که به معنای مقادیر اعمال شده به counter ویژگی به یک عدد اجباری خواهد شد. تعداد انگشت شماری از این تبدیل‌ها توسط Lit خارج از جعبه انجام می‌شوند، اما اگر چیز پیچیده‌تری در ذهن دارید، با مبدل‌های سفارشی برای حل این موارد استفاده آشنا شوید.

اعداد و رشته ها بسیار دقیق هستند، آزمایش زیر تأیید می کند که این مقادیر در واقع به عنصر سفارشی زمانی که به DOM متصل می شوند اعمال می شوند:

it('has a default header "Hey there" and counter 5', async () => {
  const el = await fixture<TestingComponents>(html`<testing-components></testing-components>`);

  expect(el.header).to.equal('Hey there');
  expect(el.counter).to.equal(5);
});
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

آزمایش اینکه یک ویژگی به طور پیش‌فرض با مقدار پیش‌فرض آن برابر است، ممکن است کمی زائد به نظر برسد، اما قبل از اینکه به هر چیز دیگری بپردازید، خط پایه مؤلفه وب شما را تضمین می‌کند. آزمایش اینکه یک ویژگی برابر با یک دارایی است نیز ممکن است کمی سخت به نظر برسد، در واقع چیزی را در مورد ملک آزمایش نمی کند و ممکن است حق با شما باشد. بسته به این که چنین خاصیتی در یک بیشتر چه می کند کامل مؤلفه وب، ممکن است تأیید شود که آن ویژگی ها به طور مناسب در یک عکس فوری DOM یا در یک آزمایش رگرسیون بصری ظاهر می شوند مفید باشد. در بخش‌های آینده به این تکنیک‌ها و موارد دیگر خواهیم پرداخت.

تعامل

هنگام آزمایش رابط کاربری وب، مهم است که ورودی های آزمایشی خود را به عنوان یک بازدیدکننده آینده در تعامل با مؤلفه وب یا یک ساختمان توسعه دهنده آینده با مؤلفه وب خود در نظر بگیرید. یک بازدید کننده می تواند به روش های مختلفی با کد شما تعامل داشته باشد، از جمله ماوس و صفحه کلید و @web/test-runner راه‌های قدرتمندی برای تقلید از آن تعاملات ارائه می‌دهد که بعداً بررسی خواهیم کرد. این تست تولید شده به عنوان یک ساختمان توسعه دهنده با مؤلفه وب شما عمل می کند. با استفاده از این واقعیت که @web/test-runner در رشته JS یک مرورگر واقعی برای استفاده از APIهای عنصری مانند وجود دارد querySelector() و click() در کد آزمون شما:

it('increases the counter on button click', async () => {
  const el = await fixture<TestingComponents>(html`<testing-components></testing-components>`);
  el.shadowRoot!.querySelector('button')!.click();

  expect(el.counter).to.equal(6);
});
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اگر تعجب می کنید که چرا شخصی که با مؤلفه وب شما ساخته می شود ممکن است به عنصر شما و به صورت دستی دسترسی پیدا کند click() چیزی در عنصر شما، احتمالا شما تنها نیستید. با این حال، در زمان آزمایش، انجام این کار گاهی اوقات می تواند تنها راه برای شروع تعاملات از زمینه JS باشد. در موارد دیگر، این می تواند نشانه واضحی باشد که API عنصر شما به طور کامل الزامات رابط عمومی خود را در نظر نگرفته است.

آیا کلیک کردن روی این دکمه کاری است که یک برنامه مصرف کننده باید بتواند بدون دخالت انسان انجام دهد؟ پاسخ ممکن است “خیر” باشد، همانطور که در کد تولید شده وجود دارد، اما، اگر پاسخ “بله” است، ممکن است بخواهید عنصر خود را تغییر دهید تا از دسترسی توسعه دهندگان مصرف کننده به مؤلفه وب شما به این روش جلوگیری کنید. درک تکنیک های مختلف آزمایش یک مؤلفه وب می تواند به آشکار شدن این سؤالات و پاسخ آنها قبل از ارسال کد شما به مصرف کنندگان کمک کند.

سفارشی سازی

با استفاده از property decorator در تعریف کلاس خود، ما نه تنها آن خصوصیات را به‌عنوان واکنش‌پذیر ارتقاء دادیم، بلکه آن ویژگی‌ها را به ویژگی‌های عنصر سفارشی خود نیز متصل کردیم. به این ترتیب، هر دو header و counter می توان مقادیر جدیدی را از طریق ویژگی هایی با همان نام ارائه کرد. تست زیر تضمین می کند که این رابطه برای header ویژگی/ویژگی:

it('can override the header via attribute', async () => {
  const el = await fixture<TestingComponents>(
    html`<testing-components header="attribute header"></testing-components>`,
  );

  expect(el.header).to.equal('attribute header');
});
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اگر شما یکی از افرادی هستید که «کامل» هستند، همین کار را می‌توان برای آن انجام داد counter همچنین. این تست به طور خاص از اهرم html قالب تحت اللفظی برای ایجاد یک نمونه از <testing-components> عنصر و مقدار را اعمال می کند attribute header به عنوان یک ویژگی برای آن عنصر. شما می توانید به طور مشابه با استفاده از مرجع عنصر موجود در آن، آن ویژگی را به صورت دستی اعمال کنید el متغیر؛ این همان عملیات ضروری خواهد بود el.setAttribute('header', 'attribute header');، اگر یکی از “کامل” بودن بودی…

دسترسی (a11y)

پروژه Open Web Components نه تنها تولید کننده ای را ارائه می دهد که ما مؤلفه وب خود را بر اساس آن در این گفتگو قرار می دهیم، بلکه آنها Chai A11y ax را نیز می فروشند که متصل می شود. axe-core با ادعای چای برای مصرف آسان در @web/test-runner محیط. این بدان معنی است که می توانید از موتور تست دسترسی استاندارد صنعتی برای تأیید دسترسی به مؤلفه وب خود در زمان آزمون واحد استفاده کنید. این به شکل زیر است:

it('passes the a11y audit', async () => {
  const el = await fixture<TestingComponents>(html`<testing-components></testing-components>`);

  await expect(el).shadowDom.to.be.accessible();
});
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

یادداشت مهم: expect().to.be.accessible() یک دستور ناهمزمان است. اگر شما نمی await با این انتظار، در نتایج آزمایش خود، مثبت کاذب دریافت خواهید کرد.

اما، هنگامی که شما انجام دهید await اطمینان از دسترسی به عکس فوری عنصر سفارشی شما به همین سادگی است. من “عکس فوری” را در اینجا دیدم .accessible() در مورد مؤلفه وب شما به جز وضعیتی که از آن تماس گرفته اید چیزی نمی داند. این بدان معناست که اگر تعاملات بیشتر با عنصر مدل دسترس‌پذیری را تغییر دهد، باید مطمئن شوید که یک آزمایش یا آزمایش‌هایی اضافه کنید که مؤلفه وب شما را به آن حالت می‌برد و دسترسی آن را در آن زمینه تأیید می‌کند. در مقاله‌های آینده، به معنای آن و همچنین تفاوت بین مؤلفه‌ای که دارای درخت قابل دسترس از گره‌های DOM است و به طور خاص یک درخت دسترسی منحصر به فرد را به فناوری کمکی ارائه می‌کند، نگاهی دقیق خواهیم داشت.

چه داریم؟

در حال حاضر شما به خوبی تست شده است <testing-components> عنصری که ویژگی های a header و counter ویژگی که دکمه ای را به مصرف کنندگان شما می دهد که به آنها اجازه می دهد شمارنده را افزایش دهند. چه چیزی بیشتر می توانید بخواهید؟

اوه… خیلی؟

به نظر منصفانه است. در مؤلفه‌ای که ما تولید کرده‌ایم چیزهای زیادی وجود ندارد، که خوب است، زیرا به این معنی است که اگر واقعاً یک پروژه جدید با الزامات واقعی را شروع می‌کردید، برای شروع تمرکز روی آن‌ها چیز زیادی برای برداشتن وجود نداشت. وقتی در آینده با هم برگردیم، از همان جایی که کار را متوقف کرده‌ایم شروع می‌کنیم و عمیق‌تر به آزمایش اجزای وب در مرورگر با @web/test-runner. امیدواریم که شما حداقل در مورد اینکه چگونه همه چیز در این زمینه کنار هم قرار می‌گیرند، درک دقیقی داشته باشید و هیجان زده باشید که برای سواری همراه شوید.

بعدش چی…

اکنون ما می دانیم که چگونه می توانیم با یک پروژه کامپوننت وب جدید با استفاده از مولد Open Web Components شروع کنیم و اصول اولیه آزمایش پیش فرض ها، تعامل، سفارشی سازی و دسترسی به آن عنصر را درک کنیم. @web/test-runner، اما در داستان طولانی توسعه و آزمایش رابط کاربری، ما تازه شروع کرده ایم. در طول مکالمات آینده، موضوعات مهمتری برای آزمایش اجزای وب را بررسی خواهیم کرد، مانند:

  • قابلیت‌ها (و محدودیت‌های) تست UI از رشته JS
  • چگونه می توانید بیشتر آزمایش کنید، مانند اینکه یک کاربر جزء شما را مصرف می کند، چه با ماوس، یک صفحه کلید، یا کمی کندتر از زمان اجرای JS معمولی.
  • چه نوع دسترسی تضمین می کند که می توانید در زمان واحد آزمایش کنید
  • تست با عکس های فوری DOM
  • تست رگرسیون بصری
  • و بیشتر…

اگر چشم تیزبین داشته باشید، متوجه خواهید شد که فهرست در حال حاضر طولانی تر می شود. به من کمک کنید چیزهایی را که از دست داده ام پیدا کنم. با هر مفهومی که دوست دارید در اقساط بعدی پوشش داده شود، به نظرات زیر مراجعه کنید. من نمی توانم تضمین کنم که بتوانم آنها را پوشش دهم، اما اکنون که شروع به آزمایش اجزای وب کرده اید، شاید بتوانید همه چیز را در مورد جنبه مورد علاقه خود به من آموزش دهید.

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا