پیکاسو: تست کتابخانه مؤلفه آسان شد


اخیراً نسخه جدیدی از سیستم طراحی Toptal منتشر شده است که ما نیاز به ایجاد تغییراتی در تقریباً هر مؤلفه در آن داریم پیکاسو، کتابخانه مؤلفه داخلی ما. تیم ما با یک چالش مواجه شد: چگونه اطمینان حاصل کنیم که رگرسیون اتفاق نمی افتد؟

پاسخ کوتاه، به طور غیرقابل تعجب، تست است. تست های زیادی.

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

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

هرم تست

ما به خودی خود هرم آزمایشی تعریف نشده‌ایم، اما اگر انجام می‌دادیم به این شکل می‌شد:

آزمایش تصویر هرم

هرم تست Toptal آزمایش هایی را که ما بر آن تاکید می کنیم را نشان می دهد.

تست های واحد

تست های واحد برای نوشتن ساده و آسان هستند. اگر زمان بسیار کمی برای نوشتن تست دارید، آنها باید اولین انتخاب شما باشند.

با این حال، آنها کامل نیستند. صرف نظر از اینکه کدام کتابخانه آزمایشی را انتخاب می کنید (کتابخانه تست Jest و React [RTL] در مورد ما)، DOM واقعی نخواهد داشت و به شما اجازه نمی دهد عملکرد را در مرورگرهای مختلف بررسی کنید، اما به شما امکان می دهد پیچیدگی را از بین ببرید و بلوک های ساختمان ساده کتابخانه خود را آزمایش کنید.

تست‌های واحد نه تنها با آزمایش رفتار کد، بلکه با بررسی تست‌پذیری کلی کد، ارزش اضافه می‌کنند. اگر نمی توانید تست های واحد را به راحتی بنویسید، به احتمال زیاد کد بدی دارید.

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

حتی اگر 100٪ پوشش تست واحد داشته باشید، این بدان معنا نیست که اجزا در دستگاه ها و مرورگرها خوب به نظر می رسند.

تشخیص رگرسیون های بصری به ویژه با آزمایش دستی دشوار است. به عنوان مثال، اگر برچسب یک دکمه 1 پیکسل جابجا شود، آیا یک مهندس QA متوجه می شود؟ خوشبختانه راه حل های زیادی برای این مشکل دید محدود وجود دارد. شما می توانید راه حل های همه کاره درجه یک سازمانی مانند لامبدا تست یا مابل. می توانید افزونه هایی مانند پرسی، به تست های موجود شما و همچنین راه حل های DIY از امثال لوکی یا کتاب داستان (این همان چیزی است که ما قبل از پیکاسو استفاده می کردیم). همه آنها معایبی دارند: برخی از آنها بسیار گران هستند در حالی که برخی دیگر منحنی یادگیری تند دارند یا نیاز به تعمیر و نگهداری بیش از حد دارند.

اسید برای نجات! این یک رقیب مستقیم برای Percy است، اما بسیار ارزان‌تر است، از مرورگرهای بیشتری پشتیبانی می‌کند و استفاده از آن آسان‌تر است. یک نقطه فروش بزرگ دیگر؟ از ادغام Cypress پشتیبانی می کند، که مهم بود زیرا می خواستیم از Storybook برای آزمایش بصری استفاده نکنیم. ما خود را در موقعیت‌هایی دیدیم که مجبور بودیم داستان‌هایی ایجاد کنیم تا بتوانیم پوشش آزمایشی بصری را تضمین کنیم، نه به این دلیل که نیاز به مستندسازی آن مورد استفاده داشتیم. که اسناد ما را آلوده کرد و درک آنها را دشوارتر کرد. ما می خواستیم آزمایش بصری را از مستندات بصری جدا کنیم.

تست های یکپارچه سازی

حتی اگر دو جزء دارای تست واحد و بصری باشند، این تضمینی نیست که با هم کار کنند. به عنوان مثال، ما باگی را پیدا کردیم که در آن یک راهنمای ابزار هنگام استفاده در یک آیتم کشویی باز نمی‌شود، اما در صورت استفاده به تنهایی به خوبی کار می‌کند.

برای اطمینان از ادغام قطعات به خوبی، از آزمایش Cypress استفاده کردیم ویژگی تست کامپوننت. در ابتدا از آن ناراضی بودیم عملکرد ضعیف، اما ما توانستیم آن را بهبود بخشیم یک پیکربندی بسته وب سفارشی. نتیجه؟ ما توانستیم از API عالی Cypress برای نوشتن تست های عملکردی استفاده کنیم که اطمینان حاصل شود که اجزای ما به خوبی با هم کار می کنند.

استفاده از هرم تست

همه اینها در زندگی واقعی چگونه به نظر می رسد؟ بیایید تست کنیم آکاردئون جزء!

اولین غریزه شما ممکن است باز کردن ویرایشگر و شروع به نوشتن کد باشد. توصیه من؟ مدتی را صرف درک تمام ویژگی‌های کامپوننت کنید و موارد آزمایشی را که می‌خواهید پوشش دهید، بنویسید.

گیف نمایشی کتابخانه مؤلفه پیکاسو

چه چیزی را تست کنیم؟

در اینجا خلاصه ای از مواردی است که آزمایشات ما باید پوشش دهد:

  • ایالت ها – آکاردئون ها را می توان گسترش داد و جمع کرد، حالت پیش فرض آن را می توان پیکربندی کرد، و این ویژگی را می توان غیرفعال کرد
  • سبک ها – آکاردئون ها می توانند تغییرات حاشیه ای داشته باشند
  • محتوا – آنها می توانند با واحدهای دیگر کتابخانه یکپارچه شوند
  • سفارشی سازی – کامپوننت می‌تواند سبک‌های آن را لغو کند و می‌تواند آیکون‌های توسعه سفارشی داشته باشد
  • تماس های تلفنی – هر بار که وضعیت تغییر می کند، می توان یک تماس برگشتی فراخوانی کرد

گیف نمایشی کتابخانه اجزای پیکاسو - جزء آکاردئونی

چگونه تست کنیم؟

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

  • ایالت ها – تست‌های واحد می‌توانند به ما کمک کنند تا ارزیابی کنیم که آیا وضعیت‌ها بر اساس آن تغییر می‌کنند، اما ما همچنین به آزمایش‌های بصری نیاز داریم تا مطمئن شویم که مؤلفه به درستی در هر حالت ارائه شده است.
  • سبک ها – تست های دیداری باید برای تشخیص رگرسیون انواع مختلف کافی باشد
  • محتوا – ترکیبی از تست های بصری و ادغام بهترین انتخاب است، زیرا آکاردئون ها را می توان در ترکیب با بسیاری از اجزای دیگر استفاده کرد.
  • سفارشی سازی – می‌توانیم از یک آزمون واحد برای بررسی اینکه آیا نام کلاس به درستی اعمال شده است استفاده کنیم، اما برای اطمینان از اینکه مؤلفه و استایل‌های سفارشی پشت سر هم کار می‌کنند به یک آزمایش بصری نیاز داریم.
  • تماس های تلفنی – تست های واحد برای اطمینان از فراخوانی تماس های مناسب ایده آل هستند

هرم تست آکاردئون

تست های واحد

مجموعه کامل تست های واحد را می توان یافت اینجا. ما تمام تغییرات ایالتی را پوشش داده ایم سفارشی سازی و تماس های تلفنی:

  it('toggles', async () => {
    const handleChange = jest.fn()

    const { getByText, getByTestId } = renderAccordion({
      onChange: handleChange,
      expandIcon: <span data-testid='trigger' />
    })

    fireEvent.click(getByTestId('accordion-summary'))
    await waitFor(() => expect(getByText(DETAILS_TEXT)).toBeVisible())

    fireEvent.click(getByTestId('trigger'))
    await waitFor(() => expect(getByText(DETAILS_TEXT)).not.toBeVisible())

    fireEvent.click(getByText(SUMMARY_TEXT))
    await waitFor(() => expect(getByText(DETAILS_TEXT)).toBeVisible())

    expect(handleChange).toHaveBeenCalledTimes(3)
  })

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

تست های بصری در این بلوک سرو را توصیف می کند. اسکرین شات ها را می توان در پیدا کرد داشبورد هاپو.

می توانید مشاهده کنید که تمام حالات اجزای مختلف، انواع مختلف و سفارشی سازی ها ثبت شده است. هر بار که یک روابط عمومی باز می شود، CI اسکرین شات ها را مقایسه می کند که هاپو در شعبه شما ذخیره کرده است:

  it('renders', () => {
    mount(
      <TestingPicasso>
        <TestAccordion />
      </TestingPicasso>
    )
    cy.get('body').happoScreenshot()
  })
  it('renders disabled', () => {
    mount(
      <TestingPicasso>
        <TestAccordion disabled />
        <TestAccordion expandIcon={<Check16 />} />
      </TestingPicasso>
    )
    cy.get('body').happoScreenshot()
  })
  it('renders border variants', () => {
    mount(
      <TestingPicasso>
        <TestAccordion borders="none" />
        <TestAccordion borders="middle" />
        <TestAccordion borders="all" />
      </TestingPicasso>
    )
    cy.get('body').happoScreenshot()
  })

تست های یکپارچه سازی

ما یک تست “مسیر بد” نوشتیم این بلوک سرو را توصیف می کند که نشان می دهد آکاردئون همچنان به درستی عمل می کند و کاربران می توانند با مولفه سفارشی تعامل داشته باشند. ما همچنین ادعاهای بصری اضافه شده است برای اطمینان بیشتر:

describe('Accordion with custom summary', () => {
  it('closes and opens', () => {
    mount(<AccordionCustomSummary />)
    toggleAccordion()
    getAccordionContent().should('not.be.visible')

    cy.get('[data-testid=accordion-custom-summary]').happoScreenshot()

    toggleAccordion()
    getAccordionContent().should('be.visible')

    cy.get('[data-testid=accordion-custom-summary]').happoScreenshot()
  })
  // …
})

یکپارچه سازی مداوم

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

گردش کار بر روی هر تغییر در شاخه راه دور به ترتیب متوالی اجرا می‌شود و تست‌های ادغام و بصری آخرین مرحله هستند زیرا اجرای آنها گران‌ترین هستند (هم از نظر عملکرد و هم از نظر هزینه پولی). مگر اینکه همه آزمایش ها با موفقیت کامل شوند، درخواست کشش را نمی توان ادغام کرد.

این مراحلی است که GitHub Actions هر بار طی می کند:

  1. نصب وابستگی
  2. کنترل نسخه – تأیید می کند که قالب commit ها و عنوان روابط عمومی مطابقت دارند مرسوم متعهد می شود
  3. لینت – ESlint کد با کیفیت خوب را تضمین می کند
  4. کامپایل TypeScript – بررسی کنید که خطای نوع وجود ندارد
  5. گردآوری پکیج – اگر بسته ها نتوانند ساخته شوند، با موفقیت منتشر نخواهند شد. تست های Cypress ما نیز انتظار دارند کد کامپایل شده را داشته باشند
  6. تست های واحد
  7. ادغام و تست های بصری

گردش کار کامل را می توان یافت اینجا. در حال حاضر تکمیل تمام مراحل کمتر از 12 دقیقه زمان می برد.

آزمایش پذیری

مانند اکثر کتابخانه های مؤلفه، پیکاسو دارای یک مؤلفه ریشه است که باید همه مؤلفه های دیگر را بپوشاند و می توان از آن برای تنظیم قوانین جهانی استفاده کرد. این امر نوشتن تست‌ها را به دو دلیل سخت‌تر می‌کند – ناهماهنگی در نتایج آزمایش، بسته به لوازم مورد استفاده در لفاف. و دیگ بخار اضافی:

import { render } from '@testing-library/react'

describe('Form', () => {
  it('renders', () => {
    const { container } = render(
      <Picasso loadFavicon={false} environment="test">
        <Form />
      </Picasso>
    )

    expect(container).toMatchSnapshot()
  })
})

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

اکنون خواندن تست‌های ما آسان‌تر و نوشتن ساده‌تر است:

import { render } from '@toptal/picasso/test-utils'

describe('Form', () => {
  it('renders', () => {
    const { container } = render(<Form />)

    expect(container).toMatchSnapshot()
  })
})

نتیجه

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

کتابخانه های مؤلفه منحصر به فرد هستند زیرا به دو نوع مخاطب خدمت می کنند: کاربران نهایی که با رابط کاربری تعامل دارند و توسعه دهندگانی که از کد شما برای ساخت برنامه های خود استفاده می کنند. سرمایه گذاری زمان در یک چارچوب تست قوی برای همه مفید خواهد بود. سرمایه گذاری زمان در بهبود قابلیت آزمایش به شما به عنوان یک نگهدارنده و مهندسانی که از کتابخانه شما استفاده می کنند (و آزمایش می کنند) سود خواهد برد.

ما درباره مواردی مانند پوشش کد، آزمایش‌های سرتاسر، و خط‌مشی‌های نسخه و انتشار بحث نکردیم. توصیه کوتاه در مورد آن موضوعات این است: اغلب منتشر کنید، نسخه معنایی مناسب را تمرین کنید، در فرآیندهای خود شفافیت داشته باشید، و انتظاراتی را برای مهندسانی که به کتابخانه شما متکی هستند تعیین کنید. ممکن است در پست های بعدی این موضوعات را با جزئیات بیشتر بررسی کنیم.



منبع

Matthew Newman

Matthew Newman Matthew has over 15 years of experience in database management and software development, with a strong focus on full-stack web applications. He specializes in Django and Vue.js with expertise deploying to both server and serverless environments on AWS. He also works with relational databases and large datasets
[ Back To Top ]