Büyük bir Rails uygulamasında RSpec testlerini hızlandırma


91

RSpec testlerimde 2.000'den fazla örnek içeren bir Rails uygulamam var. Söylemeye gerek yok, bu büyük bir uygulama ve test edilecek çok şey var. Bu testleri bu noktada çalıştırmak çok verimsizdir ve çok uzun sürdüğü için, yeni bir yapıya geçmeden önce bunları yazmaktan neredeyse vazgeçme noktasındayız. En uzun süre çalışan örnekleri bulmak için spec.opts'a --profile ekledim ve bunların çalıştırılması ortalama 10 saniye süren en az 10 tanesi var. Siz RSpec uzmanları arasında bu normal mi? Bir örnek için 10 saniye tamamen çok mu uzun? 2000 örnekle, her şeyi kapsamlı bir şekilde test etmenin önemsiz olmayan bir zaman alacağının farkındayım - ancak bu noktada 4 saat biraz saçma.

En uzun soluklu örnekleriniz için ne tür zamanlar görüyorsunuz? Darboğazları bulmak ve işleri hızlandırmak için mevcut özelliklerimdeki sorunları gidermek için ne yapabilirim? Bu noktada her dakika gerçekten yardımcı olacaktır.


1
Yavaş testler entegrasyon testleri mi? Bir db mi vuruyorlar? Öyleyse, db ne sıklıkla yeniden yükleniyor ve db ile dalga geçebilir misiniz?
Kaleb Pederson

1
SeattleRB'nin otomatik testine benzer şekilde, üzerinde çalıştığınız bölümle ilgili spesifikasyonların bir kısmını çalıştırabiliyor musunuz? Tüm testleri çalıştırabilen sürekli bir entegrasyon sunucunuz var mı?
Andrew Grimm

Her şeyin göreceli olduğunu da unutmayın. "Grrr, test süitimiz sonsuza kadar sürer" duydum hem 20 dakika hem de 16-20 saat. Hepsi bakanın gözünde. Belirli bir test için 10 saniye, genellikle aşağıda belirtildiği gibi bir entegrasyon testi haline gelen bir birim testi anlamına gelir.
Michael Durrant

Bu tür bir sorun için bir öneri: perftools.rbZamanınızın çoğunu neyin tükettiğini anlamak için test çerçevenizle birlikte kullanın . İlk 10 aramayı alın ve onları ortadan kaldırmaya / gözden geçirmeye çalışın. Sonra mutlu olana kadar tekrarlayın.
aledalgrande

Yanıtlar:


118

10 saniye, tek bir testin çalışması için çok uzun bir süredir. İçimden gelen his, spesifikasyon hedefinizin aynı anda hem birim hem de entegrasyon testleri çalıştırmasıdır. Bu, projelerin içine düştüğü tipik bir şeydir ve bir aşamada, daha fazlasını, daha hızlı üretmek istiyorsanız bu teknik borcun üstesinden gelmeniz gerekecektir . Bunu yapmanıza yardımcı olabilecek birkaç strateji var ... ve geçmişte kullandığım birkaçını önereceğim.

1. Entegrasyon Testlerinden Üniteyi Ayırın

Yapacağım ilk şey, birimi entegrasyon testlerinden ayırmaktır. Bunu şu şekilde yapabilirsiniz:

  1. Bunları taşıma (spesifikasyon dizini altındaki ayrı klasörlere) - ve tırmık hedeflerini değiştirme
  2. Bunları etiketleme (rspec, testlerinizi etiketlemenize izin verir)

Felsefe, normal yapılarınızın hızlı olmasını istemenizdir - aksi takdirde insanlar onları sık sık çalıştırmaktan çok mutlu olmayacaktır. Öyleyse o bölgeye geri dönün. Hızlı çalıştırmak için düzenli testlerinizi alın ve daha eksiksiz bir yapı çalıştırmak için sürekli bir tümleştirme sunucusu kullanın.

Entegrasyon testi, harici bağımlılıkları içeren bir testtir (örn. Veritabanı, Web Hizmeti, Kuyruk ve bazıları FileSystem'i tartışabilir). Bir birim testi, yalnızca kontrol edilmesini istediğiniz belirli kod öğesini test eder. Hızlı çalışmalıdır (45 saniyede 9000 mümkündür), yani çoğu bellekte çalışmalıdır.

2. Entegrasyon Testlerini Birim Testlerine Dönüştür

Birim testlerinizin çoğu entegrasyon test paketinizden daha küçükse, bir sorununuz var demektir. Bunun anlamı, tutarsızlıkların daha kolay ortaya çıkmaya başlayacağıdır. Yani buradan, entegrasyon testlerini değiştirmek için daha fazla birim testi oluşturmaya başlayın. Bu süreçte yardımcı olmak için yapabileceğiniz şeyler şunlardır:

  1. Gerçek kaynak yerine alaycı bir çerçeve kullanın. Rspec, yerleşik bir alay çerçevesine sahiptir.
  2. Rcov'u birim test süitinizde çalıştırın. Bunu, birim test süitinizin ne kadar kapsamlı olduğunu ölçmek için kullanın.

Bir entegrasyon testini değiştirmek için uygun bir birim testiniz olduğunda - entegrasyon testini kaldırın. Yinelenen test, yalnızca bakımı daha da kötüleştirir.

3. Fikstür Kullanmayın

Fikstür kötüdür. Bunun yerine bir fabrika kullanın (makinist veya fabrika botu). Bu sistemler, daha uyarlanabilir veri grafikleri oluşturabilir ve daha da önemlisi, harici bir veri kaynağından bir şeyler yüklemek yerine kullanabileceğiniz bellek içi nesneler oluşturabilirler.

4. Entegrasyon Testlerine Dönüşen Ünite Testlerini Durdurmak İçin Kontroller Ekleyin

Artık daha hızlı test uyguladığınıza göre, bunun tekrar olmasını DURDURMAK için kontroller koymanın zamanı geldi.

Veritabanına (UnitRecord) erişmeye çalışırken bir hata atmak için aktif kaydı yama yapan kütüphaneler vardır.

Ekibinizi daha hızlı testler yazmaya zorlamaya yardımcı olabilecek eşleştirme ve TDD'yi de deneyebilirsiniz, çünkü:

  1. Biri kontrol ediyor - bu yüzden kimse tembelleşmiyor
  2. Uygun TDD, hızlı geri bildirim gerektirir. Yavaş testler her şeyi acı verici hale getirir.

5. Sorunun Üstesinden Gelmek İçin Diğer Kitaplıkları Kullanın

Biri spork'ten (raylar altındaki test takımı için yükleme sürelerini hızlandırır3), hydra / parallel_tests - birim testlerini paralel olarak (birden çok çekirdekte) çalıştırmak için bahsetti.

Bu muhtemelen SON kullanılmalıdır. Asıl sorununuz 1., 2., 3. adımlarla ilgilidir. Bunu çözerseniz, ek altyapıyı devreye almak için daha iyi bir konumda olacaksınız.


Mükemmel cevap. Hiçbir gelişmiş aracın kötü testlerin hızlı bir şekilde yapılmasına yardımcı olamayacağı çok doğrudur. Bu yüzden sadece iyi olanları yazmayı deneyin.
Yura Omelchuk

5
Demirbaş kullanmamanız gerektiği konusunda üçüncü fikrinize katılmıyorum. Düzgün kullanılırsa, nesneler oluşturmak zorunda kalmadığınız için fabrikalardan daha hızlıdırlar. Verileriniz oradadır, her test senaryosunda oluşturmanız gerekmez.
wallerjake

3
Fabrikaların daha hızlı olması bir şaka değil mi?
Mike Szyndel

Factory
Girl'den

16

Test süitinizin performansını artırmayla ilgili harika bir yemek kitabı için, Süitinizi Gresleyin sunumuna bakın.

Aşağıdakiler gibi teknikleri kullanarak test paketi çalışma süresinde 45 kat hızlanma olduğunu belgeliyor:


Bağlantıları beğendim ama sunumu beğenmedim. Birinin konuşması için dizin kartları, konuşmacının sunumun etini doldurması için bir uyarıdır.
Brian Maltzan

Bu sunum artık bitmiyor. fast_context birden fazla gereken bloğu hızlandırır. quickerclip (bu bağlantı da ölüdür) görünüşte Ataç'ı hızlandırır. Hydra, paralel testler ve Gorgon için kullanımdan kaldırıldı. bootsnap dosya sistemi ayarlarına sahiptir ve artık Rails'e dahil edilmiştir. Ruby'nin son sürümlerinde gelişmiş ayırma ve GC var.
rep

5

Spork'ü kullanabilirsiniz. 2.3.x desteği vardır,

https://github.com/sporkrb/spork

veya 2.x için çalışabilen ./script/spec_server

Ayrıca, veritabanı yapılandırmasını düzenleyebilirsiniz (bu, veritabanı sorgularını hızlandırır vb.), Bu da testler için performansı artıracaktır.


Spork harika. Ayrıca biraz hack ile Rails 3 üzerinde de çalışır. Ancak Spork on Rails 3 ile dikkat edilmesi gereken bir şey, denetleyicilerdeki değişiklikleri almıyor gibi görünmesidir, bu nedenle sık sık yeniden başlatmanız gerekir. Ama her neyse, Spork gerçekten harika, testlerin hız artışı çok önemli.
AboutRuby

4
Spork, testleri değil, yalnızca başlatmayı hızlandırmak içindir. Bu yüzden birçok özellik ile avantaj önemsizdir.
Reactormonk

Yukarıdaki yorumların aksine spork, railscast railscasts.com/episodes/285-spork uyarınca testleri ve başlatmayı hızlandırmak için kullanılabilir . Çok büyük bir uygulamada rspec test paketimi büyük ölçüde geliştirdim. (192 saniyeden 10 saniyeye
düşürüldü

3

Örnek başına 10 saniye çok uzun bir süre gibi görünüyor. Bir saniyeden fazla süren ve çoğu çok daha az süren bir özellik görmedim. Ağ bağlantılarını test ediyor musunuz? Veritabanı yazıyor mu? Dosya sistemi yazıyor mu?

Mümkün olduğunca taklitler ve taslaklar kullanın - bunlar veritabanına isabet eden kod yazmaktan çok daha hızlıdır. Maalesef, alay ve anlatma da yazmak için daha fazla zaman alıyor (ve doğru şekilde yapmak daha zor). Test yazmak için harcanan zaman ile testleri yapmak için harcanan zamanı dengelemelisiniz.

Andrew Grimm'in test paketinizi paralel hale getirmenize izin verebilecek bir CI sistemine bakma konusundaki yorumunu ikinci kez düşünüyorum. Bu büyüklükte bir şey için geçerli tek çözüm bu olabilir.


evet 10 saniye ise profilini
çıkarır

1
Büyük bir projem var ve tek bir rspec testi yapmak yaklaşık 15-20 saniye sürüyor.
2013





-4

Mevcut test paketini silin. İnanılmaz derecede etkili olacak.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.