เร่งการทดสอบ RSpec ในแอปพลิเคชัน Rails ขนาดใหญ่


91

ฉันมีแอปพลิเคชัน Rails ที่มีตัวอย่างมากกว่า 2,000 ตัวอย่างในการทดสอบ RSpec ของฉัน ไม่จำเป็นต้องพูดว่ามันเป็นแอปพลิเคชั่นขนาดใหญ่และมีอะไรให้ทดสอบมากมาย การเรียกใช้การทดสอบเหล่านี้ ณ จุดนี้ไม่มีประสิทธิภาพมากและเนื่องจากใช้เวลานานมากเราจึงเกือบจะหมดกำลังใจที่จะเขียนก่อนที่จะผลักดันงานสร้างใหม่ ฉันเพิ่ม - profile ใน spec.opts ของฉันเพื่อค้นหาตัวอย่างที่ทำงานได้ยาวนานที่สุดและมีอย่างน้อย 10 ตัวที่ใช้เวลาโดยเฉลี่ย 10 วินาทีในการรัน เป็นเรื่องปกติในหมู่ผู้เชี่ยวชาญ RSpec หรือไม่? 10 วินาทีนานเกินไปสำหรับตัวอย่างเดียวหรือไม่ ฉันตระหนักดีว่าด้วยตัวอย่าง 2,000 ตัวอย่างการทดสอบทุกอย่างอย่างละเอียดจะต้องใช้เวลาไม่น้อย แต่ ณ จุดนี้ 4 ชั่วโมงเป็นเรื่องที่น่าหัวเราะเล็กน้อย

คุณเห็นช่วงเวลาแบบใดสำหรับตัวอย่างที่ทำงานยาวนานที่สุด ฉันจะทำอย่างไรเพื่อแก้ปัญหาข้อกำหนดที่มีอยู่เพื่อหาปัญหาคอขวดและช่วยเร่งความเร็ว ทุกนาทีจะช่วยในจุดนี้ได้จริงๆ


1
การทดสอบการรวมการทดสอบช้าหรือไม่ พวกเขากดปุ่ม db หรือไม่? ถ้าเป็นเช่นนั้น db ถูกโหลดซ้ำบ่อยแค่ไหนและคุณสามารถล้อเลียน db ได้หรือไม่?
Kaleb Pederson

1
คุณสามารถเรียกใช้ข้อมูลจำเพาะบางส่วนที่เกี่ยวข้องกับส่วนที่คุณกำลังทำงานอยู่ซึ่งคล้ายกับการทดสอบอัตโนมัติของ SeattleRB หรือไม่? คุณมีเซิร์ฟเวอร์การรวมแบบต่อเนื่องที่สามารถรันการทดสอบทั้งหมดหรือไม่
Andrew Grimm

จำไว้ด้วยว่าทุกสิ่งสัมพันธ์กัน ฉันเคยได้ยินว่า "grrr ชุดทดสอบของเราใช้เวลาตลอดไป" ทั้ง 20 นาที ... และ 16-20 ชั่วโมง ทุกอย่างอยู่ในสายตาของผู้มอง 10 วินาทีสำหรับการทดสอบหนึ่ง ๆ มักหมายถึงการทดสอบหน่วยที่กลายเป็นการทดสอบการรวมตามที่กล่าวไว้ด้านล่าง
Michael Durrant

ข้อเสนอแนะสำหรับปัญหาประเภทนี้: ใช้perftools.rbร่วมกับกรอบการทดสอบของคุณเพื่อทำความเข้าใจกับสิ่งที่ใช้เวลาส่วนใหญ่ รับสาย 10 อันดับแรกและพยายามกำจัด / อ่านรายละเอียด จากนั้นทำซ้ำจนกว่าจะมีความสุข
aledalgrande

คำตอบ:


118

10 วินาทีเป็นเวลาที่ยาวนานมากสำหรับการทดสอบเพียงครั้งเดียว ความรู้สึกของฉันคือเป้าหมายข้อมูลจำเพาะของคุณกำลังเรียกใช้การทดสอบทั้งหน่วยและการรวมในเวลาเดียวกัน นี่เป็นเรื่องปกติที่โครงการจะตกอยู่ในและในบางขั้นตอนคุณจะต้องเอาชนะหนี้ทางเทคนิคนี้หากคุณต้องการผลิตมากขึ้นเร็วขึ้น มีกลยุทธ์หลายอย่างที่ช่วยให้คุณทำสิ่งนี้ได้ ... และฉันจะแนะนำบางส่วนที่ฉันเคยใช้ในอดีต

1. แยกหน่วยจากการทดสอบการรวม

สิ่งแรกที่ฉันจะทำคือแยกหน่วยออกจากการทดสอบการรวม คุณสามารถทำได้โดย:

  1. การย้าย (ลงในโฟลเดอร์แยกต่างหากภายใต้ไดเร็กทอรีข้อมูลจำเพาะ) - และการปรับเปลี่ยนเป้าหมายคราด
  2. การติดแท็ก (rspec ช่วยให้คุณสามารถติดแท็กการทดสอบของคุณ)

ปรัชญากล่าวว่าคุณต้องการให้งานสร้างปกติของคุณเป็นไปอย่างรวดเร็วมิฉะนั้นผู้คนจะไม่พอใจที่จะเรียกใช้บ่อยๆ ดังนั้นกลับไปที่ดินแดนนั้น รับการทดสอบปกติของคุณเพื่อรันอย่างรวดเร็วและใช้เซิร์ฟเวอร์การรวมแบบต่อเนื่องเพื่อรันบิลด์ที่สมบูรณ์ยิ่งขึ้น

การทดสอบการรวมคือการทดสอบที่เกี่ยวข้องกับการอ้างอิงภายนอก (เช่นฐานข้อมูล, WebService, คิวและบางส่วนอาจโต้แย้ง FileSystem) การทดสอบหน่วยจะเป็นการทดสอบรายการรหัสเฉพาะที่คุณต้องการตรวจสอบ ควรทำงานเร็ว (9000 ใน 45 วินาทีเป็นไปได้) กล่าวคือส่วนใหญ่ควรทำงานในหน่วยความจำ

2. แปลงการทดสอบการรวมเป็นการทดสอบหน่วย

หากการทดสอบหน่วยจำนวนมากของคุณมีขนาดเล็กกว่าชุดทดสอบการรวมระบบแสดงว่าคุณมีปัญหา สิ่งนี้หมายความว่าความไม่สอดคล้องกันจะเริ่มปรากฏได้ง่ายขึ้น จากตรงนี้ให้เริ่มสร้างการทดสอบหน่วยเพิ่มเติมเพื่อแทนที่การทดสอบการรวม สิ่งที่คุณสามารถทำได้เพื่อช่วยในกระบวนการนี้ ได้แก่

  1. ใช้กรอบการเยาะเย้ยแทนทรัพยากรจริง Rspec มีกรอบการเยาะเย้ยในตัว
  2. เรียกใช้ rcov บนชุดทดสอบหน่วยของคุณ ใช้เพื่อวัดว่าชุดทดสอบหน่วยของคุณละเอียดเพียงใด

เมื่อคุณมีการทดสอบหน่วยที่เหมาะสมเพื่อแทนที่การทดสอบการรวม - ลบการทดสอบการรวม การทดสอบซ้ำจะทำให้การบำรุงรักษาแย่ลงเท่านั้น

3. อย่าใช้อุปกรณ์ติดตั้ง

การแข่งขันเป็นสิ่งชั่วร้าย ใช้โรงงานแทน (ช่างเครื่องหรือ Factorybot) ระบบเหล่านี้สามารถสร้างกราฟข้อมูลที่ปรับเปลี่ยนได้มากขึ้นและที่สำคัญกว่านั้นคือสามารถสร้างออบเจ็กต์ในหน่วยความจำที่คุณสามารถใช้ได้แทนที่จะโหลดสิ่งต่างๆจากแหล่งข้อมูลภายนอก

4. เพิ่มการตรวจสอบเพื่อหยุดการทดสอบหน่วยเป็นการทดสอบการรวม

ตอนนี้คุณมีการทดสอบที่เร็วขึ้นแล้วเวลาในการตรวจสอบเพื่อหยุดสิ่งนี้ไม่ให้เกิดขึ้นอีก

มีไลบรารีที่มี Monkey patch active record เพื่อส่งข้อผิดพลาดเมื่อพยายามเข้าถึงฐานข้อมูล (UnitRecord)

คุณสามารถลองจับคู่และ TDD ซึ่งสามารถช่วยบังคับให้ทีมของคุณเขียนแบบทดสอบได้เร็วขึ้นเนื่องจาก:

  1. มีคนตรวจสอบ - ไม่มีใครขี้เกียจ
  2. TDD ที่เหมาะสมต้องการการตอบรับที่รวดเร็ว การทดสอบอย่างช้าๆทำให้ทุกอย่างเจ็บปวด

5. ใช้ไลบรารีอื่นเพื่อเอาชนะปัญหา

มีคนกล่าวถึง spork (เพิ่มความเร็วในการโหลดชุดทดสอบใต้ราง 3), hydra / parallel_tests - เพื่อเรียกใช้การทดสอบหน่วยแบบขนาน (ในหลายคอร์)

ควรใช้ LAST ปัญหาที่แท้จริงของคุณอยู่ในขั้นตอนที่ 1, 2, 3 แล้วคุณจะอยู่ในตำแหน่งที่ดีขึ้นในการกำหนดบทบาทของโครงสร้างพื้นฐานเพิ่มเติม


คำตอบที่ดี เป็นเรื่องจริงมากที่ไม่มีเครื่องมือขั้นสูงที่ช่วยให้ทำการทดสอบที่ไม่ดีได้อย่างรวดเร็ว ดังนั้นลองเขียน แต่เรื่องดีๆ
Yura Omelchuk

5
ฉันไม่เห็นด้วยในประเด็นที่สามของคุณว่าคุณไม่ควรใช้อุปกรณ์ติดตั้ง หากใช้อย่างถูกต้องจะเร็วกว่าโรงงานเนื่องจากคุณไม่ต้องสร้างวัตถุ ข้อมูลของคุณอยู่ที่นั่นคุณไม่จำเป็นต้องสร้างขึ้นในแต่ละกรณีการทดสอบ
wallerjake

3
เรื่องโรงงานเร็วขึ้นเป็นเรื่องตลกใช่ไหม?
Mike Szyndel

Speed ​​Up Tests by Selectively Avoiding Factory Girl - robots.thoughtbot.com/…
geekdev

16

สำหรับตำราอาหารที่ยอดเยี่ยมในการปรับปรุงประสิทธิภาพชุดทดสอบของคุณโปรดดูการนำเสนอGrease Your Suite

เขาจัดทำเอกสารเร่งความเร็ว 45 เท่าในเวลาทำงานของชุดทดสอบโดยใช้เทคนิคต่างๆเช่น:


ฉันชอบการเชื่อมโยง แต่ไม่ใช่การนำเสนอ บัตรดัชนีสำหรับการพูดของใครบางคนเป็นการกระตุ้นให้ผู้พูดกรอกข้อมูลในงานนำเสนอ
Brian Maltzan

งานนำเสนอนี้ไม่ขึ้นแล้ว fast_context เพิ่มความเร็วในการบล็อกควรหลายรายการ Quickerclip (ลิงค์นั้นตายด้วย) ดูเหมือนว่า Paperclip จะเร็วขึ้น Hydra เลิกใช้งานสำหรับ parallel_tests และ Gorgon bootsnap มีการปรับแต่งระบบไฟล์และตอนนี้รวมอยู่ใน Rails แล้ว Ruby เวอร์ชันล่าสุดได้ปรับปรุงการจัดสรรและ GC
ตัวแทน

5

คุณสามารถใช้ Spork รองรับ 2.3.x,

https://github.com/sporkrb/spork

หรือ. /script/spec_server ซึ่งอาจใช้ได้กับ 2.x

นอกจากนี้คุณยังสามารถแก้ไขการกำหนดค่าฐานข้อมูล (ซึ่งโดยพื้นฐานแล้วการสืบค้นฐานข้อมูลจะเร็วขึ้นเป็นต้น) ซึ่งจะช่วยเพิ่มประสิทธิภาพในการทดสอบด้วย


Spork น่ากลัว นอกจากนี้ยังใช้งานได้กับ Rails 3 ด้วยการแฮ็กเล็กน้อย แต่สิ่งหนึ่งที่ควรทราบสำหรับ Spork บน Rails 3 คือดูเหมือนว่าจะไม่ได้รับการเปลี่ยนแปลงในคอนโทรลเลอร์ดังนั้นคุณจะต้องรีสตาร์ททุกครั้ง แต่อย่างไรก็ตาม Spork นั้นยอดเยี่ยมมากการปรับปรุงความเร็วของการทดสอบมีความสำคัญมาก
AboutRuby

4
Spork ใช้สำหรับเร่งการเริ่มต้นเท่านั้นไม่ใช่การทดสอบ ดังนั้นด้วยข้อกำหนดจำนวนมากข้อได้เปรียบจึงไม่มีนัยสำคัญ
Reactormonk

ขัดกับความคิดเห็นข้างต้น Spork สามารถนำมาใช้เพื่อเพิ่มความเร็วในการทดสอบเช่นเดียวกับการเริ่มต้นเป็นต่อ railscast railscasts.com/episodes/285-spork ปรับปรุงชุดทดสอบ rspec ของฉันอย่างมหาศาลในแอปขนาดใหญ่มาก (ลดลงจาก 192 วินาทีเหลือ 10 วินาที!)
jamesc

3

10 วินาทีต่อตัวอย่างดูเหมือนจะนานมาก ฉันไม่เคยเห็นข้อมูลจำเพาะที่ใช้เวลามากกว่าหนึ่งวินาทีและส่วนใหญ่ใช้เวลาน้อยกว่านี้มาก คุณกำลังทดสอบการเชื่อมต่อเครือข่ายหรือไม่ ฐานข้อมูลเขียน? ระบบไฟล์เขียน?

ใช้ mocks และสมบูรณ์มากที่สุดเท่าที่เป็นไปได้ - พวกเขามีมากเร็วกว่าการเขียนโค้ดที่นิยมฐานข้อมูล น่าเสียดายที่การล้อเลียนและการเขียนขื่อต้องใช้เวลามากกว่าในการเขียน (และยากที่จะทำอย่างถูกต้อง) คุณต้องสร้างสมดุลระหว่างเวลาที่ใช้ในการเขียนแบบทดสอบกับเวลาที่ใช้ในการทดสอบ

ฉันสองความคิดเห็นของAndrew Grimmเกี่ยวกับการดูระบบ CI ซึ่งอาจช่วยให้คุณสามารถขนานชุดทดสอบของคุณได้ สำหรับบางสิ่งบางอย่างที่มีขนาดนั้นอาจเป็นทางออกเดียวที่ทำงานได้


ใช่ถ้า 10 วินาทีฉันจะทำโปรไฟล์และดูว่าคอขวดอยู่
ที่ไหน

1
ฉันมีโปรเจ็กต์ขนาดใหญ่และการทดสอบ rspec ครั้งเดียวใช้เวลาประมาณ 15-20 วินาที
ExiRe

2

หลายคนได้กล่าวถึงไฮดราข้างต้น เราได้ใช้มันอย่างประสบความสำเร็จในอดีต เมื่อเร็ว ๆ นี้ฉันได้บันทึกขั้นตอนการเริ่มต้นและใช้งานไฮดรา: http://logicalfriday.com/2011/05/18/faster-rails-tests-with-hydra/

ฉันเห็นด้วยกับความเชื่อมั่นว่าไม่ควรใช้เทคนิคแบบนี้แทนการทดสอบการเขียนที่มีโครงสร้างดีและรวดเร็วโดยค่าเริ่มต้น


2

หากคุณใช้โมเดล ActiveRecord คุณควรพิจารณาต้นทุนของการเข้ารหัส BCrypt ด้วย

คุณสามารถอ่านเพิ่มเติมเกี่ยวกับเรื่องนี้ได้ในบล็อกโพสต์นี้: http://blog.syncopelabs.co.uk/2012/12/speed-up-rspec-test.html


0

Fast_require gem อาจช่วยคุณได้ นอกจากนั้นวิธีเดียวของคุณคือการ (เช่นเดียวกับที่คุณทำ) โปรไฟล์และเพิ่มประสิทธิภาพหรือใช้ spork หรือสิ่งที่เรียกใช้ข้อกำหนดของคุณควบคู่ไปกับคุณ http://ruby-toolbox.com/categories/distributed_testing.html


0

คุณสามารถทำตามเคล็ดลับง่ายๆเพื่อตรวจสอบก่อนว่าเวลาส่วนใหญ่จะใช้ไปไหนหากคุณยังไม่ได้ลองใช้ ดูบทความด้านล่าง:

https://blog.mavenhive.in/7-tips-to-speed-up-your-webdriver-tests-4f4d043ad581

ฉันเดาว่าส่วนใหญ่เป็นขั้นตอนทั่วไปซึ่งจะนำไปใช้โดยไม่คำนึงถึงเครื่องมือที่ใช้ในการทดสอบด้วย


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.