Bir E2E Test Yolculuğu Bölüm 2: WebdriverIO'dan Cypress'e

Yayınlanan: 2019-11-21

Not: Bu, #frontend@twiliosendgrid'den bir gönderidir. Diğer mühendislik gönderileri için teknik blog rulosuna gidin.

Tüm ön uç uygulamalarımızda şu hedefimiz vardı ve hâlâ da var: ön uç uygulamalarımız için tutarlı, hata ayıklanabilir, bakımı yapılabilir ve değerli E2E (uçtan uca) otomasyon testleri yazmanın bir yolunu sağlamak ve CICD ile entegre etmek (sürekli entegrasyon) ve sürekli dağıtım).

Bugün sahip olduğumuz duruma, yüzlerce E2E testinin muhtemelen tetiklendiği veya SendGrid'deki tüm ön uç ekiplerimizde bir programa göre çalıştığı duruma ulaşmak için, bu ana başarıya ulaşana kadar yol boyunca birçok potansiyel çözümü araştırmak ve denemek zorunda kaldık. amaç.

Tüm ekiplerin tek bir depoya katkıda bulunabileceği ve tarayıcılar arası otomasyon testleri çalıştırabileceği, SiteTestUI diğer adıyla STUI adlı özel test mühendisleri tarafından geliştirilen kendi özel Ruby Selenium çözümümüzü kullanıma sunmaya çalıştık. Ne yazık ki yavaş, kesintili testlere, yanlış alarmlara, depolar ve diller arasındaki bağlam eksikliğine, bir sepette çok fazla el, acı verici hata ayıklama deneyimlerine ve değer sağlamaktan çok bakım için harcanan zamana yenik düştü.

Daha sonra WebdriverIO'da her takımın uygulama depolarıyla birlikte JavaScript'te testler yazmak için gelecek vaat eden başka bir kitaplık denedik. Bu, bazı sorunları çözerken, daha fazla ekip sahipliğini güçlendirdi ve testleri CICD sağlayıcımız olan Buildkite ile entegre etmemize izin verdi, ancak yine de benzer Selenium hataları ve tuhaflıklarıyla uğraşmanın yanı sıra hata ayıklaması acı verici ve yazması zor olan lapa lapa testlerimiz vardı. .

Başka bir STUI 2.0'dan kaçınmak istedik ve diğer seçenekleri araştırmaya başladık. STUI'den WebdriverIO'ya geçiş sırasında öğrenilen dersler ve keşfedilen stratejiler hakkında daha fazla bilgi edinmek isterseniz, blog yazısı serisinin 1. bölümüne göz atın.

Blog gönderisi serisinin bu son ikinci bölümünde, STUI ve WebdriverIO'dan Cypress'e yolculuğumuzu ve genel altyapıyı kurarken, organize E2E testleri yazarken, Buildkite boru hatlarımızla entegrasyon ve ölçeklendirmede benzer geçişlerden nasıl geçtiğimizi ele alacağız. kuruluştaki diğer ön uç ekipleri.

TLDR: Cypress'i STUI ve WebdriverIO üzerinden benimsedik ve CICD ile entegre olacak değerli E2E testleri yazma hedeflerimizin tamamını gerçekleştirdik. WebdriverIO ve STUI'den öğrendiğimiz pek çok çalışma ve ders, bugün Cypress testlerini nasıl kullandığımızı ve entegre ettiğimizi güzel bir şekilde aktardı.

İçindekiler

Cypress'i Keşfetme ve İniş

STUI ve WebdriverIO'dan Cypress'e geçiş

Adım 1: Cypress için Bağımlılıkları Yükleme

2. Adım: Ortam Yapılandırmaları ve Komut Dosyaları

Ortam Yapılandırmalarının ve Komut Dosyalarının İlk Geçişi

Ortam Yapılandırmalarının ve Komut Dosyalarının Evrimi

3. Adım: E2E testlerini yerel olarak uygulama

Adım 4: Testleri yerleştirme

Adım 5: CICD ile Entegrasyon

Adım 6: Cypress ile WebdriverIO/STUI'yi Karşılaştırma

7. Adım: Diğer Ön Uç Takımlarına Ölçeklendirme

Cypress ile sabırsızlıkla beklediğimiz şey

Cypress'i Geleceğe Sahiplenmek

Cypress'i Keşfetme ve İniş

WebdriverIO'ya alternatifler aradığımızda, WebdriverIO'ya ayarlanmış benzer bir özelliğe sahip İletki ve Gece Saati gibi diğer Selenyum sarmalayıcıları gördük, ancak büyük olasılıkla uzun kurulumlar, kesintili testler ve yol boyunca sıkıcı hata ayıklama ve bakımlarla karşılaşacağımızı hissettik.

Hızlı kurulumları, tarayıcıda yapılan hızlı ve hata ayıklanabilir testleri, ağ katmanı istek sapmasını ve en önemlisi, kaputun altında Selenium'u kullanmamayı sergileyen Cypress adlı yeni bir E2E test çerçevesine çok şükür ki rastladık.

Video kayıtları, Cypress GUI, ücretli Kontrol Paneli Hizmeti ve denenecek paralelleştirme gibi harika özelliklere hayran kaldık. Geliştiricilerimiz ve QA'larımız için testleri uygulamak, hata ayıklamak ve sürdürmek için emrimizde bir araç repertuarı ile Chrome'dan tutarlı bir şekilde geçen değerli testler lehine tarayıcılar arası destekten ödün vermeye hazırdık.

Ayrıca, tüm ön uç ekiplerimizde testlere daha standart bir yaklaşıma sahip olmamız için seçilen test çerçevelerini, iddia kitaplıklarını ve diğer tüm araçları takdir ettik. Aşağıda, WebdriverIO ve Cypress gibi bir çözüm arasındaki farkların bir ekran görüntüsünü sağladık ve Cypress ve Selenium çözümleri arasındaki farklardan daha fazlasını görmek istiyorsanız, nasıl çalıştığına dair belgelerine göz atabilirsiniz.

Bunu akılda tutarak, CICD sırasında Buildkite ile eninde sonunda entegre edilecek hızlı, tutarlı ve hata ayıklanabilir E2E testleri yazmak için başka bir çözüm olarak Cypress'i test etmeye karar verdik. Ayrıca, Cypress'i ileriye dönük olarak aramaya devam edip etmeyeceğimizi veya test takımlarımızı oluşturmamız gerekip gerekmediğini nihai olarak veri noktalarına göre belirlemek için Cypress'i önceki Selenium tabanlı çözümlerle karşılaştırmak için kasıtlı olarak başka bir hedef belirledik. Mevcut WebdriverIO testlerini ve halen STUI'de bulunan diğer yüksek öncelikli testleri Cypress testlerine dönüştürmeyi ve geliştirici deneyimlerimizi, hızımızı, kararlılığımızı, test çalıştırma sürelerimizi ve testlerin bakımını karşılaştırmayı planladık.

STUI ve WebdriverIO'dan Cypress'e geçiş

STUI ve WebdriverIO'dan Cypress'e geçiş yaparken, ön uç uygulama depolarımızda STUI'den WebdriverIO'ya geçişimizi denediğimizde kullandığımız aynı üst düzey stratejiyle sistematik olarak ele aldık. WebdriverIO için bu tür adımları nasıl gerçekleştirdiğimize dair daha fazla ayrıntı için lütfen blog yazısı serisinin 1. bölümüne bakın. Cypress'e geçiş için genel adımlar aşağıdakileri içeriyordu:

  1. Cypress ile bağlantı kurmak için bağımlılıkları yükleme ve ayarlama
  2. Ortam yapılandırmaları ve komut dosyası komutları oluşturma
  3. Farklı ortamlara karşı yerel olarak geçen E2E testlerini uygulama
  4. Testleri dockerize etme
  5. Dockerized testleri CICD sağlayıcımız Buildkite ile entegre etme

İkincil hedeflerimizi gerçekleştirmek için, Cypress'i önceki Selenium çözümleriyle karşılaştırmak ve sonunda Cypress'i organizasyondaki tüm ön uç ekipler arasında ölçeklendirmek için ek adımlar ekledik:

6. Cypress'i geliştirici deneyimleri, testlerin hızı ve kararlılığı açısından WebdriverIO ve STUI ile karşılaştırma
7. Diğer ön uç ekiplerine ölçeklendirme

Adım 1: Cypress için Bağımlılıkları Yükleme

Cypress ile hızlı bir şekilde çalışmaya başlamak için tek yapmamız gereken projelerimize `npm install cypress` yüklemek ve bir `cypress.json` konfigürasyon dosyası ve cypress klasörü ile otomatik olarak düzenlenmesi için Cypress'i ilk kez başlatmaktı. komutlar ve eklentiler için başlangıç ​​donanımları, testler ve diğer kurulum dosyaları ile. Cypress'in test yürütücüsü olarak Mocha, iddialar için Chai ve kullanmak ve zincirlemek için daha fazla iddia için Chai-jQuery ve Sinon-Chai ile birlikte gelmesini takdir ettik. WebdriverIO veya STUI ile ilk başladığımız zamana kıyasla, hangi test çalıştırıcısı, muhabiri, iddiaları ve hizmet kitaplıklarını kuracağımızı ve kullanacağımızı araştırmak için artık çok fazla zaman harcamak zorunda kalmadık. Oluşturulan testlerden bazılarını Cypress GUI ile hemen çalıştırdık ve zaman yolculuğu hata ayıklama, seçici oyun alanı, kaydedilmiş videolar, ekran görüntüleri, komut günlükleri, tarayıcı geliştirici araçları vb. gibi elimizdeki birçok hata ayıklama özelliğini keşfettik.

Ayrıca, yeni Cypress test kodunu işlerken izlenecek ekstra statik tip denetimi ve biçimlendirme kuralları için Eslint ve TypeScript ile daha sonra kurduk. Başlangıçta TypeScript desteğiyle ilgili bazı aksaklıklar yaşadık ve eklenti dosyalarının etrafında toplanmış olanlar gibi JavaScript dosyaları olması gereken bazı dosyalar vardı, ancak çoğunlukla testlerimiz, sayfa nesnelerimiz ve komutlarımız için dosyalarımızın çoğunu kontrol etmeyi başardık.

Ön uç ekiplerimizden birinin sayfa nesnelerini, eklentileri ve komutları birleştirmek için izlediği örnek bir klasör yapısı:

2. Adım: Ortam Yapılandırmaları ve Komut Dosyaları

Cypress'i yerel olarak çalışacak şekilde hızlı bir şekilde kurduktan ve ayarladıktan sonra, Cypress testlerimizin her ortam için farklı ayarlarla çalışması için bir yola ihtiyacımız vardı ve WebdriverIO komutlarımızın yapmamıza izin verdiği aynı kullanım durumlarını desteklemek istedik. Bu testleri nasıl gerçekleştirmek istediğimize ve neden onları desteklemek istediğimize ilişkin kullanım durumlarının çoğunu gösteren bir liste aşağıda verilmiştir:

  • Localhost üzerinde çalışan bir Webpack dev sunucusuna (yani http://localhost:8000) karşı ve bu dev sunucusu belirli bir ortam API'sine (yani https://testing.api.com veya https://staging.api. com) test etme veya evreleme gibi.
    Niye ya? Bazen, öğelerle daha sağlam bir şekilde etkileşim kurmak için testlerimize daha spesifik seçiciler eklemek gibi yerel web uygulamamızda değişiklikler yapmamız gerekir veya yeni bir özellik geliştirme sürecindeydik ve mevcut otomasyon testlerini ayarlamamız ve doğrulamamız gerekiyordu. yeni kod değişikliklerimize karşı yerel olarak geçerdi. Uygulama kodu değiştiğinde ve henüz konuşlandırılmış ortama geçmediğimizde, testlerimizi yerel web uygulamamıza karşı çalıştırmak için bu komutu kullandık.
  • Test etme veya hazırlama gibi belirli bir ortam (ör. https://testing.app.com veya https://staging.app.com) için dağıtılan bir uygulamaya karşı
    Niye ya? Diğer zamanlarda uygulama kodu değişmez, ancak bazı aksaklıkları gidermek için test kodumuzu değiştirmemiz gerekebilir veya herhangi bir ön uç değişikliği yapmadan testleri tamamen eklemek veya silmek için kendimizi yeterince güvende hissediyoruz. Testlerimizin CICD'de nasıl çalıştığını daha yakından simüle etmek için dağıtılan uygulamaya karşı testleri yerel olarak güncellemek veya hata ayıklamak için bu komutu yoğun bir şekilde kullandık.
  • Test etme veya hazırlama gibi belirli bir ortam için dağıtılmış bir uygulamaya karşı bir Docker kapsayıcısında çalıştırma
    Niye ya? Bu, CICD'ye yöneliktir, bu nedenle, örneğin aşamalı olarak dağıtılan uygulamaya karşı bir Docker kapsayıcısında çalıştırılacak E2E testlerini tetikleyebilir ve kodun üretime dağıtılmasından önce veya özel bir işlem hattında zamanlanmış test çalıştırmalarında geçtiklerinden emin olabiliriz. Bu komutları başlangıçta ayarlarken, farklı ortam değişken değerlerine sahip Docker kapsayıcılarını döndürmek için çok sayıda deneme yanılma gerçekleştirdik ve CICD sağlayıcımız Buildkite ile bağlantı kurmadan önce uygun testlerin başarıyla yürütüldüğünü test ettik.

Ortam Yapılandırmalarının ve Komut Dosyalarının İlk Geçişi

Cypress'i kurmayı ilk denediğimizde, bunu Gönderen Kimlik Doğrulaması, E-posta Etkinliği ve E-posta Doğrulaması gibi özellik sayfalarını içeren bir web uygulaması olan https://app.sendgrid.com'u kapsayan depoda yaptık ve kaçınılmaz olarak paylaştık. https://mc.sendgrid.com alan adını kapsayan Pazarlama Kampanyaları web uygulamamızın arkasındaki ekiplerle keşiflerimiz ve öğrendiklerimiz. E2E testlerimizi hazırlama ortamımıza karşı çalıştırmak istedik ve kullanım durumlarımızı gerçekleştirmek için Cypress'in komut satırı arayüzünü ve --config veya --env gibi seçenekleri kullandık.

Cypress testlerini yerel olarak örneğin http://127.0.0.1:8000 üzerindeki web uygulamasına veya konuşlandırılmış hazırlama uygulaması URL'sine karşı çalıştırmak için baseUrl yapılandırma bayrağını ayarladık ve yardımcı olması için testEnv gibi ekstra ortam değişkenleri ekledik Cypress testlerimizde belirli armatürleri veya ortama özel test verilerini yükleyin. Örneğin, kullanılan API anahtarları, oluşturulan kullanıcılar ve diğer kaynaklar ortamlar arasında farklı olabilir. Bu armatürleri değiştirmek veya bazı özellikler bir ortamda desteklenmiyorsa veya test kurulumu farklıysa özel koşullu mantık eklemek için testEnv kullandık ve özelliklerimizde Cypress.env(“testEnv”) gibi bir çağrı aracılığıyla ortama erişirdik.

Daha sonra komutlarımızı cypress:open:* yerel olarak geliştirdiğimizde UI üzerinden çalıştırılacak testlerimizi seçmemiz için Cypress GUI'nin açılmasını temsil edecek ve cypress:run:* komutlarımızı daha özel olan başsız modda testlerin yürütülmesini belirtmek için düzenledik CICD sırasında bir Docker kapsayıcısında çalışmak için. Açıldıktan veya run sonra gelen, ortam olacaktır, bu nedenle komutlarımız GUI'yi open için npm run cypress:open:localhost:staging gibi kolayca okunur ve hazırlama API'lerini veya npm run cypress:run:staging . npm run cypress:run:staging dağıtılan hazırlama uygulamasına ve API'ye karşı testleri başsız modda çalıştırmak için hazırlama. package.json Cypress betikleri şu şekilde çıktı:

Ortam Yapılandırmalarının ve Komut Dosyalarının Evrimi

Başka bir projede, Cypress cypress/plugins/index.js dosyasındaki bazı Düğüm mantığından yararlanmak için Cypress komutlarımızı ve yapılandırmalarımızı, temel cypress.json dosyasına ve adı verilen bir ortam değişkenine dayalı olarak okunacak ayrı yapılandırma dosyalarına sahip olacak şekilde geliştirdik. configFile belirli bir yapılandırma dosyasını yüklemek için. Yüklenen yapılandırma dosyaları daha sonra temel dosyayla birleştirilerek sonunda bir hazırlama veya sahte arka uç sunucusuna işaret edilir.

Sahte arka uç sunucusu hakkında daha fazla merak ediyorsanız, isteklerde iletilen sorgu parametrelerine bağlı olarak statik JSON verilerinin ve durum kodlarının (ör. 200, 4XX, 5XX) değişen yanıtlarını döndüren arka uç uç noktalarına sahip bir Ekspres sunucu geliştirdik. Bu, gerçek API'nin gelecekte kullanıma sunulduğunda nasıl görüneceğini taklit eden yanıtlarla sahte arka uç sunucusuna yapılan gerçek ağ çağrılarıyla sayfa akışlarını geliştirmeye devam etmek için ön ucun engellemesini kaldırdı. Ayrıca, aksi takdirde üretimde yeniden üretilmesi zor olacak farklı UI durumlarımız için farklı başarı ve hata yanıt düzeylerini kolayca simüle edebilirdik ve deterministik ağ çağrıları yapacağımız için, Cypress testlerimiz aynı ağı ateşlemede daha az kesintili olacaktır. istekler ve cevaplar her zaman.

Genel zaman aşımları için paylaşılan özellikler, daha sonra bahsedeceğimiz Cypress Dashboard Hizmeti ile bağlantı kurmak için proje kimliği ve aşağıda gösterildiği gibi diğer ayarları içeren bir temel cypress.json dosyamız vardı:

Yerel Webpack dev sunucumuzu yerel bir sahte API sunucusuna karşı çalıştırmak için localhostMock.json veya konuşlandırılmış hazırlama uygulamasına ve API'ye karşı çalıştırmak için staging.json gibi yapılandırma dosyalarımızın her birini tutmak için cypress klasöründe bir config klasörü oluşturduk. Temel yapılandırma ile değiştirilecek ve birleştirilecek bu yapılandırma dosyaları şöyle görünüyordu:

CICD yapılandırma dosyaları, daha sonra inceleyeceğimiz değişen Docker hizmeti ön uç temel URL'sini ve sahte sunucu API ana bilgisayarlarını hesaba katmak için ortam değişkenlerini dinamik olarak ayarlamamız gerektiğinden daha da basit bir JSON dosyasına sahipti.

Cypress cypress/plugins/index.js dosyamızda, bir Cypress komutundan configFile adlı bir ortam değişkenini okumak için mantık ekledik ve bu, sonunda config klasöründeki ilgili dosyayı okuyacak ve aşağıdaki gibi temel cypress.json ile birleştirecek:

Kullanım durumlarımız için ayarlanmış ortam değişkenleriyle mantıklı Cypress komutları yazmak için aşağıdakine benzeyen bir Makefile yararlandık:

Bir Makefile içinde düzgünce düzenlenmiş bu komutlarla, `package.json` npm betiklerimizde make cypress_open_staging veya make cypress_run_staging gibi şeyleri hızlı bir şekilde yapabiliriz.

Önceden, hatasız düzenlemesi zor olan bazı komutları uzun bir satıra yerleştirirdik. Neyse ki Makefile, ortam değişkenlerinin birden çok satırda Cypress komutlarına okunabilir enterpolasyonu ile işleri çok daha iyi yaymaya yardımcı oldu. Hangi ortam yapılandırma dosyasının yükleneceğini BASE_URL , sayfalarımızı ziyaret etmek için configFile , farklı arka uç ortamları için API_HOST veya Makefile komutlarından herhangi birini başlatmadan önce hangi testlerin çalıştırılacağını belirlemek için SPECS gibi ortam değişkenlerini hızlı bir şekilde ayarlayabilir veya dışa aktarabiliriz.

Ayrıca Makefile komutlarını diğer uzun npm betikleri ve Docker komutlarının yanı sıra Webpack varlıklarımızı oluşturmak, bağımlılıkları kurmak veya komutları başkalarıyla aynı anda çalıştırmak gibi kullandık. Sonunda bazı Makefile komutlarını package.json komut dosyaları bölümüne çevirecektik, ancak birisi yalnızca Makefile'ı kullanmak isterse bu gerekli değildi ve aşağıdaki gibi görünürdü:

Cypress CICD komutlarının çoğunu, günlük geliştirmede kullanılacak komutlar olmadığı için bilerek dışarıda bıraktık ve bunun sonucunda package.json daha düzenli tuttuk. En önemlisi, sahte sunucu ve yerel Webpack dev sunucusu ile ilgili tüm Cypress komutlarını hazırlama ortamlarına karşı ve hangilerinin başsız modda "çalıştırmak" yerine GUI'yi "açtığını" hemen bir bakışta görebiliyorduk.

3. Adım: E2E testlerini yerel olarak uygulama

Cypress ile E2E testlerini uygulamaya başladığımızda, dönüştürmek için WebdriverIO ve STUI'deki mevcut testlerimize başvurduk ve basit sağlık kontrollerinden karmaşık mutlu yol akışlarına kadar diğer yüksek öncelikli özellikler için daha yeni testler ekledik. Mevcut sayfa nesnelerini ve test dosyalarını WebdriverIO veya STUI'den Cypress'teki eşdeğer sayfa nesnelerine ve özelliklerine çevirmek çok kolay oldu. Aslında, öğeler için daha az açık bekleme ve iddiaların ve diğer Cypress komutlarının daha iyi zincirlenebilirliği ile öncekinden çok daha temiz kodla sonuçlandı.

Örneğin, testlerin genel adımları son kullanıcı açısından aynı kaldı, bu nedenle dönüştürme çalışması WebdriverIO veya STUI API'sini Cypress API'ye aşağıdaki şekillerde eşleştirmeyi içeriyordu:

  • Bir çok komut esasen ortaya çıktı ve neredeyse sadece $ veya browser cy veya Cypress ile değiştirdiğimiz noktaya cy.get(“.button”).click() şekilde çalıştı $(“.button”).click() cy.get(“.button”).click() , browser.url() 'den cy.visit() 'e veya $(“.input”).setValue() 'den cy.get(“.input”).type()
  • $ veya $$ kullanımı genellikle cy.get(...) veya cy.contains(...) , yani $$(“.multiple-elements-selector”) veya $(“.single-element-selector”) cy.get(“.any-element-selector”) , cy.contains(“text”) veya cy.contains(“.any-selector”)
  • $(“.selector”).waitForVisible(timeoutInMs) , $(“.selector”).waitUntil(...) veya $(“.selector”).waitForExist() çağrılarının kaldırılması, Cypress'in varsayılan olarak izin verilmesi lehine öğelerin yeniden denemelerini ve alınmasını cy.get('.selector') ve cy.contains(textInElement) ile tekrar tekrar ele alın. Varsayılandan daha uzun bir zaman aşımına ihtiyacımız olsaydı, cy.get('.selector', { timeout: longTimeoutInMs }) öğesini birlikte kullanırdık ve ardından öğeyi aldıktan sonra, örneğin cy.get(“.selector”).click() öğesiyle bir şeyler yapmak için sonraki eylem komutunu zincirlerdik. cy.get(“.selector”).click() .
  • Tarayıcı ile özel komutlar. addCommand('customCommand, () => {})` turned into `Cypress.Commands.add('customCommand', () => {}) ve `cy.customCommand()` yapıyor
  • node-fetch adlı bir kitaplık kullanarak API üzerinden kurulum veya sökme için ağ istekleri yapmak ve bunu browser.call(() => return fetch(...)) ve/veya browser.waitUntil(...) içine sarmak Cypress Node sunucusunda cy.request(endpoint) veya tanımladığımız özel bir eklenti aracılığıyla HTTP istekleri yapmak ve cy.task(taskToHitAPIOrService) gibi çağrılar yapmak.
  • Önceleri, önemli bir ağ isteğinin kayda değer herhangi bir kullanıcı arayüzü değişikliği olmadan muhtemelen tamamlanmasını beklemek zorunda kaldığımızda, bazen browser.pause(timeoutInMs) kullanmaya başvurmak zorunda kalıyorduk, ancak Cypress ile bunu ağ saplama işleviyle geliştirdik ve dinleyebildik. ve belirli isteğin cy.server() , cy.route(“method”, “/endpoint/we/are/waiting/for).as(“endpoint”)`, and `cy.wait(“@endpoint”) , isteği tetikleyecek eylemi başlatmadan önce.

WebdriverIO sözdiziminin ve komutlarının çoğunu Cypress komutlarına çevirdikten sonra, testler için ihtiyaç duyduğumuz her sayfa için ortak paylaşılan işlevsellik için bir temel sayfa nesnesine ve genişletilmiş sayfa nesnelerine sahip olma konseptini getirdik. Burada, tüm sayfalarda paylaşılacak ortak bir open() işlevine sahip bir temel sayfa nesnesi örneği verilmiştir.

Genişletilmiş bir sayfa nesnesi, öğe seçiciler için alıcılar ekler, open() işlevini sayfa yolu ile uygular ve aşağıda gösterildiği gibi herhangi bir yardımcı işlevsellik sağlar.

Gerçek genişletilmiş sayfa nesnelerimiz, tüm CSS seçicilerimizi tek bir yerde tutmak için basit bir nesne haritası kullandı; bunlar, veri öznitelikleri, birim testlerinde referans olarak React bileşenlerimize ekleyeceğimiz ve Cypress sayfa nesnelerinde seçicilerimiz olarak kullanacağız. Ayrıca, sayfa nesnesi sınıflarımız, örneğin bir sayfa nesnesinin, Bastırma sayfalarımız gibi bir grup benzer görünümlü ve işleyen sayfa için yeniden kullanıldığını ve rotayı veya belirli özellikleri değiştirmek için argümanlar ileteceğimizi söylesek, zaman zaman sınıf oluşturucusundan yararlanarak değişiyordu.

Ek bir not olarak, ekiplerin sayfa nesnelerini kullanmasına gerek yoktu, ancak tüm sayfalarda ortak işlevselliği paylaşmak için sayfa işlevselliğini ve DOM öğesi seçici referanslarını standart bir sınıf nesne yapısıyla birlikte tutmak için modelin tutarlılığını takdir ettik. Diğer ekipler, ES6 sınıflarını kullanmadan küçük yardımcı işlevlerle birçok farklı dosya oluşturmayı tercih etti, ancak çıkarılması gereken önemli şey, daha iyi geliştirici verimliliği ve sürdürülebilirliği için her şeyi kapsüllemek ve testler yazmak için organize, öngörülebilir bir yol sağlamaktı.

Testi API aracılığıyla mümkün olduğunca kurmaya çalışarak, eski WebdriverIO testlerimizde kullanılan aynı genel test stratejisine bağlı kaldık. Test etmeyi amaçlamadığımız parçalar için kesinti ve zaman kaybı yaratmamak için özellikle kurulum durumumuzu UI aracılığıyla oluşturmaktan kaçınmak istedik. Çoğu test bu stratejiyi içeriyordu:

  • API aracılığıyla kurma veya yıkma – Kullanıcı arabirimi aracılığıyla bir varlık oluşturmayı test etmemiz gerekirse, varlığı önce API aracılığıyla sildiğimizden emin oluruz. Önceki test çalıştırmasının nasıl başarılı veya başarısız sonuçlandığına bakılmaksızın, testin tutarlı bir şekilde davranmasını ve doğru koşullarla başlamasını sağlamak için testin düzgün bir şekilde kurulması veya API üzerinden kaldırılması gerekiyordu.
  • API aracılığıyla özel bir test kullanıcısında oturum açma – Testlerimizin yalıtılması ve paralel olarak çalıştırıldığında birbirlerinin kaynaklarını ezmemesi için sayfa başına veya hatta otomasyon testi başına özel test kullanıcıları oluşturduk. Giriş sayfamızla aynı isteği API aracılığıyla yaptık ve kimliği doğrulanmış sayfayı doğrudan ziyaret edebilmemiz ve gerçek test adımlarına başlayabilmemiz için test başlamadan önce tanımlama bilgisini depoladık.
  • Adımları son kullanıcı perspektifinden otomatikleştirme – Kullanıcıya API üzerinden oturum açtıktan sonra, sayfayı doğrudan ziyaret ettik ve bir özellik akışını tamamlamak ve kullanıcının doğru şeyleri gördüğünü ve bunlarla etkileşime girdiğini doğrulamak için son kullanıcının yapacağı adımları otomatikleştirdik. yol boyunca.

Testi beklenen orijinal durumuna geri döndürmek için, global bir cy.login komutuyla API aracılığıyla özel bir test kullanıcısına oturum açar, kullanıcının oturumunu açık tutmak için bir çerez ayarlar, geri dönmek için gerekli API çağrılarını yaparız. kullanıcıyı cy.request(“endpoint”) veya cy.task(“pluginAction”) çağrıları aracılığıyla istenen başlangıç ​​durumuna getirin ve doğrudan test etmeye çalıştığımız kimliği doğrulanmış sayfayı ziyaret edin. Ardından, aşağıdaki test düzeninde gösterildiği gibi bir kullanıcı özellik akışını gerçekleştirmek için adımları otomatikleştirirdik.

Giriş yapmak için bahsettiğimiz özel komutları hatırlıyor musunuz, cy.login() ve çıkış yapıyor, cy.logout() ? Bunları Cypress'te bu şekilde kolayca uyguladık, böylece tüm testlerimiz aynı şekilde API üzerinden bir kullanıcıya giriş yapacaktı.

Ayrıca, WebdriverIO veya STUI ile daha önce pek iyi yapamadığımız e-posta içeren belirli karmaşık akışları otomatikleştirmek ve doğrulamak istedik. Bazı örnekler, E-posta Etkinliğini bir CSV'ye aktarmayı, Gönderen Kimlik Doğrulaması için İş Arkadaşına Gönder akışından geçmeyi veya E-posta Doğrulama sonuçlarını bir CSV'ye aktarmayı içeriyordu. Cypress, bir testte birinin birden fazla süper alana erişmesini engeller, bu nedenle sahip olmadığımız bir kullanıcı arayüzü aracılığıyla bir e-posta istemcisine gitmek bir seçenek değil, sorunluydu.

Bunun yerine Cypress eklentilerini cy.task(“pluginAction”) komutları aracılığıyla geliştirdik ve Cypress Node sunucusundaki bazı kitaplıkları kullanarak bir test e-postası IMAP istemcisine/gelen kutusuna bağlanmak için bir eylem istedikten sonra bir gelen kutusundaki eşleşen e-postaları kontrol etmek için kullandık. kullanıcı arayüzünde ve belirli indirme sayfalarının ortaya çıktığını ve tüm müşteri akışını etkin bir şekilde tamamladığını doğrulamak için bu e-postalardan web uygulama alanımıza geri yönlendirme bağlantılarını takip etmek için. Belirli konu satırları verildiğinde e-postaların SquirrelMail gelen kutusuna ulaşmasını bekleyecek, e-postaları silecek, e-posta gönderecek, e-posta olaylarını tetikleyecek, arka uç hizmetlerini yoklayacak ve testlerimizin kullanması için API aracılığıyla çok daha yararlı kurulumlar ve ayırmalar yapacak eklentiler uyguladık.

Cypress ile gerçekte neyi test ettiğimiz hakkında daha fazla bilgi sağlamak için, aşağıdakiler gibi çok sayıda yüksek değerli vakayı ele aldık:

  • Tüm sayfalarımız için sağlık kontrolleri, yani uygulamayı gezmek – Bazı içeriklerle yüklenen sayfaların bazen belirli arka uç hizmetlerine veya ön uç barındırma hizmetinin kapalı olmasına neden olduğundan emin olmak istedik. Ayrıca, seçiciler ve yardımcı işlevlerle sayfa nesneleri oluşturmaya ilişkin zihinsel kas belleğini oluşturmak ve bir ortama karşı çalışan hızlı, çalışan testler almak için bu testleri yapmanızı da önerdik.
  • Bir sayfada CRUD işlemleri – Testleri her zaman API aracılığıyla buna göre sıfırlar ve ardından kullanıcı arayüzünde özellikle oluşturma, okuma, güncelleme veya silme işlemlerini test ederiz. Örneğin, UI aracılığıyla bir alan kimlik doğrulaması oluşturabilmeyi test edersek, son test çalıştırmasının nasıl sona erdiğine bakılmaksızın, devam etmeden önce UI aracılığıyla oluşturacağımız alan adının ilk önce API aracılığıyla silindiğinden emin olmamız gerekiyordu. etki alanını oluşturmak ve çarpışmaları önlemek için otomatik kullanıcı arayüzü adımlarıyla. Kullanıcı arayüzü aracılığıyla bir gizlemeyi silmeyi test ettiysek, önce API aracılığıyla gizlemeyi oluşturduğumuzdan emin olduk ve ardından adımlara devam ettik.
  • Bir sayfada arama filtrelerini test etme – Filtrelerin otomatik olarak doldurulduğundan emin olmak için E-posta Etkinliği ile bir dizi gelişmiş arama filtresi ayarlamayı ve sayfayı sorgu parametreleriyle ziyaret etmeyi test ettik. Ayrıca E-posta Doğrulaması için API aracılığıyla veri ekledik ve bir kez daha farklı arama filtrelerini başlattık ve tablonun o sayfadaki arama filtreleriyle eşleştiğini doğruladık.
  • Farklı kullanıcı erişimleri – Twilio SendGrid'de, altlarında değişen kapsamlara veya erişim izinlerine sahip ekip arkadaşlarına veya alt kullanıcılara sahip olabilen ve ayrıca değişen derecelerde erişime sahip olan ve bir şekilde bir üst hesaba benzer şekilde davranan üst hesaplarımız vardır. Belirli sayfalar ve alt kullanıcılar için yönetici erişimine karşı salt okuma erişimine sahip ekip arkadaşları, bir sayfada belirli şeyleri görür veya görmez ve bu, bu tür kullanıcılarda oturum açmayı ve Cypress testlerinde ne görüp görmediklerini kontrol etmeyi otomatikleştirmeyi kolaylaştırdı.
  • Farklı kullanıcı paketleri – Kullanıcılarımız ayrıca Essentials, Pro ve Premier gibi ücretsiz ve ücretli paket türlerinde değişiklik gösterebilir ve bu paketler bir sayfada belirli şeyleri görebilir veya görmeyebilir. Kullanıcılara farklı paketlerle giriş yapar ve Cypress testlerinde kullanıcıların eriştiği özellikleri, kopyaları veya sayfaları hızlı bir şekilde doğrulardık.

Adım 4: Testleri yerleştirme

Buluttaki yeni bir AWS makinesinde her Buildkite ardışık düzen adımını yürütürken, bu makinelerde Düğüm, tarayıcılar, uygulama kodumuz veya Cypress'i çalıştıracak başka bağımlılıklar olmadığı için basitçe npm run cypress:run:staging . testler. WebdriverIO'yu daha önce kurduğumuzda, testlerin çalışması için uygun Selenium, Chrome ve uygulama kodu hizmetlerinin birlikte çalışması için bir Docker Compose dosyasında üç ayrı hizmeti birleştirmemiz gerekiyordu.

Cypress ile, ortamı bir Dockerfile kurmak için yalnızca Cypress temel Docker görüntüsüne, cypress/base 'e ve Cypress'i çalıştırmak için uygulama kodumuzla bir docker-compose.yml dosyasında yalnızca bir hizmete ihtiyacımız olduğundan çok daha basitti. testler. Kullanılacak başka Cypress Docker görüntüleri ve Docker'da Cypress testlerini kurmanın başka yolları olduğundan, bunu yapmanın bir yolunu ele alacağız. Alternatif olarak Cypress belgelerine bakmanızı öneririz.

Cypress testlerini çalıştırmak için gerekli tüm uygulamamız ve test kodlarımızla bir hizmet getirmek için Dockerfile adında bir Dockerfile.cypress ve tüm node_modules ve kodu bir Node ortamında görüntünün çalışma dizinine kopyaladık. Bu bizim cypress Docker Compose hizmetimiz tarafından kullanılacaktı ve Dockerfile kurulumunu şu şekilde gerçekleştirdik:

Bu Dockerfile.cypress ile, seçilen özellikleri belirli bir ortam API'sine ve dağıtılan uygulamaya karşı cypress adlı bir Docker Compose hizmeti aracılığıyla çalıştırmak için Cypress'i entegre edebiliriz. Tek yapmamız gereken, npm run cypress:run:cicd:staging komutu aracılığıyla seçili Cypress testlerini belirli bir temel URL'ye karşı çalıştırmak için SPECS ve BASE_URL gibi bazı ortam değişkenlerini enterpolasyon yapmaktı, ”cypress:run:cicd:staging”: “cypress run --record --key --config baseUrl=$BASE_URL --env testEnv=staging” .

Bu ortam değişkenleri, Buildkite ardışık düzeninin ayarlar/yapılandırma dosyaları aracılığıyla ayarlanır veya dağıtım hattımızdan çalıştırılacak Cypress testleri tetiklendiğinde dinamik olarak dışa aktarılır. Örnek bir docker-compose.cypress.yml dosyası şuna benziyordu:

Ayrıca gözlemlenmesi gereken birkaç şey daha var. Örneğin, belirli bir etiketli Docker görüntüsüne başvurmamıza izin veren VERSION ortam değişkenini görebilirsiniz. Daha sonra bir Docker görüntüsünü nasıl etiketlediğimizi göstereceğiz ve ardından o derleme için aynı Docker görüntüsünü Cypress testleri için doğru koda karşı çalıştırmak üzere aşağı çekeceğiz.

Ayrıca, başlattığımız her derleme için diğer Buildkite ortam değişkenleriyle birlikte ücretsiz olarak gelen BUILDKITE_BUILD_ID ve ci-build-id bayrağının geçtiğini de fark edeceksiniz. Bu, Cypress'in paralelleştirme özelliğini etkinleştirir ve Cypress testleri için belirli sayıda makine tahsis ettiğimizde, otomatik olarak sihirli bir şekilde bu makinelerin nasıl döndürüleceğini bilecek ve testlerimizi optimize etmek ve hızlandırmak için tüm bu makine düğümlerinde çalışacak şekilde ayıracaktır. çalışma süreleri.

Sonunda ayrıca hacim montajından ve Buildkite'ın eserler özelliğinden de faydalandık. Ay için ücretli tahsisli test kayıtlarımız biterse veya bir şekilde Gösterge Tablosu Hizmetine erişemezsek, Buildkite UI "Yapılar" sekmesinden doğrudan erişilebilecek videoları ve ekran görüntülerini yüklüyoruz. Cypress “run” komutu başsız modda çalıştırıldığında, cypress/videos ve cypress/screenshots klasörlerinde birinin yerel olarak gözden geçirmesi için çıktılar olur ve biz sadece bu klasörleri monte eder ve bizim için güvenli bir şekilde Buildkite'a yükleriz.

Adım 5: CICD ile Entegrasyon

Cypress testlerinin bir Docker kapsayıcısında farklı ortamlarda başarılı bir şekilde çalışmasını sağladıktan sonra, CICD sağlayıcımız Buildkite ile entegrasyona başladık. Buildkite, AWS makinelerimizdeki bir .yml dosyasındaki adımları, kodda veya web kullanıcı arayüzündeki deponun Buildkite ardışık düzeni ayarları aracılığıyla ayarlanmış Bash komut dosyaları ve ortam değişkenleriyle yürütmenin yollarını sağladı. Buildkite ayrıca, dışa aktarılan ortam değişkenleriyle ana dağıtım hattımızdan bu test hattını tetiklememize izin verdi ve bu test adımlarını, QA'larımızın izlemesi ve bakması için bir programda çalışacak diğer izole test boru hatları için yeniden kullanırdık.

Yüksek düzeyde, Cypress için test Buildkite işlem hatlarımız ve ayrıca önceki WebdriverIO işlem hatlarımız aşağıdaki benzer adımları paylaştı:

  • Docker görüntülerini ayarlayın . Testler için gereken Docker görüntülerini derleyin, etiketleyin ve daha sonraki bir adımda indirebilmemiz için kayıt defterine iletin.
  • Ortam değişkeni yapılandırmalarına dayalı testleri çalıştırın . Belirli yapı için etiketli Docker görüntülerini aşağı çekin ve ayarlanmış ortam değişkenlerinden seçilen test takımlarını çalıştırmak için konuşlandırılmış bir ortama karşı uygun komutları yürütün.

"Cypress Docker Görüntüsü Oluştur" adımında Docker görüntülerini ayarlamayı ve "Cypress testlerini çalıştır" adımında testleri çalıştırmayı gösteren bir pipeline.cypress.yml dosyası örneği:

Dikkat edilmesi gereken bir şey, ilk adım olan “Cypress Docker Görüntüsü Oluştur” ve test için Docker görüntüsünü nasıl kurduğudur. Tüm uygulama test koduyla cypress hizmetini oluşturmak için Docker Compose build komutunu kullandı ve onu en latest ve ${VERSION} ortam değişkeniyle etiketledi, böylece aynı görüntüyü bu yapı için uygun etiketle bir gelecekteki adım. Her adım, AWS bulutunda bir yerde farklı bir makinede yürütülebilir, bu nedenle etiketler, belirli Buildkite çalışması için görüntüyü benzersiz şekilde tanımlar. Görüntüyü etiketledikten sonra, yeniden kullanılmak üzere en son ve sürüm etiketli görüntüyü özel Docker kayıt defterimize yükledik.

“Cypress testlerini çalıştır” adımında, ilk adımda oluşturduğumuz, etiketlediğimiz ve ittiğimiz imajı aşağı çekiyoruz ve testleri gerçekleştirmek için Cypress servisini başlatıyoruz. SPECS ve BASE_URL gibi ortam değişkenlerine dayanarak, bu belirli Buildkite derlemesi için belirli bir dağıtılmış uygulama ortamına karşı belirli test dosyaları çalıştırırdık. Bu ortam değişkenleri, Buildkite ardışık düzen ayarları aracılığıyla belirlenir veya hangi test takımlarının hangi ortama karşı çalıştırılacağını belirlemek için bir Buildkite seçim alanını ayrıştıran bir Bash betiğinden dinamik olarak tetiklenir.

Buildkite CICD dağıtım hattımız sırasında hangi testlerin çalıştırılacağını seçtiğimizde ve belirli dışa aktarılan ortam değişkenleriyle özel bir tetiklenmiş testler ardışık düzenini tetiklediğimizde, bunun gerçekleşmesi için pipeline.cypress.yml hattı.cypress.yml dosyasındaki adımları izleriz. Dağıtım hattından bir özellik dal ortamına bazı yeni kodlar dağıttıktan sonra testleri tetiklemeye bir örnek şuna benzer:

Tetiklenen testler ayrı bir ardışık düzende çalışır ve “Derleme #639” bağlantısını takip ettikten sonra, bizi aşağıdaki gibi tetiklenen test çalıştırması için derleme adımlarına götürür:

Bir programa göre çalışan özel Cypress Buildkite ardışık düzenlerimiz için aynı pipeline.cypress.yml hattı.cypress.yml dosyasını yeniden kullanarak, aşağıdaki fotoğrafta gösterildiği gibi, en yüksek öncelikli E2E testlerimiz olan "P1"imizi çalıştıran derlemelere sahibiz:

Tek yapmamız gereken, Buildkite boru hattının ayarlarında hangi özelliklerin çalıştırılacağı ve hangi arka uç ortamına ulaşılacağı gibi şeyler için uygun ortam değişkenlerini ayarlamaktır. Ardından, işlem hattı ayarlarında da bulunan bir Cron zamanlanmış derlemesini belirli saatlerde başlayacak şekilde yapılandırabiliriz ve artık hazırız. We would then create many other separate pipelines for specific feature pages as needed to run on a schedule in a similar way and we would only vary the Cron schedule and environment variables while once again uploading the same `pipeline.cypress.yml` file to execute.

In each of those “Run Cypress tests” steps, we can see the console output with a link to the recorded test run in the paid Dashboard Service, the central place to manage your team's test recordings, billing, and other Cypress stats. Following the Dashboard Service link would take us to a results view for developers and QAs to take a look at the console output, screenshots, video recordings, and other metadata if required such as this:

Step 6: Comparing Cypress vs. WebdriverIO/STUI

After diving into our own custom Ruby Selenium solution in STUI, WebdriverIO, and finally Cypress tests, we recorded our tradeoffs between Cypress and Selenium wrapper solutions.

Artıları

  • It's not another Selenium wrapper – Our previous solutions came with a lot of Selenium quirks, bugs, and crashes to work around and resolve, whereas Cypress arrived without the same baggage and troubles to deal with in allowing us full access to the browser.
  • More resilient selectors – We no longer had to explicitly wait for everything like in WebdriverIO with all the $(.selector).waitForVisible() calls and now rely on cy.get(...) and c y.contains(...) commands with their default timeout. It will automatically keep on retrying to retrieve the DOM elements and if the test demanded a longer timeout, it is also configurable per command. With less worrying about the waiting logic, our tests became way more readable and easier to chain.
  • Vastly improved developer experience – Cypress provides a large toolkit with better and more extensive documentation for assertions, commands, and setup. We loved the options of using the Cypress GUI, running in headless mode, executing in the command-line, and chaining more intuitive Cypress commands.
  • Significantly better developer efficiency and debugging – When running the Cypress GUI, one has access to all of the browser console to see some helpful output, time travel debug and pause at certain commands in the command log to see before and after screenshots, inspect the DOM with the selector playground, and discern right away at which command the test failed. In WebdriverIO or STUI we struggled with observing the tests run over and over in a browser and then the console errors would not point us toward and would sometimes even lead us astray from where the test really failed in the code. When we opted to run the Cypress tests in headless mode, we got console errors, screenshots, and video recordings. With WebdriverIO we only had some screenshots and confusing console errors. These benefits resulted in us cranking out E2E tests much faster and with less overall time spent wondering why things went wrong. We recorded it took less developers and often around 2 to 3 times less days to write the same level of complicated tests with Cypress than with WebdriverIO or STUI.
  • Network stubbing and mocking – With WebdriverIO or STUI, there was no such thing as network stubbing or mocking in comparison to Cypress. Now we can have endpoints return certain values or we can wait for certain endpoints to finish through cy.server() and cy.route() .
  • Less time to set up locally – With WebdriverIO or STUI, there was a lot of time spent up front researching which reporters, test runners, assertions, and services to use, but with Cypress, it came bundled with everything and started working after just doing an npm install cypress.
  • Less time to set up with Docker – There are a bunch of ways to set up WebdriverIO with Selenium, browser, and application images that took us considerably more time and frustration to figure out in comparison to Cypress's Docker images to use right out of the gate.
  • Parallelization with various CICD providers – We were able to configure our Buildkite pipelines to spin up a certain number of AWS machines to run our Cypress tests in parallel to dramatically speed up the overall test run time and uncover any flakiness in tests using the same resources. The Dashboard Service would also recommend to us the optimal number of machines to spin up in parallel for the best test run times.
  • Paid Dashboard Service – When we run our Cypress tests in a Docker container in a Buildkite pipeline during CICD, our tests are recorded and stored for us to look at within the past month through a paid Dashboard Service. We have a parent organization for billing and separate projects for each frontend application to check out console output, screenshots, and recordings of all of our test runs.
  • Tests are way more consistent and maintainable – Tests passed way more consistently with Cypress in comparison to WebdriverIO and STUI where the tests kept on failing so much to the point where they were often ignored. Cypress tests failing more often signaled actual issues and bugs to look into or suggested better ways to refactor our tests to be less flaky. With WebdriverIO and STUI, we wasted a lot more time in maintaining those tests to be somewhat useful, whereas with Cypress, we would every now and then adjust the tests in response to changes in the backend services or minor changes in the UI.
  • Tests are faster – Builds passed way more consistently and overall test run times would be around 2 to 3 times faster when run serially without parallelization. We used to have overall test runs that would take hours with STUI and around 40 minutes with WebdriverIO, but now with way more tests and with the help of parallelization across many machine nodes, we can run over 200 tests in under 5 minutes .
  • Room to grow with added features in the future – With a steady open-source presence and dedicated Cypress team working towards releasing way more features and improvements to the Cypress infrastructure, we viewed Cypress as a safer bet to invest in rather than STUI, which would require us to engineer and solve a lot of the headaches ourselves, and WebdriverIO, which appeared to feel more stagnant in new features added but with the same baggage as other Selenium wrappers.

Eksileri

  • Lack of cross-browser support – As of this writing, we can only run our tests against Chrome. With WebdriverIO, we could run tests against Chrome, Firefox, Safari, and Opera. STUI also provided some cross-browser testing, though in a much limited form since we created a custom in-house solution
  • Cannot integrate with some third-party services – With WebdriverIO, we had the option to integrate with services like BrowserStack and Sauce Labs for cross-browser and device testing. However, with Cypress there are no such third-party integrations but there are some plugins with services like Applitools for visual regression testing available. STUI, on the other hand, also had some small integrations with TestRail , but as a compromise, we log out the TestRail links in our Cypress tests so we can refer back to them if we needed to.
  • Requires workarounds to test with iframes – There are some issues around handling iframes with Cypress. We ended up creating a global Cypress command to wrap how to deal with retrieving an iframe's contents as there is no specific API to deal with iframes like how WebdriverIO does.

To summarize our STUI, WebdriverIO, and Cypress comparison, we analyzed the overall developer experience (related to tools, writing tests, debugging, API, documentation, etc.), test run times, test passing rates, and maintenance as displayed in this table:

Following our analysis of the pros and cons of Cypress versus our previous solutions, it was pretty clear Cypress would be our best bet to accomplish our goal of writing fast, valuable, maintainable, and debuggable E2E tests we could integrate with CICD.

Though Cypress lacked features such as cross-browser testing and other integrations with third-party services that we could have had with STUI or WebdriverIO, we most importantly need tests that work more often than not and with the right tools to confidently fix broken ones. If we ever needed cross-browser testing or other integrations we could always still circle back and use our knowledge from our trials and experiences with WebdriverIO and STUI to still run a subset of tests with those frameworks.

We finally presented our findings to the rest of the frontend organization, engineering management, architects, and product. Upon demoing the Cypress test tools and showcasing our results between WebdriverIO/STUI and Cypress, we eventually received approval to standardize and adopt Cypress as our E2E testing library of choice for our frontend teams.

Step 7: Scaling to Other Frontend Teams

After successfully proving that using Cypress was the way to go for our use cases, we then focused on scaling it across all of our frontend teams' repos. We shared lessons learned and patterns of how to get up and running, how to write consistent, maintainable Cypress tests, and of how to hook those tests up during CICD or in scheduled Cypress Buildkite pipelines.

To promote greater visibility of test runs and gain access to a private monthly history of recordings, we established our own organization to be under one billing method to pay for the Dashboard Service with a certain recorded test run limit and maximum number of users in the organization to suit our needs.

Once we set up an umbrella organization, we invited developers and QAs from different frontend teams and each team would install Cypress, open up the Cypress GUI, and inspect the “Runs” and “Settings” tab to get the “Project ID” to place in their `cypress.json` configuration and “Record Key” to provide in their command options to start recording tests to the Dashboard Service. Finally, upon successfully setting up the project and recording tests to the Dashboard Service for the first time, logging into the Dashboard Service would show that team's repo under the “Projects” tab like this:

When we clicked a project like “mako”, we then had access to all of the test runs for that team's repo with quick access to console output, screenshots, and video recordings per test run upon clicking each row as shown below:

For more insights into our integration, we set up many separate dedicated test pipelines to run specific, crucial page tests on a schedule like say every couple hours to once per day. We also added functionality in our main Buildkite CICD deploy pipeline to select and trigger some tests against our feature branch environment and staging environment.

Tahmin edilebileceği gibi, bu, özellikle çeşitli şekillerde katkıda bulunan ve testleri tetikleyen birden fazla ekip olduğu için, ay için tahsis edilen kayıtlı test çalışmalarımızı hızla patlattı. Deneyimlerimizden yola çıkarak, bir programda kaç testin yürütüldüğüne, bu testlerin ne sıklıkta çalıştırıldığına ve CICD sırasında hangi testlerin yürütüldüğüne dikkat etmenizi öneririz. Planlanmış test çalıştırmalarının sıklığını geri çevirmek veya yalnızca CICD sırasında testleri tetiklemek için muhtemelen bazılarından tamamen kurtulmak gibi bazı gereksiz test çalıştırmaları ve daha tutumlu olması gereken diğer alanlar olabilir.

Tutumlu olmanın aynı kuralı, bu sınırlı noktaları doldurmak için üst yönetim ve bu ekiplerin dışındaki diğer kişiler yerine Dashboard Hizmetini yoğun olarak kullanacak olan ön uç ekiplerdeki geliştiricilere ve QA'lara erişim sağlamayı vurguladığımız gibi, kullanıcı eklemek için de geçerlidir.

Cypress ile sabırsızlıkla beklediğimiz şey

Daha önce de belirttiğimiz gibi, Cypress, açık kaynak topluluğunda ve E2E testlerimizde kullanmamız için daha yararlı özellikler sunmaktan sorumlu özel ekibiyle çok fazla umut ve büyüme potansiyeli gösterdi. Vurguladığımız birçok olumsuzluk şu anda ele alınıyor ve aşağıdakiler gibi şeyleri sabırsızlıkla bekliyoruz:

  • Çapraz tarayıcı desteği - Bu büyük bir destek, çünkü Cypress'i benimsememizden gelen tepkilerin çoğu, Firefox, Chrome ve Safari gibi tarayıcıları destekleyen Selenium tabanlı çözümlere kıyasla yalnızca Chrome'u kullanmasından geldi. Neyse ki, daha güvenilir, bakımı kolay ve hata ayıklanabilir testler kuruluşumuz için kazandı ve gelecekte Cypress ekibi bu tür tarayıcılar arası desteği yayınladığında test takımlarımızı daha fazla tarayıcılar arası testlerle güçlendirmeyi umuyoruz.
  • Ağ katmanı yeniden yazma – Fetch API'yi daha yeni React alanlarımızda yoğun olarak kullanma eğiliminde olduğumuzdan ve daha eski Backbone/Marionette uygulama alanlarında hala jQuery AJAX ve normal XHR tabanlı çağrıları kullandığımızdan, bu aynı zamanda çok büyük. XHR alanlarındaki istekleri kolayca saplayabilir veya dinleyebiliriz, ancak aynı etkiyi elde etmek için çoklu dolguları getirme ile bazı geçici çözümler yapmak zorunda kaldık. Ağ katmanı yeniden yazmanın bu acıları hafifletmeye yardımcı olması gerekiyor.
  • Gösterge Tablosu Hizmetinde artımlı iyileştirmeler – Son zamanlarda Gösterge Tablosu Hizmetinde bazı yeni UI değişiklikleri gördük ve daha fazla istatistik görselleştirmesi ve faydalı verilerin dökümü ile büyümeye devam etmeyi umuyoruz. Ayrıca paralelleştirme özelliğini yoğun bir şekilde kullanıyoruz ve Kontrol Paneli Hizmetindeki başarısız test kayıtlarımızı sık sık kontrol ediyoruz, bu nedenle düzende ve/veya özelliklerde yinelemeli iyileştirmeler görmek güzel olurdu.

Cypress'i Geleceğe Sahiplenmek

Kuruluşumuz için, Chrome tarayıcısı altında çalıştırıldığında Cypress testlerinin geliştirici verimliliğine, hata ayıklamasına ve kararlılığına değer verdik. Yolda daha az bakım gerektiren ve yeni testler geliştirmek ve mevcut testleri düzeltmek için birçok araçla tutarlı, değerli testler gerçekleştirdik.

Genel olarak, elimizdeki belgeler, API ve araçlar, herhangi bir dezavantajdan çok daha ağır bastı. Cypress GUI ve ücretli Dashboard Service'i deneyimledikten sonra kesinlikle WebdriverIO'ya veya özel Ruby Selenium çözümümüze geri dönmek istemedik.

Testlerimizi Buildkite ile bağladık ve ön uç uygulamalarımızın CICD ile entegre olması için tutarlı, hata ayıklanabilir, bakımı yapılabilir ve değerli E2E otomasyon testleri yazmanın bir yolunu sağlama hedefimize ulaştık. Cypress'i benimsemenin ve WebdriverIO ve STUI'yi bırakmanın yararlarını ön uç ekiplerinin geri kalanına, mühendislik üstlerine ve ürün sahiplerine kanıtlarla kanıtladık.

Twilio SendGrid'deki ön uç ekipler arasında yüzlerce test daha sonra yapıldı ve hazırlama ortamımızda birçok hata yakaladık ve her zamankinden çok daha fazla güvenle tarafımızdaki kesintili testleri hızlı bir şekilde düzeltebildik. Geliştiriciler ve QA'lar artık E2E testleri yazma düşüncesinden korkmuyorlar, ancak şimdi yayınladığımız her yeni özellik için veya biraz daha fazla kapsam kullanabilecek her eski özellik için bunları yazmayı dört gözle bekliyorlar.