대규모 Rails 애플리케이션에서 RSpec 테스트 속도 향상


91

내 RSpec 테스트에서 2,000 개 이상의 예제가있는 Rails 애플리케이션이 있습니다. 말할 필요도없이, 그것은 큰 응용 프로그램이고 많은 테스트가 필요합니다. 이 시점에서 이러한 테스트를 실행하는 것은 매우 비효율적이며 시간이 너무 오래 걸리기 때문에 새 빌드를 푸시하기 전에 작성하는 것이 거의 권장되지 않습니다. 가장 오래 실행되는 예제를 찾기 위해 spec.opts에 --profile을 추가했으며 실행하는 데 평균 10 초가 걸리는 예제가 10 개 이상 있습니다. RSpec 전문가들 사이에서 그게 정상입니까? 예를 들어 10 초가 너무 길어? 2,000 개의 예제를 사용하면 모든 것을 철저히 테스트하는 데 사소한 시간이 걸리지 않지만이 시점에서 4 시간은 약간 우스꽝 스럽습니다.

가장 오래 실행되는 예제에 대해 어떤 종류의 시간을보고 있습니까? 병목 현상을 파악하고 작업 속도를 높이기 위해 기존 사양의 문제를 해결하려면 어떻게해야합니까? 이 시점에서 매 순간 정말 도움이 될 것입니다.


1
느린 테스트 통합 테스트입니까? 그들은 db를 치고 있습니까? 그렇다면 얼마나 자주 db가 다시로드되고 db를 조롱 할 수 있습니까?
Kaleb Pederson

1
SeattleRB의 자동 테스트와 같이 작업중인 부분과 관련된 사양의 일부만 실행할 수 있습니까? 모든 테스트를 실행할 수있는 지속적 통합 서버가 있습니까?
Andrew Grimm

모든 것이 상대적이라는 것을 기억하십시오. "그르르, 우리 테스트 스위트는 영원히 걸린다"라는 말을 20 분 동안 ... 16-20 시간 동안 들었습니다. 모든 것이 보는 사람의 눈에 달려 있습니다. 주어진 테스트에서 10 초는 종종 아래에 언급 된 통합 테스트가 된 단위 테스트를 의미합니다.
Michael Durrant

이러한 종류의 문제에 대한 제안 : perftools.rb테스트 프레임 워크와 함께 사용하여 대부분의 시간을 소비하는 항목을 이해하십시오. 상위 10 개의 통화를 가져와 제거 / 탈지 해보십시오. 그런 다음 행복 할 때까지 반복하십시오.
aledalgrande 2014

답변:


118

10 초는 단일 테스트를 실행하는 데 매우 긴 시간입니다. 내 직감은 사양 대상이 단위 및 통합 테스트를 동시에 실행하고 있다는 것입니다. 이것은 프로젝트에 해당하는 전형적인 것이며 어떤 단계 에서이 기술적 부채를 극복해야합니다. 더 많은 것을 더 빨리 생산하려면 . 이 작업을 수행하는 데 도움이 될 수있는 여러 가지 전략이 있습니다. 과거에 사용했던 몇 가지 전략을 권장합니다.

1. 통합 테스트에서 단위 분리

가장 먼저 할 일은 통합 테스트에서 유닛을 분리하는 것입니다. 다음 중 하나를 수행 할 수 있습니다.

  1. 그것들을 (spec 디렉토리 아래의 별도 폴더로) 이동-레이크 타겟 수정
  2. 태그 지정 (rspec을 사용하면 테스트에 태그를 지정할 수 있음)

철학은 일반 빌드가 빠르기를 원한다는 것입니다. 그렇지 않으면 사람들이 자주 실행하는 것을 너무 좋아하지 않을 것입니다. 그러니 그 영역으로 돌아가십시오. 정기적 인 테스트를 빠르게 실행하고 지속적 통합 서버를 사용하여보다 완전한 빌드를 실행하십시오.

통합 테스트는 외부 종속성 (예 : Database, WebService, Queue 및 일부는 FileSystem을 주장함)을 포함하는 테스트입니다. 단위 테스트는 확인하려는 특정 코드 항목 만 테스트합니다. 빠르게 실행되어야합니다 (45 초에 9000이 가능). 즉, 대부분이 메모리에서 실행되어야합니다.

2. 통합 테스트를 단위 테스트로 변환

단위 테스트의 대부분이 통합 테스트 스위트보다 작 으면 문제가있는 것입니다. 이것이 의미하는 바는 불일치가 더 쉽게 나타나기 시작한다는 것입니다. 따라서 여기에서 통합 테스트를 대체 할 더 많은 단위 테스트를 만들기 시작합니다. 이 프로세스를 돕기 위해 수행 할 수있는 작업은 다음과 같습니다.

  1. 실제 리소스 대신 모의 프레임 워크를 사용합니다. Rspec에는 내장 된 조롱 프레임 워크가 있습니다.
  2. 단위 테스트 스위트에서 rcov를 실행하십시오. 이를 사용하여 단위 테스트 스위트가 얼마나 철저한 지 측정하십시오.

통합 테스트를 대체 할 적절한 단위 테스트가 있으면 통합 테스트를 제거하십시오. 중복 테스트는 유지 관리를 악화시킬뿐입니다.

3. 비품을 사용하지 마십시오

비품은 사악합니다. 대신 팩토리를 사용하십시오 (기계공 또는 팩토리 봇). 이러한 시스템은보다 적응 가능한 데이터 그래프를 구축 할 수 있으며, 더 중요한 것은 외부 데이터 소스에서 데이터를로드하는 대신 사용할 수있는 메모리 내 개체를 구축 할 수 있다는 것입니다.

4. 통합 테스트가되는 단위 테스트를 중지하기위한 검사 추가

이제 더 빠른 테스트가 준비되었으므로이 문제가 다시 발생하지 않도록 확인해야합니다.

데이터베이스 (UnitRecord)에 액세스하려고 할 때 오류를 발생시키기 위해 원숭이 패치 활성 레코드가있는 라이브러리가 있습니다.

다음과 같은 이유로 팀이 더 빠른 테스트를 작성하도록 할 수있는 페어링 및 TDD를 시도 할 수도 있습니다.

  1. 누군가 확인 중입니다. 그래서 아무도 게으르지 않습니다.
  2. 적절한 TDD에는 빠른 피드백이 필요합니다. 느린 테스트는 모든 것을 고통스럽게 만듭니다.

5. 문제를 극복하기 위해 다른 라이브러리 사용

누군가는 spork (rails3 아래 테스트 스위트의로드 시간을 단축), hydra / parallel_tests를 언급하여 병렬로 (여러 코어에 걸쳐) 단위 테스트를 실행했습니다.

이것은 아마도 마지막에 사용되어야합니다. 실제 문제는 1, 2, 3 단계에 있습니다.이 문제를 해결하면 추가 인프라 역할을 수행 할 수있는 더 나은 위치에있게됩니다.


좋은 대답입니다. 고급 도구가 잘못된 테스트를 빠르게 실행하는 데 도움이 될 수 없다는 것은 사실입니다. 그러니 좋은 것만 써보세요.
Yura Omelchuk 2011

5
나는 당신이 조명기를 사용해서는 안된다는 세 번째 요점에 동의하지 않습니다. 제대로 사용하면 개체를 만들 필요가 없기 때문에 팩토리보다 빠릅니다. 귀하의 데이터는 각 테스트 케이스로 생성 할 필요가 없습니다.
wallerjake 2014

3
공장이 더 빠르다는 것은 농담입니다.
Mike Szyndel 2014 년

최대 속도는 선택적으로 방지 공장 소녀에 의해 테스트 - robots.thoughtbot.com/...
geekdev

16

테스트 스위트의 성능 향상에 대한 훌륭한 요리 책은 Grease Your Suite 프레젠테이션을 확인하십시오 .

그는 다음과 같은 기술을 활용하여 테스트 스위트 실행 시간이 45 배 빨라 졌다고 기록합니다.


링크는 좋아하지만 프레젠테이션은 좋아하지 않습니다. 누군가의 연설에 대한 색인 카드는 발표자가 프레젠테이션의 내용을 채우도록 유도합니다.
Brian Maltzan

이 프레젠테이션은 더 이상 작동하지 않습니다. fast_context는 여러 shoulda 블록의 속도를 높입니다. quickerclip (링크도 끊어짐)은 분명히 Paperclip의 속도를 높입니다. Hydra는 parallel_tests 및 Gorgon에서 더 이상 사용되지 않습니다. bootsnap에는 파일 시스템 조정 기능이 있으며 이제 Rails에 포함됩니다. 최신 버전의 Ruby에서는 할당 및 GC가 개선되었습니다.
rep

5

Spork를 사용할 수 있습니다. 2.3.x를 지원합니다.

https://github.com/sporkrb/spork

또는 2.x에서 작동하는 ./script/spec_server

또한 데이터베이스 구성을 편집하여 (기본적으로 데이터베이스 쿼리 속도를 높이는 등) 테스트 성능도 높일 수 있습니다.


Spork는 굉장합니다. 또한 약간의 해킹이있는 Rails 3에서도 작동합니다. 그러나 Spork on Rails 3에서 주목해야 할 점은 컨트롤러의 변경 사항을 받아들이지 않는 것 같으므로 자주 다시 시작해야합니다. 그러나 어쨌든 Spork는 정말 대단합니다. 테스트의 속도 향상은 매우 중요합니다.
AboutRuby

4
Spork는 테스트가 아닌 시작 속도를 높이기위한 것입니다. 따라서 사양이 많으면 이점이 미미합니다.
Reactormonk

댓글 spork 위는 달리 당 railscast로 테스트뿐만 아니라 시작 속도를 사용할 수 있습니다 railscasts.com/episodes/285-spork을 . 매우 큰 앱에서 내 rspec 테스트 스위트를 대폭 개선했습니다. (192 초에서 10 초로 단축되었습니다!)
jamesc 2011

3

예제 당 10 초는 매우 긴 시간처럼 보입니다. 1 초 이상 걸리는 사양은 본 적이 없으며 대부분은 훨씬 적게 걸립니다. 네트워크 연결을 테스트하고 있습니까? 데이터베이스 쓰기? 파일 시스템 쓰기?

모의와 스텁을 가능한 많이 사용하십시오 . 데이터베이스에 접근하는 코드를 작성하는 것보다 훨씬 빠릅니다. 불행히도 조롱과 스터 빙은 작성하는 데 더 많은 시간이 걸립니다 (올바르게 수행하기가 더 어렵습니다). 테스트 작성 시간과 테스트 실행 시간의 균형을 맞춰야합니다.

테스트 스위트를 병렬화 할 수있는 CI 시스템을 조사하는 것에 대한 Andrew Grimm 의 의견을 두 번째 로드립니다. 이 정도 크기의 경우 유일한 솔루션 일 수 있습니다.


그래 10 초이면 프로파일 링을하고 병목이 어디인지 확인합니다.
rogerdpack

1
거대한 프로젝트가 있고 단일 rspec 테스트를 실행하는 데 15-20 초 정도 걸립니다.
ExiRe 2013

2

여러 사람이 위에서 Hydra를 언급했습니다. 우리는 과거에 큰 성공을 거두었습니다. 나는 최근에 hydra를 시작하고 실행하는 과정을 문서화했습니다 : http://logicalfriday.com/2011/05/18/faster-rails-tests-with-hydra/

나는 이런 종류의 기술이 기본적으로 잘 구조화되고 빠른 테스트를 작성하는 대신 사용되어서는 안된다는 의견에 동의합니다.





-4

기존 테스트 스위트를 삭제하십시오. 매우 효과적 일 것입니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.