Computer >> 컴퓨터 >  >> 프로그램 작성 >> Ruby

Rails 앱을 테스트하기 위한 Docker 컨테이너 설정

Ruby/Rails 개발자로서 우리는 테스트 작성을 좋아합니다. 테스트는 소프트웨어 개발의 필수적인 부분입니다. 좋은 테스트는 고품질 코드를 작성하는 데 도움이 됩니다. 그들은 전체 개발 프로세스에 가치를 더하지만 테스트를 잘 관리하지 않으면 속도가 느려질 수 있습니다. 다음은 부적절하게 관리되는 테스트의 일부 증상입니다.

  • 테스트를 실행하는 데 시간이 오래 걸립니다.
  • 테스트는 신뢰할 수 없으며 무작위로 실패합니다.
  • 테스트는 시스템마다 다르게 작동합니다.
  • 모든 테스트 모음을 실행하면 CI가 느려집니다.

이 블로그 게시물에서는 컨테이너를 사용하여 고품질 소프트웨어를 제공하는 데 도움이 되는 신뢰할 수 있는 테스트를 만드는 방법에 대해 설명합니다.

통합 테스트 및 단위 테스트

컨테이너 주제로 넘어가기 전에 먼저 단위 테스트와 통합 테스트의 차이점을 이해하고 같은 페이지에 있도록 합시다.

단위 테스트는 코드 블록을 분리하여 테스트하는 방법입니다. 코드 블록의 기능을 테스트하는 데 도움이 되지만 종속성은 테스트하지 않습니다. 예를 들어 다음은 간단한 방법입니다.

def sum(a, b)
  a + b
end

이것은 두 개의 숫자를 더하는 함수로 매우 간단합니다. 이 기능을 테스트하는 것은 매우 쉬울 것입니다. 그러나 이 함수가 외부 서비스에 종속되어 있으면 어떻게 될까요? 이 메서드는 합계가 완료되면 데이터베이스에 기록해야 합니다.

  def sum!(a, b)
    c = a + b
    Sum.create(value: c)
  end

이 코드 블록에서 값이 추가되고 데이터베이스에 저장됩니다. 이 코드 블록을 테스트하려면 데이터베이스 서버를 실행해야 합니다. 실행 중인 데이터베이스 서버에서 이것을 테스트하면 더 이상 단위 테스트가 아닙니다. 이것은 외부 종속성이 필요하며 데이터베이스 연결과 레코드가 데이터베이스에 저장되는지 여부도 테스트합니다. 이 경우 이 테스트는 통합 테스트입니다.

단위 테스트는 단독 단위 테스트일 수 있습니다. (모든 종속성을 모의/스텁) 또는 소셜 단위 테스트 (다른 종속성과의 대화 허용). 사람들은 단위 테스트에 대한 다양한 정의를 제안했습니다. 이 블로그 컨텍스트에서 우리가 말하는 단위 테스트 유형은 단독 단위 테스트입니다.

mock으로 외부 종속성을 제거하면 테스트를 더 빠르게 실행할 수 있습니다. 단위 테스트를 사용하는 동안 이러한 종속성을 생략하지만 애플리케이션이 예상대로 작동하는지 확인하려면 종속성을 테스트하는 것도 똑같이 중요합니다. 데이터베이스, 네트워크 호출 및 파일과 같은 이러한 외부 종속성을 테스트하기 위해 작성하는 테스트는 통합 테스트입니다. .

단위 테스트와 마찬가지로 사람들은 통합 테스트에 대한 다양한 정의를 제안했습니다. 그러나 기본 개념은 동일합니다. 차이점은 범위에만 있습니다. 데이터베이스에 쓰는 작은 기능은 통합 테스트가 될 수 있습니다. 시스템의 여러 부분을 연결하는 광범위한 기능도 통합 테스트입니다. 여기서 말하는 테스트는 좁은 부분에 더 초점을 맞추고 있습니다. 테스트가 좁을수록 더 많은 테스트를 작성해야 합니다. 그러나 테스트 범위가 넓을수록 필요한 테스트 수가 줄어듭니다.

통합 테스트를 실행하는 동안 데이터베이스 및 외부 서비스와 같은 애플리케이션과 종속성이 실행되어야 합니다. 이러한 종속성을 관리하는 것은 어려울 수 있습니다.

도커의 기초

Docker는 환경(운영 체제)에서 응용 프로그램을 추상화하고 호스트와 격리하여 실행하는 데 도움이 되는 기술입니다. 이것은 가상 머신과 유사하지만 더 빠르고 효율적입니다. Docker를 사용하면 애플리케이션 코드와 해당 종속성을 단일 컨테이너에 패키징할 수 있습니다. 이는 코드를 이식 가능하게 만드는 데 도움이 되며 개발, 테스트 및 프로덕션 중에 동일한 Docker 이미지를 실행할 수 있음을 의미합니다. 이렇게 하면 응용 프로그램이 실행되는 환경의 일관성이 보장됩니다. 호스트 서버에 의존하지 않기 때문에 모든 환경에서 애플리케이션의 동작을 예측할 수 있습니다. Docker는 개발자가 간단한 명령을 사용한 빌드, 실행, 배포 및 업데이트를 포함하여 애플리케이션과 해당 환경을 실행하고 관리하는 데 도움이 됩니다.

몇 가지 중요한 용어를 알아보겠습니다.

  • 도커파일 - Dockerfile은 단순히 애플리케이션에 필요한 종속성을 정의하는 파일입니다. 필요한 운영 체제, 데이터베이스 클라이언트 라이브러리 또는 애플리케이션에 필요한 패키지를 지정할 수 있습니다. 여기에서는 응용 프로그램을 실행하는 데 필요한 명령도 정의합니다. Dockerfile은 기본 이미지에서 시작합니다. 이러한 기본 이미지는 운영 체제 또는 프로그래밍 언어일 수 있습니다.

  • 이미지 - 이미지는 컨테이너를 실행하는 데 필요한 단계를 나타내는 청사진입니다. 이미지는 다른 레이어로 만들어집니다. Dockerfile에 정의된 모든 단계는 이미지 내의 계층입니다. 이렇게 하면 재사용성이 증가하고 중간 레이어를 캐싱하여 이미지를 더 빠르게 빌드하는 데 도움이 됩니다.

  • 컨테이너 - 용기는 실제 이미지입니다. 정지 상태에서도 가능합니다. 컨테이너는 도커 이미지에서 시작할 수 있습니다. 단일 도커 이미지는 여러 도커 컨테이너를 시작할 수 있습니다. 컨테이너는 이미지에 지정된 정보를 보유합니다. 애플리케이션이 실행되는 동안 이미지에 대한 모든 변경 사항이 저장되는 얇은 컨테이너 레이어가 있습니다.

  • 도커 작성 - Docker Compose는 여러 컨테이너를 관리하는 데 도움이 되는 다른 도구입니다. 동일한 도커 이미지에서 여러 컨테이너를 가질 수 있습니다. 또한 서로 다른 도커 이미지의 여러 컨테이너가 필요할 수 있으며 이러한 컨테이너는 서로 상호 작용해야 합니다. Docker Compose는 컨테이너를 관리합니다. 사용 가능한 다른 도구가 있지만 이 컨텍스트에서는 단순성 때문에 Docker Compose만 사용합니다.

가상 머신은 호스트 하이퍼바이저 위에 있으며 별도의 운영 체제를 설치해야 하므로 더 많은 호스트 리소스가 사용됩니다. 그러나 Docker를 사용하면 호스트 운영 체제에 Docker 엔진만 설치하면 되며 호스트 리소스 관리는 Docker가 수행합니다. Docker는 개발자와 sysops 모두의 삶을 더 쉽게 만들어 주므로 DevOps 문화에서 매우 인기가 있습니다.

테스트에 Docker를 사용하는 이유

Docker는 실행 중인 애플리케이션 또는 테스트를 최소한의 리소스 소비로 호스트 환경에서 격리합니다. 다음은 테스트에 docker를 사용할 때의 이점입니다.

  • 경량: Docker 컨테이너는 가볍습니다. 이렇게 하면 한 테스트 프로세스가 다른 테스트 프로세스에서 문제를 일으키지 않고 동시에 여러 컨테이너를 실행하는 데 도움이 됩니다.

  • 휴대용: Docker 이미지는 이식 가능하며 모든 환경에서 실행할 수 있습니다. 동일한 이미지를 재사용하여 로컬 및 CI 환경에서 테스트를 실행할 수 있으므로 CI에 도움이 됩니다.

  • 버전 관리: 여러 애플리케이션을 사용하거나 종속성을 업그레이드하려면 로컬 시스템에 다른 버전의 종속성이 필요합니다. Docker 없이는 관리하기가 매우 어렵습니다. Docker를 사용하면 다른 버전으로 다른 컨테이너를 실행할 수 있습니다. 다른 버전에서 테스트를 실행하고 확인할 수도 있습니다.

  • 마이크로서비스의 손쉬운 관리 :마이크로서비스를 사용하면 테스트도 분산되고 복잡해집니다. 즉, 종속 마이크로 서비스를 관리해야 합니다. Docker 및 Docker Compose는 이러한 서비스 종속성을 관리하는 데 도움이 됩니다.

필수 조건

이를 시도하려면 다음이 설정되어 있는지 확인하세요.

  • 도커
  • 도커 작성
  • Ruby 2.7(선택 사항, Ruby를 Docker 컨테이너에 추가하지만 테스트에 유용함)
  • 레일(5.1 이상 권장)

앱 고정화

간단한 Rails 앱을 만들고 컨테이너화하는 것부터 시작하겠습니다. 저는 새로운 Rails 앱으로 시작하고 있습니다. 기존 Rails 앱을 컨테이너화할 수도 있습니다.

rails new calculator

Dockerfile이라는 파일을 만듭니다. 다음 콘텐츠와 함께:

FROM ruby:2.7
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update -qq && apt-get install -y nodejs yarn
RUN mkdir /calculator
WORKDIR /calculator
COPY Gemfile /calculator/Gemfile
COPY Gemfile.lock /calculator/Gemfile.lock
RUN bundle install
COPY package.json /calculator/package.json
COPY yarn.lock /calculator/yarn.lock
RUN yarn install --check-files
COPY . /calculator
EXPOSE 3000
CMD ["rails", "server", "-b", "0.0.0.0"]

우리가 정의한 Dockerfile에는 Ruby 2.7 기본 이미지가 있습니다. NodeJS와 Yarn이 필요하므로 다음 단계는 이를 설치하는 것입니다. 설치가 완료되면 bundle install를 실행합니다. 및 yarn install . 마지막으로 모든 코드를 복사하고 3000 포트를 내보낸 Rails 서버를 실행합니다. 이것은 매우 간단한 Dockerfile입니다. 이를 통해 Rails 앱이 고정됩니다.

이제 docker 이미지를 만들고 실행하여 실행 중인지 확인할 수 있습니다.

도커 이미지 빌드:

docker build . -t  calculator

컨테이너 실행:

docker run -p 3000:3000 calculator

계산 논리로 모델 만들기

계산 논리를 추가할 수 있는 계산이라는 모델을 만들어 보겠습니다. 우리는 이 모델을 사용하여 로직과 테스트를 작성할 것입니다. Docker Compose를 사용하여 이러한 테스트의 종속성을 관리하는 방법을 살펴볼 수 있습니다.

우리는 현재 SQLite와 함께 Rails를 실행하고 있습니다. SQLite 대신 Postgres로 변경해 보겠습니다. 다음 명령으로 쉽게 수행할 수 있습니다.

rails db:system:change --to=postgresql

계산 모델 생성:

bundle exec rails generate model calculation

계산 스키마에 일부 필드 추가:

# db/migrate/create_calculation.rb

class CreateCalculations < ActiveRecord::Migration[6.0]
  def change
    create_table :calculations do |t|
      t.integer :x
      t.integer :y
      t.integer :result
      t.timestamps
    end
  end
end

다음으로 컨테이너 내부에서 데이터베이스 마이그레이션을 실행해 보겠습니다.

docker-compose exec web rails db:migrate

데이터베이스가 컨테이너 내부에서 실행되고 있지 않기 때문에 이 명령을 실행하면 오류가 발생합니다.

rake aborted!
PG::ConnectionBad: could not connect to server: No such file or directory
  Is the server running locally and accepting
  connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?

Postgres 이미지를 다른 이미지로 실행하고 이들 사이에 네트워크를 추가할 수 있습니다. 이 컨테이너 통신을 관리하기 위해 Docker Compose를 사용할 수 있습니다.

Docker Compose를 사용하여 여러 컨테이너 관리

Rails 앱을 컨테이너화하면 Docker Compose를 사용하여 서비스에 종속성을 추가할 수 있습니다. 애플리케이션에 대한 종속성은 Postgres입니다.

Postgres Docker 이미지는 공개적으로 사용할 수 있으므로 만들 필요가 없습니다. 그러나 데이터베이스 컨테이너와 Rails 앱 컨테이너를 관리해야 합니다.

version: "3.0"
services:
  db:
    image: postgres
    environment:
      POSTGRES_USER: calculator
      POSTGRES_PASSWORD: password
      POSTGRES_DB: calculator_test
  web:
    build: .
    ports:
      - "3000:3000"
    depends_on:
      - db
    environment:
      CALCULATOR_DATABASE_PASSWORD: password

이제 database.yaml로 이동합니다. 파일을 만들고 데이터베이스를 다른 호스트로 변경합니다. 호스트는 Docker Compose 파일의 서비스 내부에 지정된 이름입니다. 우리의 경우 호스트는 db입니다. . postgres에서 DB 비밀번호가 동일한지 확인하십시오. 서비스 및 web 서비스. 또한 Docker Compose 파일에 지정된 대로 사용자 이름, 비밀번호 및 데이터베이스 이름을 변경하십시오.

# database.yaml

development:
  <<: *default
  database: calculator_development
  username: calculator
  password: <%= ENV['CALCULATOR_DATABASE_PASSWORD'] %>

이제 단일 명령을 사용하여 컨테이너를 시작할 수 있습니다.

docker-compose up

그러면 데이터베이스와 Rails 서버가 모두 시작됩니다. 이제 마이그레이션 명령을 실행할 수 있으며 Postgres에 연결하여 마이그레이션을 실행할 수 있어야 합니다.

테스트 추가

이제 모든 설정이 준비되었으므로 모델 내부에 간단한 메서드를 작성하고 메서드를 테스트해 보겠습니다.

# calculation.rb

class Calculation < ApplicationRecord

  def self.sum(x, y)
    result = x + y
    Calculation.create(x: x, y: y, result: result)
    result
  end

end

이 합계 방법은 숫자를 추가할 뿐만 아니라 숫자를 데이터베이스에 저장합니다. 따라서 이 방법을 테스트하려면 데이터베이스 인스턴스가 실행 중이어야 합니다.

이 테스트는 데이터베이스에 연결해야 하므로 통합 테스트가 될 것입니다.

Rails 기본값인 Mini-test를 사용하여 테스트를 작성합니다.

# calculation_test.rb

require 'test_helper'

class CalculationTest < ActiveSupport::TestCase
  test "should sum and save the data" do
    result = Calculation.sum(1, 2)
    c = Calculation.last
    assert result, 3
    assert c.result, result
  end
end

테스트 실행:

docker-compose exec web rails test

위의 테스트에서는 sum 메소드가 값을 더하고 데이터베이스에 저장하는지 테스트하고 있습니다. Docker Compose를 사용하면 데이터베이스에 매우 쉽게 연결할 수 있습니다.

여기서 방법은 데이터베이스에 따라 다릅니다. 종속성은 데이터베이스뿐만 아니라 REST API를 제공하는 타사 서비스일 수도 있습니다. 따라서 sum을 제공하는 타사 서비스를 사용해 보겠습니다. 직접 작성하는 대신 사용할 수 있는 방법입니다.

# calculation.rb

class Calculation < ApplicationRecord

  def self.sum(x, y)
    # The hostname should be the same as it is specified in the docker-compose file
    url = 'https://sumservice:4010/sum'

    uri = URI(url)
    params = { :x => x, :y => y }
    uri.query = URI.encode_www_form(params)
    res = Net::HTTP.get_response(uri)
    throw "Error"  unless res.is_a?(Net::HTTPSuccess)
    result = res.body.to_i
    Calculation.create(x: x, y: y, result: result)
    result
  end

end

데이터베이스에 대해 종속성으로 수행한 것과 유사한 REST API를 수행할 수 있습니다. 이것이 유효한 끝점인지 확인해야 하지만 테스트 중에 실제 서비스를 호출하고 싶지는 않습니다. 이 경우 모의/스텁 테스트를 만들 수 있지만 그렇게 하면 이러한 테스트는 통합 테스트가 아닙니다. 우리는 테스트가 가능한 한 현실적이도록 하고 싶습니다. 이를 위해 컨테이너에서 실행할 모의 API 엔드포인트를 만들고 모의 컨테이너 API 서비스를 호출하면 결과로 응답합니다.

먼저 테스트를 수정해 보겠습니다.

# calculation_test.rb

require 'test_helper'

class CalculationTest < ActiveSupport::TestCase
  test "should sum and save the data" do
    result = Calculation.sum(1, 2)
    c = Calculation.last
    #  we don't need this assetion as we are deligation this responsibility to external service:
    # assert result, 3 // Not needed
    assert c.result, result
  end
end

여기서는 sum API에서 제공하는 결과가 데이터베이스에 제대로 저장되는지 테스트만 하도록 테스트 케이스를 수정했다. 합계의 실제 값이 올바른지 테스트할 필요가 없습니다. 이는 외부 서비스에서 처리하고 우리는 이를 신뢰하기 때문입니다.

모의 서버를 생성하기 위해 우리는 openAPI를 사용할 것입니다. 간단한 swagger 정의를 만들어 보겠습니다.

루트 디렉토리에 새 폴더를 만들고 이름을 mock로 지정합니다. . 폴더 안에 api.yaml 파일 이름을 만듭니다.

# api.yaml
swagger: "2.0"
info:
  description: "This is a sum api provider"
  version: "1.0.0"
  title: "API Provider"
host: "https://mock-service.com/"
basePath: "/api"
schemes:
  - "https"
  - "http"
paths:
  /sum:
    get:
      produces:
        - "application/json"
      parameters:
        - name: "x"
          in: "query"
          description: "x value"
          required: true
          type: "integer"
        - name: "y"
          in: "query"
          description: "y value"
          required: true
          type: "integer"
      responses:
        "200":
          description: "successful operation"
          schema:
            type: "integer"
            example: 3

사양에 따라 이 서버를 실행하려면 모든 모의 서비스 공급자를 사용할 수 있습니다. 프리즘이라는 도구를 사용하겠습니다. 사용 가능한 도커 이미지가 있으며 docker-compose 파일에 추가할 수 있습니다.

version: "3.0"
services:
  db:
    image: postgres
    environment:
      POSTGRES_USER: calculator
      POSTGRES_PASSWORD: password
      POSTGRES_DB: calculator_test
  web:
    build: .
    ports:
      - "3000:3000"
    depends_on:
      - db
      - sumservice
    environment:
      CALCULATOR_DATABASE_PASSWORD: password
  sumservice:
    image: stoplight/prism:4
    command: mock -h 0.0.0.0 "/tmp/api.yaml"
    volumes:
      - ./mock:/tmp/
    ports:
      - 4010:4010
    init: true

이제 테스트를 실행하고 예상대로 작동하는지 확인합니다.

> docker-compose exec web rails test

Finished in 0.337710s, 2.9611 runs/s, 5.9222 assertions/s.
1 runs, 2 assertions, 0 failures, 0 errors, 0 skips

응! 이제 테스트가 실행됩니다. 이 메서드는 합계 서비스 Docker 이미지에 연결하여 합계를 가져오고 Postgres에 연결하여 데이터를 저장합니다. 모든 종속성은 Docker Compose에서 관리하므로 이전에 설치된 종속성에 대해 걱정할 필요가 없습니다. 이 테스트를 모든 시스템으로 이동하면 종속성 설치가 필요하지 않습니다. 기계에 필요한 유일한 것은 도커입니다.

애플리케이션이 Redis 또는 Memcached와 같은 다른 종속성에 의존하는 경우 dockerhub에서 찾을 수 있습니다. 필요에 따라 이러한 이미지를 Docker Compose 파일에 추가할 수 있습니다.

병렬 테스트

Rails 5.1.5+는 병렬 테스트 실행을 지원합니다. 기본적으로 테스트는 프로세서 수에 따라 Rails 6에서 병렬로 실행됩니다. 테스트를 실행하는 동안 병렬 테스트 수를 기반으로 데이터베이스 인스턴스를 생성합니다. 4개의 프로세서가 있는 경우 "calculator_test-0",calculator_test-1,calculator_test-2,calculator_test-3데이터베이스를 생성합니다. postgres cli로 이동하여 데이터베이스를 확인하면 다음과 같이 표시됩니다.

> \l
                                        List of databases
       Name        |   Owner    | Encoding |  Collate   |   Ctype    |     Access privileges
-------------------+------------+----------+------------+------------+---------------------------
 calculator_test   | calculator | UTF8     | en_US.utf8 | en_US.utf8 |
 calculator_test-0 | calculator | UTF8     | en_US.utf8 | en_US.utf8 |
 calculator_test-1 | calculator | UTF8     | en_US.utf8 | en_US.utf8 |
 calculator_test-2 | calculator | UTF8     | en_US.utf8 | en_US.utf8 |
 calculator_test-3 | calculator | UTF8     | en_US.utf8 | en_US.utf8 |

이제 Rails 또는 미니 테스트를 사용하지 않거나 이전 버전의 Rails가 있더라도 Docker로 테스트를 작성하면 테스트를 병렬로 실행할 수 있습니다. Rails는 병렬 테스트를 위한 데이터베이스를 자동으로 생성하지만 Redis 또는 memcached와 같은 다른 종속성이 있는 경우 수동으로 관리해야 할 수도 있습니다.

모든 종속성을 관리하므로 다른 인수로 Docker Compose를 실행하여 테스트를 병렬로 실행할 수 있습니다. 이를 위해 병렬로 테스트를 실행할 폴더를 지정하고, 여러 Docker Compose 파일 생성을 실행하고, 병렬로 실행할 수 있습니다.

명령을 단순화하기 위해 Makefile 추가

테스트를 실행하기 위해 Docker 및 Docker Compose 명령을 사용했기 때문에 명령이 깁니다. 일상적인 개발을 수행하는 동안 기억하고 실행하기 어려울 수 있습니다. 간단한 명령으로 단순화하기 위해 add Makefile을 사용하겠습니다. Makefile은 대상 명령 실행을 참조하는 데 사용되는 간단한 텍스트 파일입니다.

.PHONY: test
up:
  docker-compose up
down:
  docker-compose down
test:
  docker-compose exec web rails test

makefile에 몇 가지 명령을 추가했습니다. 이것은 응용 프로그램의 요구에 따라 확장될 수 있습니다. Rails 애플리케이션의 루트 디렉토리에 makefile을 추가하십시오. 이 makefile이 있으면 다음 명령을 사용하여 간단히 테스트를 실행할 수 있습니다.

컨테이너 부팅:

> make up

테스트 실행:

> make test

로컬 개발을 위해 Docker 사용

애플리케이션을 개발하는 동안 Docker를 사용할 수도 있습니다. 이는 애플리케이션이 테스트, 개발 및 프로덕션 전반에 걸쳐 일관되게 작동하도록 하는 데 도움이 됩니다. 위의 컨테이너를 로컬 개발에 사용하기 위해 변경해야 할 사항을 검토해 보겠습니다.

볼륨 마운트

애플리케이션을 로컬로 실행하는 동안 코드를 변경할 때 애플리케이션이 로컬 서버의 변경 사항을 반영하기를 원합니다. 현재 시나리오에서는 코드가 머신에서 Docker로 복사되고 서버가 시작됩니다. 따라서 로컬 시스템에서 파일을 변경하면 Docker에 반영되지 않습니다. 코드가 항상 동기화되도록 하기 위해 볼륨 마운트를 사용할 수 있습니다.

Docker Compose 파일에서 볼륨을 추가합니다.

version: "3.0"
services:
  db:
    image: postgres
    environment:
      POSTGRES_USER: calculator
      POSTGRES_PASSWORD: password
      POSTGRES_DB: calculator_test
  web:
    build: .
    volumes:
      - .:/calculator # Volume mounted
    ports:
      - "3000:3000"
    depends_on:
      - db
      - sumservice
    environment:
      CALCULATOR_DATABASE_PASSWORD: password
  sumservice:
    image: stoplight/prism:4
    command: mock -h 0.0.0.0 "/tmp/api.yaml"
    volumes:
      - ./mock:/tmp/
    ports:
      - 4010:4010
    init: true

이제 서버를 변경하면 변경 사항이 반영됩니다. 컨트롤러를 만들고 sum 메소드를 호출하여 이것을 시도해보자:

# controllers/calculation_controller.rb
class CalculationController < ApplicationController
  def index
    result = Calculation.sum(params[:x], params[:y])
    render json: {result: result}
  end
end

루트 경로 추가:

# routes.rb

Rails.application.routes.draw do
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
  root "calculation#index"
end

이제 돌아가서 브라우저에서 앱을 확인하면 예상 응답을 얻습니다.

Rails 앱을 테스트하기 위한 Docker 컨테이너 설정

모의 sumservice를 사용하여 서버를 시작한다는 점에 유의하세요. , 그래서 우리가 URL에 쿼리 매개변수로 무엇을 제공하는지에 관계없이 항상 2를 반환합니다. 이것은 개발을 하기에 좋은 방법은 아닌 것 같지만 모의 서비스 공급자를 사용하는 것은 장점이 있습니다. 마이크로 서비스를 개발할 때 많은 종속 서비스가 있을 수 있으며 서비스를 시작하기 전에 부팅해야 합니다. 이는 개발 중 생산성을 높이는 데 도움이 됩니다. 우리는 다른 서비스에 관심이 없으며 우리가 개발하는 서비스에만 관심이 있습니다.

실제 서비스와 어떻게 작동하는지 최종 확인하려면 새 Docker Compose 파일을 만들고 서비스의 실제 이미지로 교체하면 됩니다. 내부 서비스라면 안정적인 최신 Docker 이미지로 간단히 교체할 수 있습니다. 개발 환경에서도 모의 서비스를 제공하는 것이 좋습니다.

.dockerignore

애플리케이션이 커지면 종속성으로 인해 Docker 빌드 컨텍스트가 커집니다. 빌드 컨텍스트가 클수록 도커 이미지를 빌드하는 데 더 많은 시간이 걸립니다. 볼륨 마운트도 응용 프로그램의 크기가 커짐에 따라 지연이 발생할 수 있습니다. 이 경우 원치 않는 파일을 .dockerignore에 추가할 수 있습니다. 빌드 컨텍스트를 줄이기 위한 파일입니다.

.git*
log/*
README.md
node_modules

진입점

Rails 서버가 컨테이너에서 실행되는 동안 컨테이너가 종료될 때 PID 파일이 삭제되지 않았기 때문에 서버가 이미 실행 중이라는 오류 메시지가 표시되는 경우가 있습니다. 이 오류를 제거하기 위해 server.pid를 제거하는 ENTRYPOINT를 추가할 수 있습니다. 파일.

FROM ruby:2.7
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add -
RUN echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update -qq && apt-get install -y nodejs yarn
RUN mkdir /calculator
WORKDIR /calculator
COPY Gemfile /calculator/Gemfile
COPY Gemfile.lock /calculator/Gemfile.lock
RUN bundle install
COPY package.json /calculator/package.json
COPY yarn.lock /calculator/yarn.lock
RUN yarn install --check-files
COPY . /calculator
EXPOSE 3000
ENTRYPOINT ./entrypoint.sh
CMD ["rails", "server", "-b", "0.0.0.0"]

entrypoint.sh 생성 파일:

#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /calculator/tmp/pids/server.pid

# Exec the container's main process (CMD command in rails file)
exec "$@"

실행 가능하게 만들기

chmod +x entrypoint.sh

이제 Docker 이미지를 실행할 때 이 문제가 발생하지 않습니다.

결론

통합 테스트와 단위 테스트를 구별하는 것은 매우 중요합니다. 단위 테스트를 작성하는 동안 데이터베이스와 같은 외부 종속성을 모의할 수 있습니다. 이렇게 하면 코드를 격리된 상태로 테스트하는 데 도움이 됩니다. 핵심 비즈니스 로직과 해당 종속성 간의 통합 테스트를 실행하는 것도 마찬가지로 중요합니다. 데이터베이스 및 외부 서비스와 같은 종속성은 Docker 및 Docker Compose를 사용하여 통합에서 테스트할 수 있습니다. 이 둘을 분리하는 것이 좋습니다. 별도로 실행할 수 있어야 합니다. 더 많은 단위 테스트와 더 적은 수의 통합 테스트가 있으면 테스트가 더 빠르고 안정적으로 실행됩니다.

이 워크플로의 몇 가지 장점은 다음과 같습니다.

  • 단위 테스트와 통합 테스트 간의 분리
  • 모든 CI 서비스가 컨테이너에서 실행되기 때문에 로컬 및 CI에서 실행되는 테스트는 동일한 동작을 갖습니다. 이는 로컬 시스템과 CI 서버에서 테스트 동작의 일관성을 보장하는 데 도움이 됩니다.
  • 컨테이너를 사용하여 애플리케이션을 배포하면 프로덕션 서버의 일관성을 보장하는 데도 도움이 됩니다.
  • 종속성이 잘 관리되므로 신뢰할 수 있는 테스트입니다.
  • 휴대용 테스트, 여러 개발자가 사용할 때 설정에 약간의 노력이 필요합니다.