E2E 테스팅 여정 파트 2: WebdriverIO에서 Cypress로
게시 됨: 2019-11-21참고: 이것은 #frontend@twiliosendgrid의 게시물입니다. 다른 엔지니어링 게시물을 보려면 기술 블로그 롤로 이동하십시오.
우리의 모든 프론트엔드 앱에서 우리는 다음과 같은 목표를 가지고 있었고 지금도 가지고 있습니다. 프론트엔드 애플리케이션에 대해 일관되고 디버그 가능하고 유지 관리 가능하고 가치 있는 E2E(종단 간) 자동화 테스트를 작성하고 CICD(지속적 통합)와 통합하는 방법을 제공합니다. 및 지속적인 배포).
수백 개의 E2E 테스트가 현재 SendGrid의 모든 프론트엔드 팀에서 일정에 따라 실행되거나 실행될 수 있는 상태에 도달하기 위해 주요 목표를 달성할 때까지 그 과정에서 많은 잠재적 솔루션을 연구하고 실험해야 했습니다. 목표.
모든 팀이 하나의 리포지토리에 기여하고 브라우저 간 자동화 테스트를 실행할 수 있는 SiteTestUI(STUI라고도 함)라는 전담 테스트 엔지니어가 개발한 자체 사용자 지정 Ruby Selenium 솔루션을 롤링하려고 했습니다. 슬프게도 느리고 불안정한 테스트, 잘못된 경보, 저장소와 언어 간의 컨텍스트 부족, 한 바구니에 너무 많은 인력, 고통스러운 디버깅 경험, 가치 제공보다 유지 관리에 더 많은 시간이 소요되었습니다.
그런 다음 WebdriverIO의 또 다른 유망한 라이브러리를 실험하여 각 팀의 애플리케이션 저장소와 함께 배치된 JavaScript로 테스트를 작성했습니다. 이것은 일부 문제를 해결하고 더 많은 팀 소유권을 부여하고 CICD 제공업체인 Buildkite와 테스트를 통합할 수 있게 해주었지만, 너무 유사한 Selenium 버그 및 단점을 처리하는 것 외에도 디버그하기 힘들고 작성하기 힘든 불안정한 테스트가 있었습니다. .
우리는 다른 STUI 2.0을 피하고 싶었고 다른 옵션을 탐색하기 시작했습니다. STUI에서 WebdriverIO로 마이그레이션할 때 배운 교훈과 발견한 전략에 대해 자세히 알아보려면 블로그 게시물 시리즈의 1부를 확인하십시오.
블로그 게시물 시리즈의 마지막 2부에서는 STUI 및 WebdriverIO에서 Cypress로의 여정과 전체 인프라 설정, 조직화된 E2E 테스트 작성, Buildkite 파이프라인과의 통합 및 조직의 다른 프론트엔드 팀.
TLDR: 우리는 STUI 및 WebdriverIO보다 Cypress를 채택했으며 CICD와 통합할 가치 있는 E2E 테스트를 작성하려는 모든 목표를 달성했습니다. WebdriverIO 및 STUI에서 배운 많은 작업과 교훈은 오늘날 Cypress 테스트를 사용하고 통합하는 방법에 훌륭하게 적용되었습니다.
목차
Cypress 탐색 및 착륙
STUI 및 WebdriverIO에서 Cypress로 전환
1단계: Cypress에 대한 종속성 설치
2단계: 환경 구성 및 스크립트
환경 구성 및 스크립트의 첫 번째 단계
환경 구성 및 스크립트의 진화
3단계: 로컬에서 E2E 테스트 구현
4단계: 테스트 도커화
5단계: CICD와 통합
6단계: Cypress와 WebdriverIO/STUI 비교
7단계: 다른 프런트엔드 팀으로 확장
Cypress에서 기대하는 것
미래에 Cypress 채택
Cypress 탐색 및 착륙
WebdriverIO에 대한 대안을 검색할 때 WebdriverIO와 유사한 기능이 설정된 Protractor 및 Nightwatch와 같은 다른 Selenium 래퍼를 보았지만 긴 설정, 불안정한 테스트, 지루한 디버깅 및 유지 관리에 직면할 가능성이 가장 높다고 느꼈습니다.
우리는 고맙게도 Cypress라는 새로운 E2E 테스트 프레임워크를 발견했습니다. 이 프레임워크는 빠른 설정, 브라우저에서 실행되는 빠르고 디버그 가능한 테스트, 네트워크 계층 요청 스터빙, 그리고 가장 중요한 것은 Selenium을 사용하지 않는 것을 보여줍니다.
우리는 비디오 녹화, Cypress GUI, 유료 대시보드 서비스, 병렬화와 같은 멋진 기능에 감탄했습니다. 우리는 개발자와 QA를 위한 테스트를 구현, 디버그 및 유지 관리할 수 있는 도구 목록을 사용하여 Chrome에 대해 일관되게 통과하는 귀중한 테스트를 위해 브라우저 간 지원에 대해 기꺼이 타협했습니다.
우리는 또한 모든 프론트엔드 팀에서 테스트에 대한 보다 표준화된 접근 방식을 갖기 위해 선택한 테스트 프레임워크, 주장 라이브러리 및 기타 모든 도구에 감사했습니다. 아래에서 WebdriverIO 및 Cypress와 같은 솔루션 간의 차이점에 대한 스크린샷을 제공했으며 Cypress와 Selenium 솔루션 간의 차이점을 더 알고 싶다면 작동 방식에 대한 설명서를 확인할 수 있습니다.
이를 염두에 두고 우리는 CICD 동안 궁극적으로 Buildkite와 통합될 빠르고 일관되며 디버그 가능한 E2E 테스트를 작성하기 위한 또 다른 솔루션으로 Cypress를 테스트하기 위해 노력했습니다. 우리는 또한 Cypress를 이전 Selenium 기반 솔루션과 비교하는 또 다른 목표를 의도적으로 설정하여 궁극적으로 데이터 포인트를 기준으로 Cypress를 계속 살펴봐야 하는지 아니면 앞으로 Cypress로 테스트 제품군을 구축해야 하는지를 결정합니다. 우리는 기존 WebdriverIO 테스트와 여전히 STUI에 있는 다른 높은 우선 순위 테스트를 Cypress 테스트로 변환하고 개발자 경험, 속도, 안정성, 테스트 실행 시간 및 테스트 유지 관리를 비교할 계획이었습니다.
STUI 및 WebdriverIO에서 Cypress로 전환
STUI 및 WebdriverIO에서 Cypress로 전환할 때 프런트엔드 애플리케이션 저장소에서 STUI에서 WebdriverIO로의 마이그레이션을 시도할 때 사용한 것과 동일한 상위 수준 전략을 통해 체계적으로 해결했습니다. WebdriverIO에서 이러한 단계를 수행한 방법에 대한 자세한 내용은 블로그 게시물 시리즈의 1부를 참조하십시오. Cypress로 전환하기 위한 일반적인 단계는 다음과 같습니다.
- Cypress와 연결하기 위한 종속성 설치 및 설정
- 환경 구성 및 스크립트 명령 설정
- 다른 환경에 대해 로컬로 통과하는 E2E 테스트 구현
- 테스트 도커화
- CICD 제공업체인 Buildkite와 Docker화된 테스트 통합
2차 목표를 달성하기 위해 Cypress를 이전 Selenium 솔루션과 비교하고 궁극적으로 조직의 모든 프론트엔드 팀에서 Cypress를 확장하는 추가 단계도 추가했습니다.
6. 개발자 경험, 속도 및 테스트 안정성 측면에서 Cypress와 WebdriverIO 및 STUI 비교
7. 다른 프론트엔드 팀으로 확장
1단계: Cypress에 대한 종속성 설치
Cypress를 빠르게 시작하고 실행하려면 프로젝트에 `npm install cypress`를 설치하고 Cypress를 처음 시작하여 `cypress.json` 구성 파일과 cypress
폴더를 자동으로 배치하기만 하면 됩니다. 명령 및 플러그인을 위한 스타터 픽스처, 테스트 및 기타 설정 파일이 포함됩니다. 우리는 Cypress가 테스트 러너로 Mocha, 어설션을 위해 Chai, 더 많은 어설션을 사용하고 연결하기 위해 Chai-jQuery 및 Sinon-Chai와 함께 번들로 제공되는 방식에 감사했습니다. WebdriverIO 또는 STUI를 처음 시작할 때와 비교하여 더 이상 설치하고 사용할 테스트 러너, 리포터, 어설션 및 서비스 라이브러리에 대해 조사하는 데 상당한 시간을 할애할 필요가 없었습니다. 생성된 테스트 중 일부를 Cypress GUI로 즉시 실행하고 시간 여행 디버깅, 선택기 플레이그라운드, 녹화된 비디오, 스크린샷, 명령 로그, 브라우저 개발자 도구 등과 같은 다양한 디버깅 기능을 탐색했습니다.
또한 새로운 Cypress 테스트 코드를 커밋할 때 따를 추가 정적 유형 검사 및 형식 지정 규칙을 위해 Eslint 및 TypeScript를 사용하여 나중에 설정했습니다. 처음에는 TypeScript 지원에 문제가 있었고 일부 파일은 플러그인 파일 중심의 파일과 같은 JavaScript 파일이어야 했지만 대부분의 경우 테스트, 페이지 개체 및 명령에 대해 대부분의 파일을 유형 검사할 수 있었습니다.
다음은 프론트엔드 팀 중 하나가 페이지 개체, 플러그인 및 명령을 통합하기 위해 따랐던 폴더 구조의 예입니다.
2단계: 환경 구성 및 스크립트
Cypress를 빠르게 설치하고 로컬에서 실행하도록 설정한 후에는 각 환경에 대해 다양한 설정으로 Cypress 테스트를 실행할 수 있는 방법이 필요했고 WebdriverIO 명령으로 수행할 수 있는 것과 동일한 사용 사례를 지원하고 싶었습니다. 다음은 이러한 테스트를 실행하고 지원하려는 이유에 대한 대부분의 사용 사례를 보여주는 목록입니다.
- localhost(예: http://localhost:8000)에서 실행되는 Webpack 개발 서버 와 해당 개발 서버는 특정 환경 API(예: https://testing.api.com 또는 https://staging.api)를 가리킬 것입니다. com) 테스트 또는 스테이징과 같습니다.
왜요? 더 강력한 방식으로 요소와 상호 작용하기 위해 테스트에 대해 보다 구체적인 선택기를 추가하는 것과 같이 로컬 웹 앱을 변경해야 하거나 새로운 기능을 개발하는 중에 기존 자동화 테스트를 조정하고 검증해야 하는 경우가 있습니다. 새로운 코드 변경 사항에 대해 로컬로 전달됩니다. 애플리케이션 코드가 변경되고 아직 배포된 환경으로 푸시하지 않을 때마다 이 명령을 사용하여 로컬 웹 앱에 대한 테스트를 실행했습니다. - 테스트 또는 스테이징과 같은 특정 환경(예: https://testing.app.com 또는 https://staging.app.com)에 배포된 앱에 대해
왜요? 다른 경우에는 애플리케이션 코드가 변경되지 않지만 약간의 결함을 수정하기 위해 테스트 코드를 변경해야 할 수도 있습니다. CICD에서 테스트가 실행되는 방식을 보다 밀접하게 시뮬레이션하기 위해 배포된 앱에 대해 로컬로 테스트를 업데이트하거나 디버그하는 데 이 명령을 많이 활용했습니다. - 테스트 또는 스테이징과 같은 특정 환경을 위해 배포된 앱에 대해 Docker 컨테이너에서 실행
왜요? 이것은 CICD를 위한 것이므로 예를 들어 스테이징 배포된 앱에 대해 Docker 컨테이너에서 실행되도록 E2E 테스트를 트리거하고 코드를 프로덕션에 배포하기 전에 또는 전용 파이프라인에서 예약된 테스트 실행에서 통과하는지 확인할 수 있습니다. 이러한 명령을 처음 설정할 때 CICD 공급자인 Buildkite와 연결하기 전에 다양한 환경 변수 값으로 Docker 컨테이너를 실행하고 적절한 테스트가 성공적으로 실행되었는지 테스트하기 위해 많은 시행착오를 수행했습니다.
환경 구성 및 스크립트의 첫 번째 단계
Cypress 설정을 처음 실험했을 때 발신자 인증, 이메일 활동 및 이메일 유효성 검사와 같은 기능 페이지가 포함된 웹 앱인 https://app.sendgrid.com을 다루는 리포지토리에서 수행했으며 불가피하게 공유했습니다. https://mc.sendgrid.com 도메인을 포함하는 마케팅 캠페인 웹 앱 뒤에 있는 팀과의 발견 및 학습. 우리는 스테이징 환경에 대해 E2E 테스트를 실행하기를 원했고 Cypress의 명령줄 인터페이스와 --config
또는 --env
와 같은 옵션을 활용하여 사용 사례를 수행했습니다.
http://127.0.0.1:8000
또는 배포된 스테이징 앱 URL에 대해 로컬로 웹 앱에 대해 Cypress 테스트를 실행하기 위해 명령에서 baseUrl
구성 플래그를 조정하고 도움이 되도록 testEnv
와 같은 추가 환경 변수를 추가했습니다. Cypress 테스트에서 특정 고정 장치 또는 환경별 테스트 데이터를 로드합니다. 예를 들어 사용된 API 키, 생성된 사용자 및 기타 리소스는 환경에 따라 다를 수 있습니다. 환경에서 일부 기능이 지원되지 않거나 테스트 설정이 다르고 사양에서 Cypress.env(“testEnv”)
와 같은 호출을 통해 환경에 액세스하는 경우 testEnv
를 사용하여 이러한 고정 장치를 토글하거나 특수 조건부 논리를 추가했습니다.
그런 다음 로컬에서 개발할 때 UI를 통해 실행할 테스트를 선택하기 위해 Cypress GUI를 여는 것을 나타내기 위해 cypress:open:*
명령을 구성하고 더 맞춤화된 헤드리스 모드에서 테스트를 실행하기 위해 cypress:run:*
명령을 구성했습니다. CICD 동안 Docker 컨테이너에서 실행하기 위한 것입니다. open
또는 run
후에 오는 것은 환경이 될 것이므로 우리의 명령은 npm run cypress:open:localhost:staging
처럼 쉽게 읽혀서 GUI를 열고 스테이징 API 또는 npm run cypress:run:staging
을 가리키는 로컬 Webpack 개발 서버에 대해 테스트를 실행합니다. npm run cypress:run:staging
- 배포된 스테이징 앱 및 API에 대해 헤드리스 모드에서 테스트를 실행합니다. package.json
Cypress 스크립트는 다음과 같이 나왔습니다.
환경 구성 및 스크립트의 진화
다른 프로젝트에서는 cypress/plugins/index.js
파일의 일부 노드 논리를 활용하여 기본 cypress.json
파일과 configFile
을 사용하여 특정 구성 파일을 로드합니다. 로드된 구성 파일은 기본 파일과 병합되어 결국 스테이징 또는 모의 백엔드 서버를 가리킵니다.
모의 백엔드 서버에 대해 더 궁금한 경우를 대비하여 요청에서 전달된 쿼리 매개변수에 따라 정적 JSON 데이터 및 상태 코드(예: 200, 4XX, 5XX)의 다양한 응답을 단순히 반환하는 백엔드 엔드포인트가 있는 Express 서버를 개발했습니다. 이렇게 하면 프론트엔드가 차단 해제되어 실제 API가 향후 사용 가능할 때 실제 API가 어떻게 보일지 에뮬레이트하는 응답으로 모의 백엔드 서버에 대한 실제 네트워크 호출로 페이지 흐름을 계속 개발할 수 있습니다. 또한 프로덕션에서 재현하기 어려운 다양한 UI 상태에 대해 다양한 수준의 성공 및 오류 응답을 쉽게 시뮬레이션할 수 있으며, 결정론적 네트워크 호출을 수행하므로 Cypress 테스트가 동일한 네트워크에서 실행될 때 덜 불안정할 것입니다. 매번 요청하고 응답합니다.
일반 시간 초과에 대한 공유 속성, 나중에 설명할 Cypress 대시보드 서비스와 연결하기 위한 프로젝트 ID, 아래에 표시된 기타 설정이 포함된 기본 cypress.json
파일이 있습니다.
로컬 모의 API 서버에 대해 localhostMock.json
Webpack 개발 서버를 실행하거나 배포된 스테이징 앱 및 API에 대해 실행하기 위해 staging.json
과 같은 각 구성 파일을 보관하기 위해 cypress
폴더에 config
폴더를 만들었습니다. 기본 구성과 비교하고 병합할 구성 파일은 다음과 같습니다.
CICD 구성 파일에는 환경 변수를 동적으로 설정하여 다양한 Docker 서비스 프론트엔드 기본 URL과 나중에 살펴볼 모의 서버 API 호스트를 설명해야 했기 때문에 훨씬 더 간단한 JSON 파일이 있었습니다.
cypress/plugins/index.js
파일에서 Cypress 명령에서 설정한 configFile
이라는 환경 변수를 읽는 로직을 추가했습니다. 이 환경 변수는 결국 config
폴더의 해당 파일을 읽고 아래와 같이 기본 cypress.json
과 병합합니다.
사용 사례에 맞게 설정된 환경 변수를 사용하여 합리적인 Cypress 명령을 작성하기 위해 다음과 유사한 Makefile
을 활용했습니다.
이러한 명령을 Makefile에 깔끔하게 배치하면 `package.json` npm 스크립트에서 make cypress_open_staging
또는 make cypress_run_staging
과 같은 작업을 빠르게 수행할 수 있습니다.
이전에는 오류 없이 편집하기 어려운 몇 가지 명령을 하나의 긴 줄에 배치했습니다. 고맙게도 Makefile은 환경 변수를 여러 줄에 걸쳐 Cypress 명령으로 읽을 수 있는 보간으로 훨씬 더 잘 퍼뜨리는 데 도움이 되었습니다. 환경 구성 파일을 로드할 configFile
, 페이지를 방문하기 위한 BASE_URL
, 다양한 백엔드 환경을 위한 API_HOST
또는 Makefile 명령을 시작하기 전에 실행할 테스트를 결정하기 위한 SPECS
와 같은 환경 변수를 빠르게 설정하거나 내보낼 수 있습니다.
또한 Webpack 자산 구축, 종속성 설치 또는 다른 사람과 동시에 명령 실행과 같이 다른 긴 npm 스크립트 및 Docker 명령에 대해 Makefile 명령을 사용했습니다. 그런 다음 일부 Makefile 명령을 package.json
스크립트 섹션으로 변환합니다. 누군가 Makefile만 사용하려는 경우에는 필요하지 않으며 다음과 같이 보일 것입니다.
Cypress CICD 명령은 일상적인 개발에 사용되는 명령이 아니기 때문에 의도적으로 생략했고 결과적으로 package.json
을 더 간소화했습니다. 가장 중요한 것은 모의 서버 및 로컬 Webpack 개발 서버와 관련된 모든 Cypress 명령 대 스테이징 환경 및 헤드리스 모드에서 "실행"이 아니라 GUI를 "열고 있는" 모든 Cypress 명령을 한 눈에 볼 수 있다는 것입니다.
3단계: 로컬에서 E2E 테스트 구현
Cypress로 E2E 테스트를 구현하기 시작했을 때 WebdriverIO 및 STUI의 기존 테스트를 참조하여 변환하고 간단한 상태 확인에서 복잡한 행복 경로 흐름에 이르기까지 우선 순위가 높은 다른 기능에 대한 새로운 테스트를 추가했습니다. WebdriverIO 또는 STUI의 기존 페이지 개체 및 테스트 파일을 Cypress의 동등한 페이지 개체 및 사양으로 변환하는 것은 쉬운 일임이 입증되었습니다. 실제로 요소에 대한 명시적인 대기가 줄어들고 어설션 및 기타 Cypress 명령의 연결성이 향상되어 이전보다 훨씬 더 깨끗한 코드가 생성되었습니다.
예를 들어 테스트의 일반 단계는 최종 사용자 관점에서 동일하게 유지되었으므로 변환 작업에는 WebdriverIO 또는 STUI API를 다음과 같은 방식으로 Cypress API에 매핑하는 작업이 포함되었습니다.
- $(".button").click()을 통해 페이지를 방문하여
$(“.button”).click()
을cy.get(“.button”).click()
으로 방문하는 거의$
또는browser
를cy
또는Cypress
로 대체하는 지점과 유사하게 많은 명령이 기본적으로 나타나고 작동했습니다.cy.get(“.button”).click()
,browser.url()
에서cy.visit()
, 또는$(“.input”).setValue()
에서cy.get(“.input”).type()
-
$
또는$$
를 사용하면 일반적으로$$(“.multiple-elements-selector”)
또는$(“.single-element-selector”)
같이cy.get(...)
또는cy.contains(...)
로 바뀝니다.$(“.single-element-selector”)
cy.get(“.any-element-selector”)
,cy.contains(“text”)
또는cy.contains(“.any-selector”)
- 기본적으로 Cypress를 허용하기 위해 불필요한
$(“.selector”).waitForVisible(timeoutInMs)
,$(“.selector”).waitUntil(...)
또는$(“.selector”).waitForExist()
호출 제거cy.get('.selector')
및cy.contains(textInElement)
를 사용하여 계속해서 요소의 재시도 및 검색을 처리합니다. 기본값보다 더 긴 시간 초과가 필요한 경우cy.get('.selector', { timeout: longTimeoutInMs })
을 모두 사용한 다음 요소를 검색한 후 다음 작업 명령을 연결하여 요소(예:cy.get(“.selector”).click()
)로 작업을 수행합니다.cy.get(“.selector”).click()
. - 브라우저로 사용자 정의 명령.
addCommand('customCommand, () => {})` turned into `Cypress.Commands.add('customCommand', () => {})
로 바뀌고 `cy.customCommand()`를 수행합니다. -
node-fetch
라는 라이브러리를 사용하여 API를 통해 설정 또는 해제에 대한 네트워크 요청을 만들고 이를browser.call(() => return fetch(...))
및/또는browser.waitUntil(...)
에 래핑하면cy.request(endpoint)
또는 우리가 정의하고cy.task(taskToHitAPIOrService)
와 같은 호출을 만든 사용자 정의 플러그인을 통해 Cypress 노드 서버에서 HTTP 요청을 만듭니다. - 눈에 띄는 UI 변경 없이 중요한 네트워크 요청이 완료될 때까지 기다려야 하는 경우가 있기 전에 때때로
browser.pause(timeoutInMs)
를 사용해야 했지만 Cypress를 사용하여 네트워크 스터빙 기능으로 이를 개선하고 수신할 수 있었습니다. 특정 요청이cy.server()
,cy.route(“method”, “/endpoint/we/are/waiting/for).as(“endpoint”)`, and `cy.wait(“@endpoint”)
요청을 트리거할 작업을 시작하기 전에.
많은 WebdriverIO 구문과 명령을 Cypress 명령으로 번역한 후 테스트에 필요한 각 페이지에 대해 공통 공유 기능과 확장된 페이지 개체를 위한 기본 페이지 개체를 갖는 동일한 개념을 가져왔습니다. 다음은 모든 페이지에서 공유되는 공통 open()
기능이 있는 기본 페이지 개체의 예입니다.
확장된 페이지 객체는 요소 선택기에 대한 getter를 추가하고, 해당 페이지 경로로 open()
기능을 구현하고, 아래와 같이 도우미 기능을 제공합니다.
우리의 실제 확장 페이지 객체는 또한 간단한 객체 맵을 활용하여 React 구성 요소에 데이터 속성으로 연결하고, 단위 테스트에서 참조하고, Cypress 페이지 객체에서 선택기로 사용할 요소의 모든 CSS 선택기를 한 곳에서 유지 관리합니다. 또한 페이지 개체 클래스는 페이지 개체가 Suppressions 페이지와 같이 유사하게 보이고 작동하는 여러 페이지에 재사용되었으며 경로 또는 특정 속성을 변경하기 위해 인수를 전달하는 경우 클래스 생성자를 활용하는 방식이 다양했습니다.
참고로 팀은 페이지 개체를 사용할 필요가 없었지만 모든 페이지에서 공통 기능을 공유하기 위해 표준 클래스 개체 구조와 함께 페이지 기능 및 DOM 요소 선택기 참조를 유지하기 위한 패턴의 일관성을 높이 평가했습니다. 다른 팀은 유틸리티 기능이 거의 없고 ES6 클래스를 사용하지 않고 다양한 파일을 만드는 것을 선호했지만 제거해야 할 중요한 점은 모든 것을 캡슐화하고 더 나은 개발자 효율성과 유지 관리 용이성을 위해 테스트를 작성하는 조직적이고 예측 가능한 방법을 제공하는 것이었습니다.
API를 통해 가능한 한 많은 테스트를 설정하려고 시도하면서 이전 WebdriverIO 테스트에 사용된 것과 동일한 일반 테스트 전략을 고수했습니다. 우리는 특히 테스트를 목표로 하지 않은 부분에 대해 허술함과 시간 낭비를 유발하지 않도록 UI를 통해 설정 상태를 구축하는 것을 피하고 싶었습니다. 대부분의 테스트에는 이 전략이 사용되었습니다.
- API를 통한 설정 또는 해제 – UI를 통해 엔터티 생성을 테스트해야 하는 경우 먼저 API를 통해 엔터티를 삭제해야 합니다. 이전 테스트 실행이 어떻게 성공했는지 실패했는지에 관계없이 테스트가 일관된 방식으로 작동하고 올바른 조건에서 시작되도록 하려면 API를 통해 테스트를 적절하게 설정하거나 해제해야 했습니다.
- API를 통해 전용 테스트 사용자에게 로그인 – 테스트가 격리되고 병렬로 실행될 때 서로의 리소스를 짓밟지 않도록 페이지 또는 자동화 테스트별로 전용 테스트 사용자를 만들었습니다. API를 통해 로그인 페이지와 동일한 요청을 하고 테스트 시작 전에 쿠키를 저장하여 인증된 페이지를 직접 방문하여 실제 테스트 단계를 시작할 수 있도록 했습니다.
- 최종 사용자 관점에서 단계 자동화 – API를 통해 사용자에 로그인한 후 페이지를 직접 방문하여 최종 사용자가 기능 흐름을 완료하고 사용자가 올바른 항목을 보고 상호 작용하는지 확인하기 위해 수행하는 단계를 자동화했습니다. 길을 따라.
테스트를 예상한 원래 상태로 다시 재설정하려면 전역 cy.login
명령을 사용하여 API를 통해 전용 테스트 사용자에게 로그인하고, 사용자 로그인을 유지하도록 쿠키를 설정하고, 사용자를 cy.request(“endpoint”)
또는 cy.task(“pluginAction”)
호출을 통해 원하는 시작 상태로 만들고 테스트하려는 인증된 페이지를 직접 방문합니다. 그런 다음 아래 테스트 레이아웃과 같이 사용자 기능 흐름을 수행하는 단계를 자동화합니다.
로그인 cy.login()
및 로그아웃 cy.logout()
()에 대해 이야기한 사용자 정의 명령을 기억하십니까? 우리는 모든 테스트가 같은 방식으로 API를 통해 사용자에게 로그인할 수 있도록 Cypress에서 이러한 방식으로 쉽게 구현했습니다.
또한 WebdriverIO 또는 STUI로 이전에는 잘 할 수 없었던 이메일과 관련된 복잡한 특정 흐름을 자동화하고 확인하고 싶었습니다. 몇 가지 예에는 이메일 활동을 CSV로 내보내기, 보낸 사람 인증을 위해 동료에게 보내기 흐름을 거치거나 이메일 유효성 검사 결과를 CSV로 내보내기가 포함됩니다. Cypress는 하나의 테스트에서 여러 슈퍼도메인에 액세스하는 것을 방지하므로 우리가 소유하지 않은 UI를 통해 이메일 클라이언트로 이동하는 것은 옵션이 아니라 불안정했습니다.
대신 cy.task(“pluginAction”)
명령을 통해 Cypress 플러그인을 개발하여 Cypress 노드 서버 내의 일부 라이브러리를 사용하여 SquirrelMail과 같은 테스트 이메일 IMAP 클라이언트/받은 편지함에 연결하여 작업을 요청한 후 받은 편지함에서 일치하는 이메일을 확인합니다. UI에서 특정 다운로드 페이지가 표시되는지 확인하고 전체 고객 흐름을 효과적으로 완료하기 위해 해당 이메일에서 웹 앱 도메인으로 리디렉션 링크를 따라갑니다. 특정 제목 줄에서 이메일이 SquirrelMail 받은 편지함에 도착하기를 기다리고, 이메일을 삭제하고, 이메일을 보내고, 이메일 이벤트를 트리거하고, 백엔드 서비스를 폴링하고, 테스트에서 사용할 API를 통해 훨씬 더 유용한 설정 및 분해를 수행하는 플러그인을 구현했습니다.
Cypress로 실제로 테스트한 내용에 대한 더 많은 통찰력을 제공하기 위해 다음과 같은 많은 고가치 사례를 다루었습니다.
- 앱 투어링이라고도 하는 모든 페이지에 대한 상태 확인 – 일부 콘텐츠가 로드된 페이지에서 때때로 특정 백엔드 서비스 또는 프론트엔드 호스팅이 중단되는지 확인하고 싶었습니다. 또한 선택기 및 도우미 기능으로 페이지 개체를 구축하는 정신적 근육 메모리를 구축하고 환경에 대해 실행되는 신속하고 작동하는 테스트를 얻기 위해 이러한 테스트를 먼저 수행하는 것이 좋습니다.
- 페이지에서 CRUD 작업 – 항상 API를 통해 그에 따라 테스트를 재설정한 다음 UI에서 생성, 읽기, 업데이트 또는 삭제를 구체적으로 테스트합니다. 예를 들어 UI를 통해 도메인 인증을 생성할 수 있는지 테스트했다면 마지막 테스트 실행이 어떻게 끝났는지에 관계없이 계속 진행하기 전에 UI를 통해 생성하려는 도메인이 처음에 API를 통해 삭제되었는지 확인해야 했습니다. 자동화된 UI 단계를 사용하여 도메인을 생성하고 충돌을 방지합니다. UI를 통해 억제를 삭제할 수 있는지 테스트했다면 먼저 API를 통해 억제를 생성한 다음 단계를 진행하도록 했습니다.
- 페이지에서 검색 필터 테스트 – 이메일 활동으로 고급 검색 필터를 설정하고 필터가 자동으로 채워졌는지 확인하기 위해 쿼리 매개변수가 있는 페이지를 방문하여 테스트했습니다. 또한 이메일 유효성 검사용 API를 통해 데이터를 추가하고 다시 한 번 다른 검색 필터를 시작하고 테이블이 해당 페이지의 검색 필터와 일치하는지 확인했습니다.
- 다양한 사용자 액세스 – Twilio SendGrid에는 다양한 범위 또는 액세스 권한을 가진 팀 동료를 가질 수 있는 상위 계정이 있거나 그 아래에 다양한 액세스 수준을 갖고 상위 계정과 다소 유사하게 동작하는 하위 사용자가 있습니다. 특정 페이지 및 하위 사용자에 대한 읽기 전용 대 관리자 액세스 권한이 있는 팀 동료는 페이지의 특정 항목을 보거나 보지 않을 수 있으므로 이러한 유형의 사용자에 대한 로그인을 자동화하고 Cypress 테스트에서 보거나 보지 않는 것을 쉽게 확인할 수 있습니다.
- 다양한 사용자 패키지 – 사용자는 또한 Essentials, Pro 및 Premier와 같은 무료에서 유료 패키지의 유형이 다를 수 있으며 해당 패키지는 페이지에서 특정 항목을 보거나 볼 수 없습니다. 우리는 다른 패키지를 가진 사용자에게 로그인하고 Cypress 테스트에서 사용자가 액세스할 수 있었던 기능, 사본 또는 페이지를 빠르게 확인했습니다.
4단계: 테스트 도커화
클라우드의 새 AWS 머신에서 각 Buildkite 파이프라인 단계를 실행할 때 npm run cypress:run:staging
을 단순히 호출할 수 없습니다. 해당 머신에는 실제로 Cypress를 실행하기 위한 노드, 브라우저, 애플리케이션 코드 또는 기타 종속성이 없기 때문입니다. 테스트. 이전에 WebdriverIO를 설정할 때 테스트를 실행하기 위해 적절한 Selenium, Chrome 및 애플리케이션 코드 서비스가 함께 작동하도록 Docker Compose 파일에 세 개의 개별 서비스를 조합해야 했습니다.
Cypress를 사용하면 Dockerfile
에 환경을 설정하는 데 Cypress 기본 Docker 이미지인 cypress/base
만 필요하고 애플리케이션 코드가 있는 docker-compose.yml
파일에 하나의 서비스만 필요하여 Cypress를 실행하는 것이 훨씬 더 간단했습니다. 테스트. 사용할 다른 Cypress Docker 이미지와 Docker에서 Cypress 테스트를 설정하는 다른 방법이 있으므로 이를 수행하는 한 가지 방법을 살펴보겠습니다. 대안에 대해서는 Cypress 설명서를 참조하는 것이 좋습니다.
Cypress 테스트를 실행하는 데 필요한 모든 애플리케이션 및 테스트 코드로 서비스를 시작하기 위해 Dockerfile
라는 Dockerfile.cypress
을 만들고 모든 node_modules
를 설치하고 코드를 Node 환경의 이미지 작업 디렉터리에 복사했습니다. 이것은 cypress
Docker Compose 서비스에서 사용되며 다음과 같은 방식으로 Dockerfile
설정을 달성했습니다.
이 Dockerfile.cypress
를 사용하면 Cypress 를 통합하여 cypress
라는 Docker Compose 서비스를 통해 특정 환경 API 및 배포된 앱에 대해 선택한 사양을 실행할 수 있습니다. 우리가 해야 할 일은 SPECS
및 BASE_URL
과 같은 일부 환경 변수를 보간하여 다음과 같은 npm run cypress:run:cicd:staging
명령을 통해 특정 기본 URL에 대해 선택된 Cypress 테스트를 실행하는 것입니다 ”cypress:run:cicd:staging”: “cypress run --record --key --config baseUrl=$BASE_URL --env testEnv=staging”
.
이러한 환경 변수는 Buildkite 파이프라인의 설정/구성 파일을 통해 설정되거나 배포 파이프라인에서 실행되도록 Cypress 테스트를 트리거할 때 동적으로 내보내집니다. docker-compose.cypress.yml
파일의 예는 다음과 유사합니다.
또한 몇 가지 다른 관찰 사항이 있습니다. 예를 들어 태그가 지정된 특정 Docker 이미지를 참조할 수 있는 VERSION
환경 변수를 볼 수 있습니다. 나중에 Docker 이미지에 태그를 지정하고 해당 빌드에 대해 동일한 Docker 이미지를 풀다운하여 Cypress 테스트에 대한 올바른 코드에 대해 실행하는 방법을 보여줍니다.
또한 BUILDKITE_BUILD_ID
를 통해 전달되며, 이는 우리가 시작하는 모든 빌드에 대한 다른 Buildkite 환경 변수와 함께 무료로 제공되며 ci-build-id
플래그도 표시됩니다. 이것은 Cypress의 병렬화 기능을 가능하게 하고 Cypress 테스트에 할당된 특정 수의 머신을 설정하면 자동으로 해당 머신을 스핀업하고 테스트를 분리하여 모든 머신 노드에서 실행하여 테스트를 최적화하고 속도를 높이는 방법을 알게 됩니다. 실행 시간.
마침내 우리는 볼륨 마운팅과 Buildkite의 아티팩트 기능도 활용했습니다. 해당 월에 할당된 유료 테스트 녹화가 소진되거나 어떻게든 대시보드 서비스에 액세스할 수 없는 경우에 대비하여 Buildkite UI "아티팩트" 탭을 통해 직접 액세스할 수 있도록 비디오와 스크린샷을 업로드합니다. 헤드리스 모드에서 Cypress "실행" 명령을 실행할 때마다 로컬에서 검토할 수 있도록 cypress/videos
및 cypress/screenshots
폴더에 출력이 있으며 우리는 해당 폴더를 마운트하고 안전 장치로 Buildkite에 업로드하기만 하면 됩니다.
5단계: CICD와 통합
다양한 환경에 대해 Docker 컨테이너에서 Cypress 테스트를 성공적으로 실행한 후 CICD 제공업체인 Buildkite와 통합하기 시작했습니다. Buildkite는 Bash 스크립트와 환경 변수가 코드에 설정되어 있거나 웹 UI에서 리포지토리의 Buildkite 파이프라인 설정을 통해 AWS 머신에서 .yml
파일의 단계를 실행하는 방법을 제공했습니다. 또한 Buildkite를 사용하여 내보낸 환경 변수를 사용하여 기본 배포 파이프라인에서 이 테스트 파이프라인을 트리거할 수 있었고 QA가 모니터링하고 볼 일정에 따라 실행되는 다른 격리된 테스트 파이프라인에 대해 이러한 테스트 단계를 재사용했습니다.
높은 수준에서 Cypress용 Buildkite 파이프라인 테스트와 이전 WebdriverIO 파이프라인은 다음과 유사한 단계를 공유했습니다.
- Docker 이미지를 설정합니다 . 테스트에 필요한 Docker 이미지를 빌드하고 태그를 지정하고 레지스트리로 푸시하면 이후 단계에서 풀다운할 수 있습니다.
- 환경 변수 구성을 기반으로 테스트를 실행합니다 . 특정 빌드에 대해 태그가 지정된 Docker 이미지를 풀다운하고 배포된 환경에 대해 적절한 명령을 실행하여 설정된 환경 변수에서 선택한 테스트 제품군을 실행합니다.
다음은 "Cypress Docker 이미지 빌드" 단계에서 Docker 이미지를 설정하고 "Cypress 테스트 실행" 단계에서 테스트를 실행하는 방법을 보여주는 pipeline.cypress.yml
.cypress.yml 파일의 예입니다.
한 가지 주목해야 할 점은 첫 번째 단계인 "Cypress Docker 이미지 빌드"와 테스트를 위해 Docker 이미지를 설정하는 방법입니다. Docker Compose build
명령을 사용하여 모든 애플리케이션 테스트 코드로 cypress
서비스를 빌드하고 latest
및 ${VERSION}
환경 변수로 태그를 지정했습니다. 미래의 단계. 각 단계는 AWS 클라우드 어딘가에 있는 다른 머신에서 실행될 수 있으므로 태그는 특정 Buildkite 실행에 대한 이미지를 고유하게 식별합니다. 이미지에 태그를 지정한 후 재사용할 수 있도록 최신 버전과 태그가 지정된 이미지를 비공개 Docker 레지스트리로 푸시했습니다.
"Cypress 테스트 실행" 단계에서는 첫 번째 단계에서 빌드, 태그 지정 및 푸시한 이미지를 풀다운하고 테스트를 실행하기 위해 Cypress 서비스를 시작합니다. SPECS
및 BASE_URL
과 같은 환경 변수를 기반으로 이 특정 Buildkite 빌드에 대해 배포된 특정 앱 환경에 대해 특정 테스트 파일을 실행합니다. 이러한 환경 변수는 Buildkite 파이프라인 설정을 통해 설정되거나 Bash 스크립트에서 동적으로 트리거되어 Buildkite 선택 필드를 구문 분석하여 실행할 테스트 제품군과 환경을 결정합니다.
Buildkite CICD 배포 파이프라인 중에 실행할 테스트를 선택하고 내보낸 특정 환경 변수로 전용 트리거 테스트 파이프라인을 트리거할 때 pipeline.cypress.yml
파일의 단계를 따라 수행합니다. 배포 파이프라인에서 일부 새 코드를 기능 분기 환경에 배포한 후 테스트를 트리거하는 예는 다음과 같습니다.
트리거된 테스트는 별도의 파이프라인에서 실행되며 "Build #639" 링크를 따라가면 아래와 같이 트리거된 테스트 실행을 위한 빌드 단계로 이동합니다.
일정에 따라 실행되는 전용 Cypress Buildkite 파이프라인에 대해 동일한 pipeline.cypress.yml
파일을 재사용하면 아래 사진과 같이 가장 우선 순위가 높은 E2E 테스트인 "P1"을 실행하는 것과 같은 빌드가 있습니다.
Buildkite 파이프라인 설정에서 실행할 사양 및 적중할 백엔드 환경과 같은 항목에 대해 적절한 환경 변수를 설정하기만 하면 됩니다. 그런 다음 파이프라인 설정에 있는 Cron 예약된 빌드를 구성하여 특정 시간마다 시작하면 바로 시작할 수 있습니다. We would then create many other separate pipelines for specific feature pages as needed to run on a schedule in a similar way and we would only vary the Cron schedule and environment variables while once again uploading the same `pipeline.cypress.yml` file to execute.
In each of those “Run Cypress tests” steps, we can see the console output with a link to the recorded test run in the paid Dashboard Service, the central place to manage your team's test recordings, billing, and other Cypress stats. Following the Dashboard Service link would take us to a results view for developers and QAs to take a look at the console output, screenshots, video recordings, and other metadata if required such as this:
Step 6: Comparing Cypress vs. WebdriverIO/STUI
After diving into our own custom Ruby Selenium solution in STUI, WebdriverIO, and finally Cypress tests, we recorded our tradeoffs between Cypress and Selenium wrapper solutions.
장점
- It's not another Selenium wrapper – Our previous solutions came with a lot of Selenium quirks, bugs, and crashes to work around and resolve, whereas Cypress arrived without the same baggage and troubles to deal with in allowing us full access to the browser.
- More resilient selectors – We no longer had to explicitly wait for everything like in WebdriverIO with all the
$(.selector).waitForVisible()
calls and now rely oncy.get(...)
and cy.contains(...)
commands with their default timeout. It will automatically keep on retrying to retrieve the DOM elements and if the test demanded a longer timeout, it is also configurable per command. With less worrying about the waiting logic, our tests became way more readable and easier to chain. - Vastly improved developer experience – Cypress provides a large toolkit with better and more extensive documentation for assertions, commands, and setup. We loved the options of using the Cypress GUI, running in headless mode, executing in the command-line, and chaining more intuitive Cypress commands.
- Significantly better developer efficiency and debugging – When running the Cypress GUI, one has access to all of the browser console to see some helpful output, time travel debug and pause at certain commands in the command log to see before and after screenshots, inspect the DOM with the selector playground, and discern right away at which command the test failed. In WebdriverIO or STUI we struggled with observing the tests run over and over in a browser and then the console errors would not point us toward and would sometimes even lead us astray from where the test really failed in the code. When we opted to run the Cypress tests in headless mode, we got console errors, screenshots, and video recordings. With WebdriverIO we only had some screenshots and confusing console errors. These benefits resulted in us cranking out E2E tests much faster and with less overall time spent wondering why things went wrong. We recorded it took less developers and often around 2 to 3 times less days to write the same level of complicated tests with Cypress than with WebdriverIO or STUI.
- Network stubbing and mocking – With WebdriverIO or STUI, there was no such thing as network stubbing or mocking in comparison to Cypress. Now we can have endpoints return certain values or we can wait for certain endpoints to finish through
cy.server()
andcy.route()
. - Less time to set up locally – With WebdriverIO or STUI, there was a lot of time spent up front researching which reporters, test runners, assertions, and services to use, but with Cypress, it came bundled with everything and started working after just doing an
npm install cypress.
- Less time to set up with Docker – There are a bunch of ways to set up WebdriverIO with Selenium, browser, and application images that took us considerably more time and frustration to figure out in comparison to Cypress's Docker images to use right out of the gate.
- Parallelization with various CICD providers – We were able to configure our Buildkite pipelines to spin up a certain number of AWS machines to run our Cypress tests in parallel to dramatically speed up the overall test run time and uncover any flakiness in tests using the same resources. The Dashboard Service would also recommend to us the optimal number of machines to spin up in parallel for the best test run times.
- Paid Dashboard Service – When we run our Cypress tests in a Docker container in a Buildkite pipeline during CICD, our tests are recorded and stored for us to look at within the past month through a paid Dashboard Service. We have a parent organization for billing and separate projects for each frontend application to check out console output, screenshots, and recordings of all of our test runs.
- Tests are way more consistent and maintainable – Tests passed way more consistently with Cypress in comparison to WebdriverIO and STUI where the tests kept on failing so much to the point where they were often ignored. Cypress tests failing more often signaled actual issues and bugs to look into or suggested better ways to refactor our tests to be less flaky. With WebdriverIO and STUI, we wasted a lot more time in maintaining those tests to be somewhat useful, whereas with Cypress, we would every now and then adjust the tests in response to changes in the backend services or minor changes in the UI.
- Tests are faster – Builds passed way more consistently and overall test run times would be around 2 to 3 times faster when run serially without parallelization. We used to have overall test runs that would take hours with STUI and around 40 minutes with WebdriverIO, but now with way more tests and with the help of parallelization across many machine nodes, we can run over 200 tests in under 5 minutes .
- Room to grow with added features in the future – With a steady open-source presence and dedicated Cypress team working towards releasing way more features and improvements to the Cypress infrastructure, we viewed Cypress as a safer bet to invest in rather than STUI, which would require us to engineer and solve a lot of the headaches ourselves, and WebdriverIO, which appeared to feel more stagnant in new features added but with the same baggage as other Selenium wrappers.
단점
- Lack of cross-browser support – As of this writing, we can only run our tests against Chrome. With WebdriverIO, we could run tests against Chrome, Firefox, Safari, and Opera. STUI also provided some cross-browser testing, though in a much limited form since we created a custom in-house solution
- Cannot integrate with some third-party services – With WebdriverIO, we had the option to integrate with services like BrowserStack and Sauce Labs for cross-browser and device testing. However, with Cypress there are no such third-party integrations but there are some plugins with services like Applitools for visual regression testing available. STUI, on the other hand, also had some small integrations with TestRail , but as a compromise, we log out the TestRail links in our Cypress tests so we can refer back to them if we needed to.
- Requires workarounds to test with iframes – There are some issues around handling iframes with Cypress. We ended up creating a global Cypress command to wrap how to deal with retrieving an iframe's contents as there is no specific API to deal with iframes like how WebdriverIO does.
To summarize our STUI, WebdriverIO, and Cypress comparison, we analyzed the overall developer experience (related to tools, writing tests, debugging, API, documentation, etc.), test run times, test passing rates, and maintenance as displayed in this table:
Following our analysis of the pros and cons of Cypress versus our previous solutions, it was pretty clear Cypress would be our best bet to accomplish our goal of writing fast, valuable, maintainable, and debuggable E2E tests we could integrate with CICD.
Though Cypress lacked features such as cross-browser testing and other integrations with third-party services that we could have had with STUI or WebdriverIO, we most importantly need tests that work more often than not and with the right tools to confidently fix broken ones. If we ever needed cross-browser testing or other integrations we could always still circle back and use our knowledge from our trials and experiences with WebdriverIO and STUI to still run a subset of tests with those frameworks.
We finally presented our findings to the rest of the frontend organization, engineering management, architects, and product. Upon demoing the Cypress test tools and showcasing our results between WebdriverIO/STUI and Cypress, we eventually received approval to standardize and adopt Cypress as our E2E testing library of choice for our frontend teams.
Step 7: Scaling to Other Frontend Teams
After successfully proving that using Cypress was the way to go for our use cases, we then focused on scaling it across all of our frontend teams' repos. We shared lessons learned and patterns of how to get up and running, how to write consistent, maintainable Cypress tests, and of how to hook those tests up during CICD or in scheduled Cypress Buildkite pipelines.
To promote greater visibility of test runs and gain access to a private monthly history of recordings, we established our own organization to be under one billing method to pay for the Dashboard Service with a certain recorded test run limit and maximum number of users in the organization to suit our needs.
Once we set up an umbrella organization, we invited developers and QAs from different frontend teams and each team would install Cypress, open up the Cypress GUI, and inspect the “Runs” and “Settings” tab to get the “Project ID” to place in their `cypress.json` configuration and “Record Key” to provide in their command options to start recording tests to the Dashboard Service. Finally, upon successfully setting up the project and recording tests to the Dashboard Service for the first time, logging into the Dashboard Service would show that team's repo under the “Projects” tab like this:
When we clicked a project like “mako”, we then had access to all of the test runs for that team's repo with quick access to console output, screenshots, and video recordings per test run upon clicking each row as shown below:
For more insights into our integration, we set up many separate dedicated test pipelines to run specific, crucial page tests on a schedule like say every couple hours to once per day. We also added functionality in our main Buildkite CICD deploy pipeline to select and trigger some tests against our feature branch environment and staging environment.
예상할 수 있듯이, 특히 여러 팀이 다양한 방식으로 테스트에 기여하고 트리거하기 때문에 할당된 기록된 테스트 실행을 빠르게 통과했습니다. 경험에 비추어 볼 때 일정에 따라 실행되는 테스트의 수, 해당 테스트의 실행 빈도 및 CICD 동안 실행되는 테스트를 염두에 두는 것이 좋습니다. 일부 중복 테스트 실행 및 예약된 테스트 실행의 빈도를 줄이거나 CICD 동안에만 테스트를 트리거하기 위해 일부를 완전히 제거하는 것과 같이 더 검소한 다른 영역이 있을 수 있습니다.
사용자를 추가하는 데에도 동일한 규칙이 적용됩니다. 이는 제한된 공간을 채우기 위해 상위 경영진 및 해당 팀 외부의 다른 사람들보다 대시보드 서비스를 많이 사용하게 될 프론트엔드 팀의 개발자 및 QA에게만 액세스를 제공하는 것을 강조했기 때문입니다.
Cypress에서 기대하는 것
앞서 언급했듯이 Cypress는 오픈 소스 커뮤니티와 E2E 테스트에 사용할 보다 유용한 기능을 제공하는 전담 팀과 함께 많은 가능성과 성장 가능성을 보여주었습니다. 우리가 강조한 많은 단점이 현재 해결되고 있으며 다음과 같은 사항을 기대합니다.
- 브라우저 간 지원 – 이는 Firefox, Chrome 및 Safari와 같은 브라우저를 지원하는 Selenium 기반 솔루션과 비교하여 Cypress를 채택한 우리의 많은 반발이 Chrome만 사용하기 때문에 발생했기 때문에 큰 것입니다. 고맙게도 우리 조직은 더 안정적이고 유지 관리 가능하며 디버그 가능한 테스트를 얻었으며 Cypress 팀이 이러한 브라우저 간 지원을 릴리스할 때 앞으로 더 많은 브라우저 간 테스트로 테스트 제품군을 향상하기를 바랍니다.
- 네트워크 계층 재작성 – 이것은 우리가 새로운 React 영역과 이전 Backbone/Marionette 애플리케이션 영역에서 여전히 jQuery AJAX 및 일반 XHR 기반 호출을 사용하는 경향이 있기 때문에 Fetch API를 많이 사용하는 경향이 있기 때문에 매우 큰 문제입니다. 우리는 XHR 영역에서 요청을 쉽게 스텁 아웃하거나 수신할 수 있지만 동일한 효과를 얻기 위해 폴리필 가져오기로 몇 가지 해킹 해결 방법을 수행해야 했습니다. 네트워크 계층 재작성은 이러한 고통을 완화하는 데 도움이 됩니다.
- 대시보드 서비스의 점진적 개선 – 최근 대시보드 서비스에 대한 몇 가지 새로운 UI 변경 사항을 이미 확인했으며 더 많은 통계 시각화 및 유용한 데이터 분석으로 계속해서 성장하기를 바랍니다. 우리는 또한 병렬화 기능을 많이 사용하고 대시보드 서비스에서 실패한 테스트 기록을 자주 확인하므로 레이아웃 및/또는 기능에 대한 반복적인 개선이 있으면 좋을 것입니다.
미래에 Cypress 채택
우리 조직의 경우 Chrome 브라우저에서 실행할 때 Cypress 테스트의 개발자 효율성, 디버깅 및 안정성을 높이 평가했습니다. 우리는 새로운 테스트를 개발하고 기존 테스트를 수정하기 위한 많은 도구와 더 적은 유지 관리로 일관되고 가치 있는 테스트를 달성했습니다.
전반적으로 우리가 사용할 수 있는 문서, API 및 도구는 단점을 훨씬 능가했습니다. Cypress GUI와 유료 대시보드 서비스를 경험한 후 WebdriverIO 또는 사용자 지정 Ruby Selenium 솔루션으로 돌아가고 싶지 않았습니다.
우리는 테스트를 Buildkite와 연결 하고 CICD와 통합할 프론트엔드 애플리케이션에 대해 일관되고 디버그 가능하고 유지 관리 가능하고 가치 있는 E2E 자동화 테스트를 작성하는 방법을 제공 한다는 목표를 달성했습니다. 우리는 Cypress를 채택하고 WebdriverIO 및 STUI를 중단하는 이점에 대해 나머지 프론트엔드 팀, 엔지니어링 상위 관리자 및 제품 소유자에게 증거로 증명했습니다.
Twilio SendGrid의 프론트엔드 팀 전반에 걸친 수백 번의 테스트 결과 우리는 스테이징 환경에서 많은 버그를 포착했으며 이전보다 훨씬 더 확신을 갖고 우리 측의 불안정한 테스트를 신속하게 수정할 수 있었습니다. 개발자와 QA는 더 이상 E2E 테스트를 작성하는 것을 두려워하지 않지만 이제 우리가 릴리스하는 모든 단일 새 기능 또는 더 많은 적용 범위를 사용할 수 있는 모든 이전 기능에 대해 작성하기를 기대합니다.