تست اجزای وب با @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
یک دویدن… چیزی شبیه به:
همچنین می توانید آزمایش ها را با آن ترکیب کنید 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
کلاس دارای ویژگی های زیر است:
- دارای هدر پیش فرض “Hey there” و شمارنده 5 است
- شمارنده کلیک روی دکمه را افزایش می دهد
- می تواند هدر را از طریق ویژگی لغو کند
- حسابرسی a11y را ارزیابی می کند
پیشفرضها، تعامل، سفارشیسازی و دسترسی، پایهای عالی برای آزمایش اکثر رابطهای کاربری وب تشکیل میدهند، بنابراین بیایید به نحوه انجام این کار برای ما دقیقتر نگاه کنیم. <testing-components>
عنصر، و چه چیز دیگری ممکن است در این زمینه ها مفید باشد.
پیش فرض ها
همانطور که در بالا دیدیم، @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
- تست رگرسیون بصری
- و بیشتر…
اگر چشم تیزبین داشته باشید، متوجه خواهید شد که فهرست در حال حاضر طولانی تر می شود. به من کمک کنید چیزهایی را که از دست داده ام پیدا کنم. با هر مفهومی که دوست دارید در اقساط بعدی پوشش داده شود، به نظرات زیر مراجعه کنید. من نمی توانم تضمین کنم که بتوانم آنها را پوشش دهم، اما اکنون که شروع به آزمایش اجزای وب کرده اید، شاید بتوانید همه چیز را در مورد جنبه مورد علاقه خود به من آموزش دهید.