Rescale에 대한 BYO 소프트웨어 회귀 테스트

 회귀 테스트2
Rescale은 소프트웨어 공급업체를 위한 귀중한 회귀 및 성능 테스트 리소스입니다. API와 명령줄 도구를 사용하여 Rescale에서 내부 회귀 테스트 전체 또는 일부를 실행하는 방법에 대해 논의합니다. Rescale 테스트의 장점은 다음과 같습니다.

  1. 컴퓨팅 리소스는 주문형이므로 실제로 테스트를 실행할 때만 비용을 지불합니다.
  2. 컴퓨팅 리소스도 확장 가능하므로 대규모 테스트 스위트를 병렬로 실행하고 피드백을 더 빨리 얻을 수 있습니다.
  3. 다양한 하드웨어 구성(예: Infiniband, 10GigE, Tesla 및 Phi 보조 프로세서)에서 소프트웨어 성능을 테스트하는 데 이기종 리소스를 사용할 수 있습니다.
  4. Rescale에서 소프트웨어를 테스트하면 선택적으로 Rescale의 다른 고객에게 비공개 베타 릴리스를 제공할 수 있습니다.

테스트 설정

이 문서의 나머지 부분에서는 다음과 같은 파일 세트가 있다고 가정합니다.

  1. 일반적으로 지원되는 아카이브 형식(tar.gz, zip 등)의 소프트웨어 패키지의 전체 빌드 트리
  2. 보관된 참조 테스트 입력 및 예상 출력 세트
  3. 하나 이상의 테스트 입력에 대해 소프트웨어 빌드를 실행하기 위한 스크립트 또는 명령줄
  4. 예상 출력으로 실제 테스트 출력을 평가하는 스크립트
  5. (선택 사항) 전체 빌드 트리 위에 오버레이할 더 작은 증분 빌드 제품 세트

아래 예에서는 Python을 사용합니다. SDK. 아래의 예시 중 일부는 SDK 저장소에서 사용할 수 있습니다. 여기에서 지금 확인해 보세요.. SDK는 REST API를 래핑하므로 다음에서 참조된 엔드포인트를 사용하여 이러한 예제를 다른 언어로 포팅할 수 있습니다. https://github.com/rescale/python-sdk/blob/master/rescale/client.py.
이 모든 예시에는 다음이 필요합니다.

  1. 의 계정 리스케일 플랫폼
  2. 지역의 RESCALE_API_KEY 기본 플랫폼 페이지의 설정->API에 있는 API 키로 설정된 환경 변수

단일 작업에서 테스트 실행

가장 간단한 예부터 시작하여 전체 빌드 및 테스트 참조 데이터를 작업 입력 파일로 업로드하고, 테스트를 순차적으로 실행하고, 결과를 비교합니다. 업로드하고 실행할 몇 가지 "소프트웨어" 예제부터 시작해 보겠습니다. 다음은 소프트웨어 패키지 및 테스트 파일 목록입니다.

echoware/bin/echo.sh (테스트를 위해 테스트를 에코합니다) test[0-9]/in (테스트 입력) test[0-9]/expected_out (예상 테스트 출력) test[0-9]/out ( 실제 테스트 실행 출력)

각 소프트웨어 빌드 및 테스트 케이스는 별도로 보관됩니다. 테스트 스위트 작업을 준비하고 실행하는 단계는 다음과 같습니다.

  1. Rescale Python SDK를 사용하여 빌드, 참조 테스트 데이터 및 결과 비교 스크립트를 업로드합니다.
#!/usr/bin/env python3 import rescale.client TEST_ARCHIVE = 'inputs/all_tests.tar.gz' BUILD_ARCHIVE = 'inputs/echoware0.1.tar.gz' POST_COMPARE_SCRIPT = 'inputs/compare_results.sh' input_files = [rescale .client.RescaleFile(file_path=TEST_ARCHIVE), rescale.client.RescaleFile(file_path=BUILD_ARCHIVE), ] post_process_file = \ rescale.client.RescaleFile(file_path=POST_COMPARE_SCRIPT)

파일 크기 조정 로컬 파일 콘텐츠를 Rescale에 업로드하고 해당 파일을 참조하기 위한 메타데이터를 반환합니다. 이 시점에서 다음 위치에서 이러한 파일을 볼 수 있습니다.  https://www.rescale.com/route/files/.
      2. 테스트 스위트 작업을 생성합니다:

TEST_COMMAND = """
테스트 케이스의 경우 $(find . -name "test[0-9]*" -type d); do ./echoware/bin/echo.sh $testcase done """ POST_RUN_COMPARE_COMMAND = """ for testcase in $(find . -name "test[0-9]*" -type d); do ./compare_results.sh $testcase done """ JOB_NAME = 'echoware0.1-all-tests' job_definition = { 'name': JOB_NAME, 'isLowPriority': True, 'jobanalyses': [ { '분석': { ' code': 'custom' }, 'hardware': { 'coresPerSlot': 1, 'slots': 1, 'coreType': { 'code': 'standard-plus' } }, 'inputFiles': [{'id ': inp.id} for inp in input_files], 'command': TEST_COMMAND, 'postProcessScript': {'id': post_process_file.id}, 'postProcessScriptCommand': POST_RUN_COMPARE_COMMAND } ], } job = rescale.client.RescaleJob(json_data =직업_정의)

RescaleJob 이제 볼 수 있는 새 작업을 생성합니다. https://www.rescale.com/route/jobs/. 여기서는 단일 Marble 코어에서 작업을 실행하고 있습니다. 다음을 통해 더 많은 코어를 실행하도록 선택할 수 있습니다. 코어당슬롯 또는 다른 코어 유형 코드를 선택하여 코어 유형을 변경하십시오. RescaleConnect.get_core_types().
참고로 명령postProcessScript명령 필드는 유효한 bash 스크립트일 수 있으므로 테스트를 실행하고 결과를 평가하는 방법에 상당한 유연성이 있습니다. 매우 간단한 예에서 테스트 후 명령 비교는 아웃예상_아웃 각 테스트 케이스 디렉터리에 있는 파일입니다.

  1. 실행할 작업을 제출하고 완료될 때까지 기다립니다.
작업.제출() 작업.대기()

작업 클러스터가 프로비저닝되면 입력 파일이 클러스터로 전송되고 암호화되지 않은 다음 작업 디렉터리에서 압축이 풀립니다. 다음으로, TEST_COMMAND 실행되고 그 다음에 POST_RUN_COMPARE_COMMAND.

  1. 테스트 결과를 다운로드하세요. 모든 Rescale 작업 명령에는 stdout이 다음으로 리디렉션되었습니다. process_output.log 테스트 결과 요약을 보려면 해당 파일 하나를 다운로드하세요.
STDOUT_LOG = 'process_output.log' test_log = job.get_file(STDOUT_LOG) test_log.download(target=test_log.name)

여기에서 작업의 후처리 단계로 테스트 결과 비교를 수행함으로써 잠재적으로 큰 출력 파일을 다운로드하여 테스트 결과를 얻는 데 걸리는 시간을 지연시키는 것을 방지한다는 점에 유의하는 것이 중요합니다. 이는 종종 실제 출력과 크기가 비슷한 테스트 참조 출력을 업로드해야 하는 문제를 해결하지 않습니다. 핵심은 우리가 시작하는 모든 테스트 작업에 대해 파일을 업로드하는 것이 아니라 파일이 변경될 때만 Rescale에 업로드하면 된다는 것입니다. 참조 테스트 사례가 자주 변경되지 않는다고 가정하면 이제 방금 Rescale에 업로드한 파일을 이후 테스트 실행에서 재사용할 수 있습니다.
이 예를 전체에서 찾을 수 있습니다. 여기에서 지금 확인해 보세요..

참조 테스트 데이터 재사용

이제 제출된 모든 테스트 작업에 대한 참조 테스트 데이터가 업로드되지 않도록 위 절차를 수정하겠습니다.

  1. (수정됨) Rescale에서 테스트 파일 메타데이터를 찾아 후속 작업에 대한 입력 파일로 사용합니다.
# 위에서 var 설정 생략 original_test_file = rescale.client.RescaleFile.get_newest_by_name(TEST_ARCHIVE) input_files = [original_test_file, rescale.client.RescaleFile(file_path=BUILD_ARCHIVE), ] post_process_file = \ rescale.client.RescaleFile.get_newest_by_name(POST_COMPARE_SCRIPT)

RescaleFile.get_newest_by_name은 이미 Rescale에 업로드된 테스트 파일에 대한 메타데이터를 검색합니다. 동일한 이름으로 여러 테스트 아카이브를 업로드한 경우 가장 최근에 업로드된 아카이브가 선택됩니다.
2~4단계는 이전 예와 동일합니다.

장기 실행 테스트 병렬화

이전 예제에서는 모든 테스트를 순차적으로 실행했지만 이제 일부 테스트를 병렬로 실행해 보겠습니다. 이 예에서는 테스트가 "짧은" 테스트와 "긴" 테스트로 분할되어 있다고 가정합니다. 짧은 테스트는 다음과 같은 아카이브에 있습니다. all_short_tests.tar.gz 각 장기 테스트는 다음과 같은 별도의 아카이브에 있습니다. long_test_.tar.gz.
이제 모든 간단한 테스트에 대해 단일 작업을 시작하고 긴 테스트에 대해 테스트당 작업을 시작하겠습니다. 첫 번째 예에서와 같이 이러한 테스트 파일이 이미 Rescale에 업로드되었다고 가정합니다.

# 명령 생략 var setup SHORT_TEST_ARCHIVE = 'inputs/all_short_tests.tar.gz' LONG_TEST_FORMAT = 'inputs/long_test_{i}.tar.gz' LONG_TEST_COUNT = 10 BUILD_ARCHIVE = 'inputs/echoware0.1.tar.gz' POST_COMPARE_SCRIPT = 'inputs /compare_results.sh' # 로컬 복사본에서 업로드하는 대신 Rescale에서 이름으로 찾기 short_test_bundle = \ rescale.client.RescaleFile.get_newest_by_name(SHORT_TEST_ARCHIVE) long_test_inputs = [ rescale.client.RescaleFile.get_newest_by_name(LONG_TEST_FORMAT.format(i=i)) for i in range(LONG_TEST_COUNT): post_process_file = \ rescale.client.RescaleFile.get_newest_by_name(POST_COMPARE_SCRIPT) # 로컬 복사본 업로드 build_input = rescale.client.RescaleFile(file_path=BUILD_ARCHIVE) def create_job(name, test_input, core_type, core_count): input_files = [build_input, test_input] job_definition = { 'name': name, 'isLowPriority': True, 'jobanalyses': [ { 'analytics': { 'code': 'custom' }, 'hardware': { 'coresPerSlot': core_count, 'slots': 1, 'coreType': { 'code': core_type } }, 'inputFiles': [input_files의 inp에 대한 {'id': inp.id}], 'command': TEST_COMMAND, 'postProcessScript' : {'id': post_process_file.id}, 'postProcessScriptCommand': POST_RUN_COMPARE_COMMAND } ], } return rescale.client.RescaleJob(json_data=job_definition) # 모든 테스트 작업 생성 short_test_job = create_job('echoware0.1-all-short-tests ', short_test_bundle, 'standard-plus', 1) long_test_jobs = [create_job('echoware0.1-long-test-{0}'.format(i), long_test, 'hpc-plus', 32) for i, long_test in enumerate(long_test_inputs)] test_jobs = [short_test_job] + long_test_jobs # 모두 제출

[test_jobs의 작업에 대한 job.submit()]

# 모두 완료될 때까지 기다립니다

[test_jobs의 작업에 대한 job.wait()]

# 결과 가져오기 [test_jobs의 작업에 대한 job.get_file(STDOUT_LOG).download(target='{0}.out'.format(job.name))]

이 예에서는 단일 Marble 코어를 사용하여 짧은 테스트 작업을 시작하고 32개 코어(2개 노드) Nickel MPI 클러스터를 사용하여 각 장기 테스트를 시작했습니다.
이 테스트 작업 구성은 특히 성능 테스트에 적합합니다. 특정 빌드 + 테스트 사례 조합이 확장되는지 테스트하려면 각각 4, 1, 2, 4개의 노드가 있는 8개의 작업을 시작할 수 있습니다.
이 예를 찾을 수 있습니다 여기에서 지금 확인해 보세요..

증분 빌드

위에서 우리는 Rescale에 이미 저장된 동일한 데이터를 재사용하여 각 테스트 실행마다 테스트 데이터를 다시 업로드하는 것을 피했습니다. 테스트해야 하는 대규모 소프트웨어 빌드가 있는 경우 이미 업로드된 데이터도 재사용하고 싶지만 테스트되는 각 빌드는 일반적으로 다릅니다. 그러나 대부분의 경우 전체 패키지에서 파일의 작은 하위 집합만 빌드마다 변경됩니다.
빌드의 유사성을 활용하기 위해 첫 번째 작업에서 업로드한 기본 빌드 트리 위에 압축이 풀릴 증분 빌드 델타를 제공할 수 있습니다. 요구사항은 2가지 뿐입니다.

  1. 빌드 델타는 기본 빌드와 동일한 디렉터리 구조를 가져야 합니다.
  2. 기본 빌드 아카이브 이후의 입력 파일로 빌드 델타 아카이브를 지정해야 합니다.
다음은 이 변경 내용을 발췌한 것입니다: FULL_BUILD_ARCHIVE = 'inputs/echoware0.1.tar.gz' BUILD_DELTA = 'inputs/echoware0.2-delta.tar.gz' # Rescale에서 이름으로 찾기 base_build_input = \ rescale.client.RescaleFile .get_newest_by_name(FULL_BUILD_ARCHIVE) # 로컬 복사본 업로드 Incremental_build_input = rescale.client.RescaleFile(file_path=BUILD_DELTA) def create_job(name, test_input, core_type, core_count): input_files = [base_build_input, test_input, Incremental_build_input] job_definition = { 'name': JOB_NAME , 'isLowPriority': True, 'jobanalyses': [ { 'analytic': { 'code': 'custom' }, 'hardware': { 'coresPerSlot': 1, 'slots': core_count, 'coreType': { ' code': core_type } }, 'inputFiles': [input_files의 inp에 대한 {'id': inp.id}], 'command': TEST_COMMAND, 'postProcessScript': {'id': post_process_file.id}, 'postProcessScriptCommand' : POST_RUN_COMPARE_COMMAND } ], } return rescale.client.RescaleJob(json_data=job_definition)

위에서, base_build_input 이미 Rescale에 있는 파일에서 가져온 것이며 Incremental_build_input 매번 업로드됩니다.

실험 계획(DOE) 작업의 병렬성

테스트를 실행하는 또 다른 방법은 여러 테스트를 단일 DOE 작업으로 그룹화하는 것입니다. 병렬로 실행할 수 있는 테스트 수는 작업에 대해 구성한 작업 슬롯 수에 따라 정의됩니다. 그런 다음 에 설명된 대로 템플릿 구성 파일로 매개변수화할 수 있도록 테스트 실행을 구조화합니다. https://www.rescale.com/resources/getting-started/doe/.
이 방법은 다중 작업의 경우에 비해 작업 클러스터 설정 시간을 단축할 수 있는 장점이 있습니다. 단점은 각 테스트 실행이 작업 슬롯에 대해 정의한 것과 동일한 하드웨어 구성으로 제한된다는 것입니다. Python SDK를 사용하여 DOE 작업을 설정하는 방법에 대한 예는 다음을 참조하세요. https://github.com/rescale/python-sdk/tree/master/examples/doe.

대용량 파일 업로드

위의 예에서는 간단한 PUT 요청으로 입력 파일을 업로드했습니다. 이는 속도가 느리거나 멀티 기가바이트 파일의 경우 작동하지 않는 경우가 많습니다. 대안은 대역폭에 최적화된 파일 업로드 및 다운로드를 제공하고 중단된 경우 전송을 재개할 수 있는 Rescale CLI 도구를 사용하는 것입니다.
Rescale CLI에 대한 자세한 내용은 여기를 참조하세요. support@rescale.com.
Rescale에서 테스트를 실행하는 것은 대규모 회귀 및 성능 테스트 스위트에 대한 내부 컴퓨팅 리소스에 대한 테스트 시간과 부담을 줄이는 좋은 방법입니다. Rescale API는 대용량 메모리, 대용량 스토리지, 인피니밴드 및 GPU 지원 클러스터를 포함한 다양한 하드웨어 구성에 대한 테스트 그룹을 시작하는 매우 유연한 방법을 제공합니다. Rescale에 대한 자체 테스트에 관심이 있다면 SDK 및 예제 스크립트를 확인하세요. https://github.com/rescale/python-sdk 또는 문의 support@rescale.com.

저자

  • 마크 휘트니

    Mark Whitney는 Rescale의 엔지니어링 이사입니다. 그의 전문 분야에는 고성능 컴퓨팅 아키텍처, 양자 정보 연구, 클라우드 컴퓨팅이 포함됩니다. 그는 캘리포니아 대학교 버클리 캠퍼스에서 컴퓨터 과학 박사 학위를 취득했습니다.

비슷한 게시물