HAQM Web Services 한국 블로그
AWS CodeBuild를 통한 CI 가속화, 병렬 테스트 실행 지원
AWS CodeBuild가 병렬 테스트 실행을 지원합니다. 이를 통해 테스트 스위트를 동시에 실행하여 빌드 시간을 크게 단축할 수 있습니다. 이 게시물을 위해 작성한 데모 프로젝트에서는 환경을 프로비저닝하는 시간을 포함하여 총 테스트 시간이 35분에서 6분으로 단축되었습니다. AWS Management Console에서 가져온 두 스크린샷이 그 차이를 보여줍니다.
테스트 스위트 순차 실행
테스트 스위트 병렬 실행
테스트 시간이 매우 길면 대규모로 지속적 통합(CI)을 실행할 때 상당한 어려움이 발생합니다. 프로젝트가 복잡해지고 팀 규모가 확대되면서 포괄적인 테스트 스위트를 실행하는 데 필요한 시간이 크게 늘어나 파이프라인 실행 시간이 증가할 수 있습니다. 이로 인해 새로운 기능 및 버그 수정 제공이 지연될 뿐만 아니라 작업을 진행하기 전에 빌드 결과를 기다려야 하므로 개발자의 생산성이 저하됩니다. 저는 파이프라인을 실행하는 데 최대 60분이 걸렸는데, 마지막 단계에서 실패하면서 전체 재실행이 필요하여 추가 지연을 경험한 것입니다. 이러한 긴 주기는 CI 프로세스에서 개발자 신뢰를 떨어뜨리고 불만을 야기하며 궁극적으로 전체 소프트웨어 제공 주기를 늦출 수 있습니다. 또한 테스트를 오래 실행하면 리소스 경합이 발생하고 컴퓨팅 성능 낭비로 인한 비용이 증가하며 개발 프로세스의 전반적인 효율성이 저하될 수 있습니다.
CodeBuild의 병렬 테스트 실행을 통해 이제 여러 빌드 컴퓨팅 환경에서 동시에 테스트를 실행할 수 있습니다. 이 기능은 각 빌드 노드가 테스트 스위트의 하위 집합을 독립적으로 실행하는 샤딩 접근 방식을 구현합니다. CodeBuild는 각 노드가 실행해야 하는 테스트를 결정하는 데 사용되는 현재 노드 수와 총 노드 수를 식별하는 환경 변수를 제공합니다. 빌드 시에는 제어 빌드 노드나 노드 간의 조정이 없습니다. 각 노드는 독립적으로 작동하여 할당된 테스트를 실행합니다.
테스트 분할을 활성화하려면 buildspec.xml
에서 원하는 병렬 처리 수준 및 기타 관련 파라미터를 지정하여 batch fanout 섹션을 구성합니다. 또한 빌드 단계에서 적절한 테스트 명령 및 선택한 분할 방법과 함께 codebuild-tests-run 유틸리티를 사용하세요.
테스트는 지정한 샤딩 전략에 따라 분할됩니다. codebuild-tests-run
은 두 가지 샤딩 전략을 제공합니다.
- 균등 분배. 이 전략은 테스트 파일을 알파벳순으로 정렬하고 병렬 테스트 환경 간에 균등하게 청크 단위로 배포합니다. 테스트 파일의 이름 또는 수량을 변경하면 샤드 전체에 파일이 재할당될 수 있습니다.
- 안정성. 이 전략은 일관된 해싱 알고리즘을 사용하여 샤드 전반에서 테스트 분포를 수정합니다. 파일이 추가 또는 제거될 때 기존의 파일-샤드 할당이 유지됩니다.
테스트를 병렬로 실행할 때 CodeBuild는 테스트 보고서의 자동 병합을 지원합니다. CodeBuild는 자동 테스트 보고서 병합 기능을 통해 테스트 보고서를 단일 테스트 요약으로 통합하여 결과 분석을 간소화합니다. 병합된 보고서에는 집계된 합격/불합격 상태, 테스트 기간 및 실패 세부 정보가 포함되므로 수동 보고서 처리의 필요성이 줄어듭니다. CodeBuild 콘솔에서 병합된 결과를 보거나, AWS Command Line Interface(AWS CLI)를 사용하여 검색하거나, 다른 보고 도구와 통합하여 테스트 분석을 간소화할 수 있습니다.
작동 방식
프로젝트에서 병렬 테스트를 구현하는 방법을 보여드리겠습니다. 이 데모에서는 수백 개의 테스트가 포함된 아주 기본적인 Python 프로젝트를 생성했습니다. 작업 속도를 높이기 위해 명령줄에서 HAQM Q Developer에게 프로젝트 1개와 테스트 사례 1,800개를 생성해 달라고 요청했습니다. 각 테스트 사례는 별도의 파일이며 완료하는 데 1초가 걸립니다. 모든 테스트를 순서대로 실행하려면 환경을 프로비저닝하는 시간을 제외하고 30분이 소요됩니다.
이 데모에서는 10개의 컴퓨팅 환경에서 테스트 스위트를 병렬로 실행하고 스위트를 실행하는 데 걸리는 시간을 측정합니다.
이를 위해 프로젝트에 buildspec.yml
파일을 추가했습니다.
version: 0.2
batch:
fast-fail: false
build-fanout:
parallelism: 10 # ten runtime environments
ignore-failure: false
phases:
install:
commands:
- echo 'Installing Python dependencies'
- dnf install -y python3 python3-pip
- pip3 install --upgrade pip
- pip3 install pytest
build:
commands:
- echo 'Running Python Tests'
- |
codebuild-tests-run \
--test-command 'python -m pytest --junitxml=report/test_report.xml' \
--files-search "codebuild-glob-search 'tests/test_*.py'" \
--sharding-strategy 'equal-distribution'
post_build:
commands:
- echo "Test execution completed"
reports:
pytest_reports:
files:
- "*.xml"
base-directory: "report"
file-format: JUNITXML
YAML 파일에서 강조할 부분이 3개 있습니다.
먼저, batch
아래에 build-fanout
섹션이 있습니다. parallelism
명령은 CodeBuild에 병렬 실행할 테스트 환경의 수를 알려줍니다. ignore-failure
명령은 팬아웃 빌드 태스크 실패를 무시할 수 있는지 여부를 나타냅니다.
둘째, 사전 설치된 codebuild-tests-run
명령을 사용하여 테스트를 실행합니다.
이 명령은 전체 테스트 파일 목록을 수신하고 현재 노드에서 실행해야 하는 테스트를 결정합니다.
sharding-strategy
인수를 사용하여 위에서 설명한 것처럼 균등 분포 또는 안정성 분포 중에서 선택합니다.files-search
인수를 사용하여 실행 대상 파일을 모두 전달합니다. 성능상의 이유로 제공된codebuild-glob-search
명령을 사용하는 것이 좋지만 find(1)와 같은 모든 파일 검색 도구를 사용할 수 있습니다.test-command
인수를 사용하여 샤드에서 실행할 실제 테스트 명령을 전달합니다.
마지막으로, reports
섹션은 CodeBuild에 각 노드의 테스트 보고서를 수집하고 병합하도록 지시합니다.
그런 다음 CodeBuild 콘솔을 열어 프로젝트와 이 프로젝트의 배치 빌드 구성을 생성합니다. 여기에는 새로운 것이 없으므로 자세한 내용은 생략하겠습니다. 설명서에 시작하는 데 필요한 모든 세부 정보가 있습니다. 병렬 테스트는 배치 빌드에서 작동합니다. 프로젝트를 배치로 실행되도록 구성해야 합니다.
이제 테스트 스위트 실행을 트리거할 준비가 되었습니다. GitHub 리포지토리에서 새 코드를 커밋하거나 콘솔에서 빌드를 트리거할 수 있습니다.
몇 분 후 각 테스트 환경 또는 샤드의 상태와 함께 빌드의 여러 단계에 대한 상태 보고서가 표시됩니다.
테스트가 완료되면 Reports 탭을 선택하여 병합된 테스트 보고서에 액세스합니다.
Reports 섹션은 모든 샤드의 모든 테스트 데이터를 집계하고 모든 빌드의 기록을 보관합니다. Report history 섹션에서 가장 최근 빌드를 선택하여 세부 보고서에 액세스합니다.
예상대로 1,800개 테스트 사례의 집계된 상태와 각 테스트 사례의 개별 상태를 볼 수 있습니다. 이 데모에서는 모두 통과하여 보고서가 초록색입니다.
데모 프로젝트의 1,800개 테스트는 각각 완료하는 데 1초가 걸립니다. 이 테스트 스위트를 순차적으로 실행했을 때 완료하는 데 35분이 걸렸습니다. 테스트 스위트를 10개의 컴퓨팅 환경에서 병렬로 실행했을 때 환경을 프로비저닝하는 시간을 포함하여 완료하는 데 6분이 걸렸습니다. 병렬 실행은 순차 실행 시간의 17.1%가 걸렸습니다. 실제 수치는 프로젝트에 따라 다를 수 있습니다.
추가 정보
이 새로운 기능은 모든 테스트 프레임워크와 호환됩니다. 설명서에는 Django, Elixir, Go, Java(Maven), Javascript(Jest), Kotlin, PHPUnit, Pytest, Ruby(Cucumber) 및 Ruby(RSpec)용 예제가 포함되어 있습니다.
공백으로 구분된 목록을 허용하지 않는 테스트 프레임워크의 경우 codebuild-tests-run
CLI는 CODEBUILD_CURRENT_SHARD_FILES
환경 변수를 통해 유연한 대안을 제공합니다. 이 변수에는 현재 빌드 샤드의 테스트 파일 경로를 줄바꿈으로 구분한 목록이 포함됩니다. 이를 사용하여 다양한 테스트 프레임워크 요구 사항에 맞게 조정하고 테스트 파일 이름의 형식을 지정할 수 있습니다.
샤딩 스크립트를 직접 작성하고 각 빌드에서 자동으로 설정되는 CODEBUILD_BATCH_BUILD_IDENTIFIER
환경 변수를 사용하여 환경 간에 테스트를 분할하는 방법을 추가로 사용자 지정할 수 있습니다. 이 기법을 사용하여 프레임워크별 병렬화 또는 최적화를 구현할 수 있습니다.
요금 및 가용성
병렬 테스트 실행을 통해 이제 이전보다 훨씬 짧은 시간에 테스트 스위트를 완료하여 개발 주기를 가속화하고 팀의 생산성을 개선할 수 있습니다. 이 게시물에서 예시를 위해 생성한 데모 프로젝트는 순차 빌드 시간의 18.7%가 소요되었습니다.
CodeBuild에서 제공하는 세 가지 컴퓨팅 모드(온디맨드, 예약 용량, AWS Lambda 컴퓨팅) 모두에서 병렬 테스트 실행을 사용할 수 있습니다.
이 기능은 현재 CodeBuild가 제공되는 모든 AWS 리전에서 사용할 수 있으며, 사용된 컴퓨팅 리소스에 대한 표준 CodeBuild 요금 외에는 추가 비용이 들지 않습니다.
오늘 CodeBuild에서 병렬 테스트 실행을 시도해 보시기 바랍니다. 자세한 내용을 알아보고 테스트 병렬화를 시작하려면 AWS CodeBuild 설명서를 참조하세요.
PS: 데모 애플리케이션 및 테스트 스위트를 생성할 때 사용한 프롬프트는 다음과 같습니다. “I’m writing a blog post to announce codebuild parallel testing. Write a very simple python app that has hundreds of tests, each test in a separate test file. Each test takes one second to complete.”
뉴스 블로그를 어떻게 생각하시나요? 이 1분짜리 설문조사에 참여해 주세요!
(이 설문조사는 외부 기업에서 호스트합니다. AWS는 AWS 개인정보 처리방침에 설명한 대로 사용자 정보를 처리합니다. AWS는 이 설문 조사를 통해 수집된 데이터를 소유하며 수집된 정보를 설문 응답자와 공유하지 않습니다)