GitLab CI/CD 및 WebdriverIO를 사용한 엔드 투 엔드 테스트

Tier: Free, Premium, Ultimate Offering: GitLab.com, Self-managed, GitLab Dedicated

Review Apps는 대단해요: 매번 머지 요청(또는 브랜치)마다 새로운 코드를 복사하고 실제 프로덕션과 유사한 환경에 배포할 수 있습니다. 이를 통해 변경 사항의 영향을 평가하는 데 드는 노력이 줄어듭니다. 따라서, Dependencies.io와 같은 의존성 관리자를 사용하면 업데이트된 의존성을 포함한 머지 요청을 제출할 수 있고, 애플리케이션이 여전히 올바르게 빌드되고 배포될 수 있음을 즉시 확인할 수 있습니다. 무엇보다도, 그것을 실제로 볼 수 있습니다!

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에 알려줘야 합니다. 이는 capabilities 옵션을 통해 구성할 수 있으며, 이 옵션은 브라우저 이름(예: firefox 또는 chrome)의 배열입니다. 모든 설치된 브라우저를 감지하기 위해 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.jsonscripts 속성에 테스트를 실행하는 라인을 추가할 수 있습니다. 예를 들어:

  "confidence-check": "wdio wdio.conf.js",

이후 npm run confidence-check를 사용하여 테스트를 실행할 수 있으며, 실제로 지정한 대로 앱에서 상호 작용하는 새 브라우저 창이 표시됩니다.

GitLab CI/CD 구성

GitLab CI/CD에서 이것을 어떻게 실행할 수 있는지에 대한 흥미로운 부분으로 넘어가 보겠습니다. 이를 위해 우리는 두 가지를 해야합니다.

  1. 실제로 브라우저를 사용할 수 있는 CI/CD 작업을 설정합니다.
  2. WebdriverIO 구성을 업데이트하여 리뷰 앱을 방문할 때 해당 브라우저를 사용합니다.

이 기사의 범위 내에서 실행하는 추가 CI/CD 단계confidence-check을 정의했습니다. 이는 리뷰 앱을 배포하는 단계 이후 에 실행됩니다. 이는 node:latest Docker 이미지를 사용합니다. 그러나 WebdriverIO는 실제 브라우저를 시작하여 응용 프로그램과 상호 작용하므로 이를 설치하고 실행해야합니다. 또한, WebdriverIO는 다양한 브라우저를 제어하기 위한 공통 인터페이스로 Selenium을 사용하므로 Selenium도 설치하고 실행해야합니다. 다행히도 Selenium 프로젝트는 Firefox용 독립형 Docker 이미지 standalone-firefox 및 Chrome용 standalone-chrome을 제공합니다. (Safari 및 Internet Explorer/Edge는 오픈 소스가 아니며 Linux에 사용할 수 없기 때문에 GitLab CI/CD에서는 사용할 수 없습니다).

GitLab CI/CD는 service 속성을 사용하여 이러한 이미지를 confidence-check 작업에 링크하는 것을 쉽게 만듭니다. 이렇게하면 Selenium 서버가 이미지 이름을 기반으로 한 호스트명으로 사용할 수 있습니다. 그런 다음 작업 구성은 다음과 같습니다.

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-checkhost 옵션의 값을 전달했습니다. 그러나 여전히 WebdriverIO에게 사용 가능한 브라우저를 알려줘야 합니다.

GitLab CI/CD는 현재 CI 작업에 대한 많은 변수를 사용 가능하게 합니다 우리는 이 정보를 사용하여 현재 실행 중인 작업에 따라 WebdriverIO 구성을 동적으로 설정할 수 있습니다. 보다 구체적으로는 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에게 그 아티팩트를 저장하라고 지정하면 GitLab에서 무엇이 잘못되었는지 확인할 수 있습니다.