Picasso: Bir Bileşen Kitaplığı Nasıl Test Edilir
Yayınlanan: 2022-03-11Toptal'ın tasarım sisteminin yeni bir versiyonu yakın zamanda piyasaya sürüldü ve bu, kurum içi bileşen kitaplığımız olan Picasso'daki hemen hemen her bileşende değişiklik yapmamızı gerektiriyordu. Ekibimiz bir zorlukla karşı karşıya kaldı: Gerilemelerin olmamasını nasıl sağlarız?
Kısa cevap, oldukça şaşırtıcı olmayan bir şekilde testler. Bir sürü test.
Test etmenin teorik yönlerini gözden geçirmeyeceğiz, farklı test türlerini, bunların kullanışlılığını tartışmayacağız veya neden ilk etapta kodunuzu test etmeniz gerektiğini açıklamayacağız. Blogumuz ve diğerleri bu konuları zaten ele aldı. Bunun yerine, yalnızca testin pratik yönlerine odaklanacağız.
Toptal'daki geliştiricilerin testleri nasıl yazdığını öğrenmek için okumaya devam edin. Depomuz halka açıktır, bu nedenle gerçek dünyadan örnekler kullanıyoruz. Herhangi bir soyutlama veya basitleştirme yoktur.
Piramidi Test Etme
Kendi başına tanımlanmış bir test piramidimiz yok, ancak yapsaydık şöyle görünürdü:
Toptal'ın test piramidi, vurguladığımız testleri göstermektedir.
Birim Testleri
Birim testlerinin yazılması ve çalıştırılması kolaydır. Test yazmak için çok az zamanınız varsa, bunlar ilk tercihiniz olmalıdır.
Ancak, mükemmel değiller. Hangi test kitaplığını seçerseniz seçin (bizim durumumuzda Jest ve React Testing Library [RTL]), gerçek bir DOM'ye sahip olmayacak ve farklı tarayıcılarda işlevselliği kontrol etmenize izin vermeyecek, ancak striptiz yapmanıza izin verecektir. karmaşıklığı ortadan kaldırın ve kitaplığınızın basit yapı taşlarını test edin.
Birim testleri, yalnızca kodun davranışını test ederek değil, aynı zamanda kodun genel test edilebilirliğini kontrol ederek de değer katar. Kolayca birim testleri yazamıyorsanız, büyük olasılıkla hatalı kodunuz vardır.
Görsel Regresyon Testleri
%100 birim testi kapsamına sahip olsanız bile bu, bileşenlerin cihazlar ve tarayıcılar arasında iyi göründüğü anlamına gelmez.
Görsel regresyonları manuel testle tespit etmek özellikle zordur. Örneğin, bir düğmenin etiketi 1 piksel taşınırsa, bir QA mühendisi bunu fark eder mi? Neyse ki, bu sınırlı görünürlük sorununa birçok çözüm var. LambdaTest veya Mabl gibi kurumsal düzeyde hepsi bir arada çözümleri tercih edebilirsiniz. Percy gibi eklentileri mevcut testlerinize ve ayrıca Loki veya Storybook (Picasso'dan önce kullandığımız şey) gibi DIY çözümlerine dahil edebilirsiniz. Hepsinin dezavantajları vardır: Bazıları çok pahalıdır, diğerleri ise dik bir öğrenme eğrisine sahiptir veya çok fazla bakım gerektirir.
Happo kurtarmaya! Percy'nin doğrudan rakibidir, ancak çok daha ucuzdur, daha fazla tarayıcıyı destekler ve kullanımı daha kolaydır. Başka bir büyük satış noktası mı? Görsel testler için Storybook'u kullanmaktan uzaklaşmak istediğimiz için önemli olan Cypress entegrasyonunu destekliyor. Kendimizi, bu kullanım örneğini belgelememiz gerektiğinden değil, görsel test kapsamı sağlayabilmek için hikayeler oluşturmamız gereken durumlarda bulduk. Bu, belgelerimizi kirletti ve anlaşılmasını zorlaştırdı. Görsel testleri görsel belgelerden ayırmak istedik.
Entegrasyon Testleri
İki bileşenin birim ve görsel testleri olsa bile bu, birlikte çalışacaklarının garantisi değildir. Örneğin, bir açılır öğede kullanıldığında araç ipucunun açılmadığı, ancak kendi başına kullanıldığında iyi çalıştığı bir hata bulduk.
Bileşenlerin iyi bir şekilde bütünleşmesini sağlamak için Cypress'in deneysel bileşen test özelliğini kullandık. İlk başta, düşük performanstan memnun değildik, ancak özel bir web paketi yapılandırmasıyla iyileştirmeyi başardık. Sonuç? Bileşenlerimizin birlikte iyi çalışmasını sağlayan performans testleri yazmak için Cypress'in mükemmel API'sini kullanabildik.
Test Piramidinin Uygulanması
Bütün bunlar gerçek hayatta neye benziyor? Akordeon bileşenini test edelim!
İlk içgüdünüz editörünüzü açıp kod yazmaya başlamak olabilir. Benim tavsiyem? Bileşenin tüm özelliklerini anlamak için biraz zaman ayırın ve ele almak istediğiniz test senaryolarını yazın.
Ne Test Edilecek?
Testlerimizin kapsaması gereken vakaların dökümü:
- Durumlar – Akordeonlar genişletilebilir ve daraltılabilir, varsayılan durumu yapılandırılabilir ve bu özellik devre dışı bırakılabilir
- Stiller – Akordeonlarda kenarlık varyasyonları olabilir
- İçerik – Kütüphanenin diğer birimleriyle entegre olabilirler
- Özelleştirme – Bileşenin stilleri geçersiz kılınabilir ve özel genişletme simgeleri olabilir
- Geri aramalar – Durum her değiştiğinde, bir geri arama başlatılabilir
Nasıl Test Edilir?
Artık neyi test etmemiz gerektiğini bildiğimize göre, nasıl yapacağımızı düşünelim. Test piramidimizden üç seçeneğimiz var. Piramidin bölümleri arasında minimum örtüşme ile maksimum kapsama elde etmek istiyoruz. Her bir test durumunu test etmenin en iyi yolu nedir?
- Durumlar – Birim testleri, durumların buna göre değişip değişmediğini değerlendirmemize yardımcı olabilir, ancak bileşenin her durumda doğru şekilde oluşturulduğundan emin olmak için görsel testlere de ihtiyacımız var.
- Stiller – Görsel testler, farklı varyantların gerilemelerini tespit etmek için yeterli olmalıdır.
- İçerik – Akordeonlar diğer birçok bileşenle birlikte kullanılabildiğinden, görsel ve entegrasyon testlerinin bir kombinasyonu en iyi seçimdir.
- Özelleştirme – Bir sınıf adının doğru uygulanıp uygulanmadığını doğrulamak için bir birim testi kullanabiliriz, ancak bileşen ve özel stillerin birlikte çalıştığından emin olmak için görsel bir teste ihtiyacımız var.
- Geri aramalar – Birim testleri, doğru geri aramaların başlatıldığından emin olmak için idealdir
Akordeon Test Piramidi
Birim Testleri
Tam birim testleri paketi burada bulunabilir. Tüm durum değişikliklerini, özelleştirmeyi ve geri aramaları ele aldık:

it('toggles', async () => { const handleChange = jest.fn() const { getByText, getByTestId } = renderAccordion({ onChange: handleChange, expandIcon: <span data-test /> }) 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) })Görsel Regresyon Testleri
Görsel testler bu Cypress açıklama bloğunda bulunur. Ekran görüntüleri Happo'nun kontrol panelinde bulunabilir.
Tüm farklı bileşen durumlarının, çeşitlerinin ve özelleştirmelerin kaydedildiğini görebilirsiniz. Bir PR her açıldığında, CI Happo'nun sakladığı ekran görüntülerini şubenizde alınan ekran görüntüleriyle karşılaştırır:
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() })Entegrasyon Testleri
Bu Cypress açıklama bloğuna Accordion'un hala doğru çalıştığını ve kullanıcıların özel bileşenle etkileşime girebileceğini belirten bir "kötü yol" testi yazdık. Ekstra güven için görsel iddialar da ekledik:
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() }) // … })Sürekli Entegrasyon
Picasso, QA için neredeyse tamamen GitHub Eylemlerine güveniyor. Ayrıca, aşamalı dosyaların kod kalite kontrolleri için Git kancaları ekledik. Yakın zamanda Jenkins'ten GHA'ya geçiş yaptık, dolayısıyla kurulumumuz hala MVP aşamasında.
İş akışı, uzak şubedeki her değişiklikte sıralı bir sırada yürütülür; çalıştırmaları en pahalı oldukları için (hem performans hem de parasal maliyet açısından) entegrasyon ve görsel testler son aşamadır. Tüm testler başarıyla tamamlanmadıkça, çekme talebi birleştirilemez.
GitHub Eylemlerinin her seferinde geçtiği aşamalar şunlardır:
- Bağımlılık yükleme
- Sürüm kontrolü - Taahhütlerin formatının ve PR başlığının geleneksel taahhütlerle eşleştiğini doğrular
- Lint – ESlint, iyi kalitede kod sağlar
- TypeScript derlemesi – Tip hatası olmadığını doğrulayın
- Paket derleme – Paketler oluşturulamıyorsa, başarılı bir şekilde serbest bırakılmazlar; Cypress testlerimiz ayrıca derlenmiş kod bekler
- Birim testleri
- Entegrasyon ve görsel testler
Tam iş akışı burada bulunabilir. Şu anda, tüm aşamaları tamamlamak 12 dakikadan az sürüyor.
test edilebilirlik
Çoğu bileşen kitaplığı gibi, Picasso'nun da diğer tüm bileşenleri sarması gereken ve genel kuralları ayarlamak için kullanılabilen bir kök bileşeni vardır. Bu, iki nedenden dolayı test yazmayı zorlaştırır: sarmalayıcıda kullanılan aksesuarlara bağlı olarak test sonuçlarındaki tutarsızlıklar; ve ekstra kazan plakası:
import { render } from '@testing-library/react' describe('Form', () => { it('renders', () => { const { container } = render( <Picasso loadFavicon={false} environment='test'> <Form /> </Picasso> ) expect(container).toMatchSnapshot() }) })İlk sorunu, test için genel kuralları önkoşullandıran bir TestingPicasso oluşturarak çözdük. Ancak her test durumu için bunu beyan etmek zorunda kalmak can sıkıcıdır. Bu nedenle, geçirilen bileşeni bir TestingPicasso'ya saran ve RTL'nin oluşturma işlevinden sağlanan her şeyi döndüren özel bir oluşturma işlevi oluşturduk.
Testlerimizin okunması artık daha kolay ve yazması kolay:
import { render } from '@toptal/picasso/test-utils' describe('Form', () => { it('renders', () => { const { container } = render(<Form />) expect(container).toMatchSnapshot() }) })Çözüm
Burada açıklanan kurulum mükemmel olmaktan uzaktır, ancak bir bileşen kitaplığı oluşturacak kadar maceraperest olanlarınız için iyi bir başlangıç noktasıdır. Piramitlerin test edilmesi hakkında çok şey okudum, ancak bunları pratikte uygulamak her zaman kolay olmuyor. Bu nedenle sizi kod tabanımızı keşfetmeye, hatalarımızdan ve başarılarımızdan ders almaya davet ediyorum.
Bileşen kitaplıkları benzersizdir çünkü iki tür hedef kitleye hizmet ederler: Kullanıcı arabirimiyle etkileşime giren son kullanıcılar ve kendi uygulamalarını oluşturmak için kodunuzu kullanan geliştiriciler. Sağlam bir test çerçevesine zaman ayırmak herkese fayda sağlayacaktır. Test edilebilirlik iyileştirmelerine zaman ayırmak, bir bakımcı olarak size ve kitaplığınızı kullanan (ve test eden) mühendislere fayda sağlayacaktır.
Kod kapsamı, uçtan uca testler, sürüm ve yayın ilkeleri gibi konuları tartışmadık. Bu konularla ilgili kısa tavsiye şudur: sık sık yayınlayın, doğru anlamsal sürüm oluşturmayı uygulayın, süreçlerinizde şeffaf olun ve kitaplığınıza güvenen mühendisler için beklentiler belirleyin. Bu konuları daha sonraki yazılarda daha ayrıntılı olarak tekrar gözden geçirebiliriz.
