GitLab CI/CD 및 WebdriverIO와 함께하는 엔드투엔드 테스팅
Review apps가 좋습니다: 각 병합 요청(혹은 브랜치)마다, 새로운 코드를 복제하여 신선한 프로덕션과 유사한 라이브 환경으로 배포할 수 있어 변경의 영향을 평가하는 노력을 줄일 수 있습니다. 따라서, Dependencies.io와 같은 의존성 관리자를 사용하면 업데이트된 종속성이 있는 병합 요청을 제출하고, 여전히 응용 프로그램을 올바르게 빌드하고 배포할 수 있는지 즉시 확인할 수 있습니다. 결국, 실행 중인 것을 볼 수 있습니다!
그러나 신선하게 배포된 코드를 확인하여 여전히 기대한 대로 보이고 작동하는지 확인하는 것은 반복적인 수동 작업이며, 이는 자동화하기에 적합한 후보입니다. 여기서 자동화된 엔드투엔드 테스팅이 등장합니다: 프론트엔드부터 데이터베이스까지 애플리케이션 모든 레이어의 적절한 작동을 요구하는 몇 가지 간단한 시나리오를 컴퓨터가 실행하도록 하는 것입니다.
이 글에서는 이러한 엔드투엔드 테스트를 작성하는 방법과 GitLab CI/CD를 설정하여 브랜치별로 새 코드에 대해 이러한 테스트를 자동으로 실행하는 방법에 대해 논의합니다. 이 글의 범위에서는 WebdriverIO를 사용하여 JavaScript 기반 응용 프로그램에 대한 엔드투엔드 테스트를 위해 GitLab CI/CD를 설정하는 과정을 안내합니다. 그러나 일반적인 전략은 다른 언어에도 적용될 수 있습니다.
여러분이 GitLab, GitLab CI/CD, Review apps, 그리고 로컬에서 앱을 실행하는 방법에 익숙하다고 가정합니다. 예를 들어 localhost:8000
에서 실행합니다.
무엇을 테스트할 것인가
널리 사용되는 테스트 피라미드 전략에서 엔드투엔드 테스트는 보호막과 같은 역할을 합니다: 대부분의 코드가 단위 테스트로 커버되어야 합니다, 이로써 문제의 근원을 쉽게 식별할 수 있습니다. 실제로 엔드투엔드 테스트의 수를 제한하는 것 이 기대치에 맞는 것입니다. 그저 배포가 의도한 대로 이루어졌음을 확신할 수 있는 테스트의 수를 제한하고, 인프라가 제대로 작동하며 코드 단위가 잘 연동되는지 확인하고자 합니다.
Selenium 및 WebdriverIO
Selenium은 웹 브라우저를 제어할 수 있는 소프트웨어로, 예를 들어 특정 URL을 방문하거나 페이지의 요소와 상호 작용하는 등의 작업을 수행할 수 있습니다. 다양한 프로그래밍 언어에서 프로그래밍적으로 제어할 수 있습니다. 이 글에서는 WebdriverIO의 JavaScript 바인딩을 사용할 것이지만, 일반적인 컨셉은 다른 Selenium이 지원하는 프로그래밍 언어로도 충분히 적용될 것입니다.
테스트 작성
WebdriverIO에서 지원하는 여러 테스팅 프레임워크로 테스트를 작성할 수 있습니다. 여기서는 Jasmine를 사용할 것입니다:
describe('계정이 없는 방문자', function(){
it('404 페이지에서 홈페이지로 이동할 수 있어야 합니다', function(){
browser.url('/page-that-does-not-exist');
expect(browser.getUrl()).toMatch('page-that-does-not-exist');
browser.element('.content a[href="/"]').click();
expect(browser.getUrl()).not.toMatch('page-that-does-not-exist');
});
});
describe
, it
및 browser
함수는 WebdriverIO에서 제공됩니다. 이들을 각각 살펴보겠습니다.
describe
함수는 관련된 테스트를 그룹화할 수 있게 합니다. 예를 들어 여러 테스트에 대해 같은 초기화 명령(예: beforeEach
를 사용하여)을 실행하려는 경우에 유용합니다.
it
함수는 개별 테스트를 정의합니다.
browser
객체는 WebdriverIO의 특별한 기능을 제공합니다. 이는 페이지의 요소에 액세스하고 상호작용하는 등 WebdriverIO API 메서드의 대부분을 제공합니다. 이 경우, 우리는 페이지에 접근하기 위해 browser.url
을 사용하여 /page-that-does-not-exist
로 이동하여 404 페이지를 만납니다. 그런 다음 browser.getUrl
을 사용하여 현재 페이지가 지정한 위치에 있는지 확인할 수 있습니다. 페이지와 상호 작용하려면 browser.element
에 CSS 선택기를 전달하여 페이지의 요소에 액세스하고 상호 작용할 수 있습니다(예: 홈페이지로 돌아가기 위해 링크를 선택).
위에 표시된 간단한 테스트는 이미 해당 사항을 충족시킨다는 것을 알면 많은 확신을 줄 수 있습니다: 배포가 성공했다는 것을 알 수 있으며, 요소가 페이지에서 보이고 실제 브라우저가 상호 작용하며 라우팅이 예상대로 작동한다는 것을 알 수 있습니다. 이 모든 것을 과도한 공백을 포함해 10줄로 구성했습니다! 이에 성공하는 단위 테스트와 완료된 파이프라인이 추가되면 웹사이트를 확인하지 않고도 의존성 업그레이드가 아무것도 망가뜨리지 않았다고 상당히 확신할 수 있습니다.
로컬에서 실행
위의 테스트를 CI/CD에서 실행하는 법은 나준에 살펴보겠습니다. 그러나 테스트를 작성할 때는 여러분이 기대하는 대로 기능하는지 확인하기 위해 파이프라인이 성공하기를 기다릴 필요가 없는 것이 도움이 됩니다. 다시 말해, 로컬에서 실행하도록 설정합시다.
로컬에서 앱이 실행되고 있는지 확인하세요. Webpack을 사용하는 경우 Webpack Dev Server WebdriverIO 플러그인을 사용하여 테스트를 수행하기 전에 자동으로 개발 서버를 시작할 수 있습니다.
WebdriverIO 문서에는 모든 구성 옵션에 대한 개요가 있지만, 시작하는 가장 쉬운 방법은 모든 가능한 옵션의 개요를 제공하는 WebdriverIO의 기본 구성으로 시작하는 것입니다. 여기에는 specs
옵션이 있으며, 이는 여러분의 테스트를 가리키는 경로의 배열이고, baseUrl
옵션이 있으며, 이는 앱이 실행되는 위치를 가리킵니다. 마지막으로, 어떤 브라우저에서 테스트를 실행할 것인지 WebdriverIO에 알려줘야 합니다. 이는 브라우저 이름의 배열(예: firefox
또는 chrome
)인 capabilities
옵션으로 구성할 수 있습니다. 모든 설치된 브라우저를 감지하기 위해 selenium-assistant를 설치하는 것이 좋습니다:
const seleniumAssistant = require('selenium-assistant');
const browsers = seleniumAssistant.getLocalBrowsers();
config.capabilities = browsers.map(browser => ({ browserName: browser.getId() }));
물론, config.capabilities = ['firefox']
와 같이 간단한 구성도 작동할 것입니다.
WebdriverIO를 의존성으로 설치했다면(npm install --save-dev webdriverio
), 예를 들어, package.json
의 scripts
속성에 wdio
를 구성 파일 경로와 함께 실행하는 줄을 추가할 수 있습니다. 예:
"confidence-check": "wdio wdio.conf.js",
이후 npm run confidence-check
를 사용하여 테스트를 실행할 수 있으며, 결과적으로 요청한 대로 새 브라우저 창이 앱과 상호 작용할 수 있음을 확인할 수 있습니다.
GitLab CI/CD 구성
여기서 이것을 GitLab CI/CD에서 어떻게 실행하는 지에 대한 흥미로운 부분에 이르렀습니다. 이를 위해 두 가지를 해야합니다.
- 실제로 브라우저를 사용할 수 있는 CI/CD jobs를 설정합니다.
- 웹드라이버IO 구성을 업데이트하여 해당 브라우저를 리뷰 앱을 방문하는 데 사용합니다.
본문의 범위 내에서 리뷰 앱을 배포하는 단계 이후에 실행되는 confidence-check
라는 별도의 CI/CD stage를 정의했습니다. 이 단계에서 node:latest
Docker image를 사용합니다. 그러나 WebdriverIO에서는 응용 프로그램과 상호 작용하기 위해 실제 브라우저를 시작해야 하므로 이를 설치하고 실행해야 합니다. 또한, WebdriverIO는 다양한 브라우저를 제어하기 위한 공통 인터페이스로 Selenium을 사용하므로 Selenium을 설치하고 실행해야 합니다. 다행히 Selenium 프로젝트는 Firefox용 Docker 이미지 standalone-firefox 및 Chrome용 Docker 이미지 standalone-chrome를 제공합니다. (Safari 및 Internet Explorer/Edge는 오픈 소스가 아니며 Linux에서 사용할 수 없기 때문에 GitLab CI/CD에서 사용할 수 없습니다).
GitLab CI/CD를 사용하면, services
속성을 사용하여 이러한 이미지를 confidence-check
jobs에 연결하는 것이 매우 간단해집니다. 이로써 Selenium 서버는 이미지 이름을 기반으로 한 호스트명으로 사용할 수 있게 됩니다.
언더스코어(_)가 있는 호스트명은 RFC 유효하지 않으며, 서드파티 애플리케이션에서 문제를 일으킬 수 있습니다. 자세한 정보는 services에 접근을 참조하세요.
예를 들어, Firefox의 작업 구성은 다음과 같습니다.
e2e:firefox:
stage: confidence-check
services:
- selenium/standalone-firefox
script:
- npm run confidence-check --host=selenium__standalone-firefox
Chrome의 경우도 마찬가지입니다.
e2e:chrome:
stage: confidence-check
services:
- selenium/standalone-chrome
script:
- npm run confidence-check --host=selenium__standalone-chrome
이제 우리에게는 엔드 투 엔드 테스트를 실행할 작업이 있으므로, WebdriverIO에게 어떻게 Selenium 서버에 연결할지 알려주어야 합니다. 이미 위에서 npm run confidence-check
명령줄 인수로 host
옵션 값을 넘겼지만, 여전히 WebdriverIO에게 사용할 수있는 브라우저를 알려주어야 합니다.
GitLab CI/CD는 현재 CI 작업에 관한 여러 변수를 사용할 수 있게 하며, 우리는 이 정보를 사용하여 실행 중인 작업의 이름에 따라 웹드라이버IO 구성을 동적으로 설정할 수 있습니다. 보다 구체적으로는 현재 실행 중인 작업의 이름에 따라 테스트를 실행할 브라우저를 WebdriverIO에게 알릴 수 있습니다. 이를 위해 위에서 wdio.conf.js
로 명명한 WebdriverIO 구성 파일을 사용할 수 있습니다.
if(process.env.CI_JOB_NAME) {
dynamicConfig.capabilities = [
{ browserName: process.env.CI_JOB_NAME === 'e2e:chrome' ? 'chrome' : 'firefox' },
];
}
마찬가지로, WebdriverIO에게 리뷰 앱이 실행되는 위치에 대해 알릴 수 있습니다 - 이 예제의 경우 <branch name>.flockademic.com
에 있습니다.
if(process.env.CI_COMMIT_REF_SLUG) {
dynamicConfig.baseUrl = `https://${process.env.CI_COMMIT_REF_SLUG}.flockademic.com`;
}
그리고 if (!process.env.CI)
를 사용하여 로컬별 구성이 CI에서 실행되지 않을 때만 사용한다. 이것으로 GitLab CI/CD에서 엔드 투 엔드 테스트를 실행하는 데 필요한 모든 구성이 갖추어졌습니다.
요약하면, 우리의 .gitlab-ci.yml
구성 파일은 다음과 같습니다.
default:
image: node:8.10
stages:
- deploy
- confidence-check
deploy_terraform:
stage: deploy
script:
# 리뷰 앱 배포 스크립트 - 작동하는 예제는 https://gitlab.com/Flockademic/Flockademic/blob/5a45f1c2412e93810fab50e2dab8949e2d0633c7/.gitlab-ci.yml#L315를 확인하세요
- echo
environment: production
e2e:firefox:
stage: confidence-check
services:
- selenium/standalone-firefox
script:
- npm run confidence-check --host=selenium__standalone-firefox
e2e:chrome:
stage: confidence-check
services:
- selenium/standalone-chrome
script:
- npm run confidence-check --host=selenium__standalone-chrome
다음 단계
자신을 위해 이를 설정하고 프로덕션 프로젝트의 작동 구성을 확인하려면 다음을 참조하세요:
WebdriverIO가 할 수 있는 것은 훨씬 많습니다. 예를 들어 screenshotPath
를 구성하여 테스트가 실패할 때 WebdriverIO에게 스크린샷을 촬영하도록 지시할 수 있습니다. 그런 다음 GitLab CI/CD에게 해당 artifacts를 저장하도록 하여 GitLab 내에서 무엇이 잘못되었는지 확인할 수 있게 됩니다.