Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

ทดสอบ Rails App ใน Docker อย่างง่ายดาย: คู่มือทีละขั้นตอน

ในฐานะ Ruby/Rails developers เราชอบเขียน tests Testing เป็นส่วนสำคัญของ software development Good tests ช่วยให้เราเขียน high-quality code พวกมันเพิ่มค่าให้ overall development process แตถ้าเราไม่ manage tests ให้ดี พวกมันอาจช้าลงนเรา นี่คือ symptoms ของ tests ที่ managed ไม่ถูกต้อง:

  • Running tests ใช้เวลานาน
  • Tests unreliable และ fail randomly
  • Tests behave differently บน machines ต่างๆ
  • Running all test suites ช้าลง CI

ในบล็อกนี้ เราจะครอบคลุมว่า containers สามารถใช้ทำให้ testing reliable ซึ่งช่วย deliver high-quality software

Integration Tests และ Unit Tests

ก่อน jump เข้าหัวข้อ containers ให้เราเข้าใจและอยู่หน้าเดียวกันก่อนเกี่ยวกับความต่างระหว่าง unit และ integration tests

Unit tests เป็นวิธี test block of code ใน isolation พวกมันช่วย test functionality ของ block of code แตไม่ใช่ dependencies ตัวอย่าง นี่คือ simple method:

def sum(a, b) a + b end 

นี่คือ function ที่บวกสองตัวเลข ซึ่งง่ายมาก การ test function นี้จะ super easy แต่ถ้า function นี้มี dependency บน external service เมธอดนี้ต้อง write to database เมื่อ complete sum

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

ใน block นี้ values ถูกบวกและ save ไป database เพื่อ test block นี้ เราต้องมี database server running หากเรา test นี้กับ database server running มันไม่ใช่ unit test แล้ว นี่ต้องการ external dependency และเราก็จะ test database connection และว่า record saved ใน database ในกรณีนี้ test นี้คือ integration test

Unit tests อาจเป็น solitary unit tests (mock/stub all dependencies) หรือ sociable unit tests (allow talking to other dependencies) คนเสนอนิยาม unit tests ต่างกัน ในบริบทบล็อกนี้ unit test ที่เราพูดคือ solitary unit test

การเอา external dependencies ออกด้วย mocks ช่วยให้ tests รันเร็วขึ้น ขณะใช้ unit tests เราทิ้ง dependencies นี้แตเพื่อ ensure application works as expected การ test dependencies เท่ากันสำคัญ Tests ที่เราเขียน test external dependencies เช่น database, network calls และ files คือ integration tests

เหมือน unit tests คนเสนอนิยาม integration tests ต่างกัน แต basic concept เหมือนกัน ความต่างมีแค่ scope function เล็กๆ ที่ write to database เป็น integration test functionality กว้างกว่าที่ connect multiple parts of system ก็เป็น integration test Test ที่เราพูดถึงนี้ focus มากกว่าบน narrow part ยิ่ง test narrow ยิ่งต้องเขียน tests มาก กับ broader tests จำนวน tests ที่ต้องเขียนลดลง

ขณะรัน integration test เราต้องการ application และ dependencies เช่น database และ external services running การจัดการ dependencies เหล่านี้ challenging

Fundamentals of Docker (พื้นฐาน Docker)

Docker เป็น technology ช่วย abstract application จาก environment (operating system) และรันใน isolation กับ host คล้าย virtual machine แตเร็วกว่าและมีประสิทธิภาพมากกว่า Docker อนุญาตให้เรา package application code และ dependencies เข้า single container นี่ช่วยทำให้ code portable และหมายถึงเราสามารถมี Docker image เดียวกันรันระหว่าง development, testing และ production นี่จะ ensure consistency ของ environment ที่ application รัน เพราะไม่ dependent on host server มันทำให้ application behavior predictable ในทุก environments Docker ช่วย developers run และ manage application และ environment รวมถึง building, running, deploying และ updating ด้วย simple commands

มาเข้าใจ terminologies สำคัญ:

  • Dockerfile - Dockerfile คือไฟล์ที่เรา define dependencies ที่ application ต้องการ เราสามารถระบุ operating system ที่ต้องการ database client libraries หรือ packages ที่ application ต้องการ ที่นี่เรายัง define command ที่ application ต้องการรัน Dockerfile เริ่มจาก base image Base images เหล่านี้อาจเป็น operating system หรือ programming language

  • Images - Images คือ blueprint ระบุ steps ที่ container ต้องการรัน Images สร้างด้วย layers ต่างๆ ทุก step ที่ define ใน Dockerfile คือ layer ภายใน image นี้เพิ่ม reusability และช่วย caching intermediate layer เพื่อ build image เร็วขึ้น

  • Containers - Containers คือ actual images พวกมันอาจอยู่ใน stopped state Containers เริ่มจาก docker image Docker image เดียวสามารถเริ่ม multiple docker containers Containers เก็บ information ที่ระบุโดย image มี thin container layer ที่ changes ทั้งหมดที่ทำกับ image ขณะ application รัน จะถูกเก็บ

  • Docker Compose - Docker Compose เป็น tool ต่างที่ช่วย manage multiple containers เราสามารถมี multiple containers จาก docker image เดียวกัน เราอาจต้องการ multiple containers จาก docker images ต่างๆ และ containers เหล่านี้ต้อง interact กัน Docker Compose จัดการ containers มี tools อื่นๆ แต่ในบริบทนี้เราจะใช้ Docker Compose เพราะ simplicity

Virtual Machines อยู่บน host hypervisor และต้องติดตั้ง separate operating system ใช้ host resources มากกว่า แตกับ Docker เราต้องติดตั้ง Docker engine ใน host operating system เท่านั้น และ host resource management ทำโดย Docker Docker ช่วยทำให้ชีวิต developers และ sysops ง่ายขึ้น จึง popular ใน DevOps culture

ทำไมใช้ Docker สำหรับ Testing

Docker isolate running application หรือ test จาก host environment ด้วย minimal resource consumption นี่คือ advantages ของการใช้ docker สำหรับ testing:

  • Lightweight: Docker containers lightweight นี่ช่วยรัน multiple containers พร้อมกัน และโดยไม่มี one test process ก่อให้เกิด issue ใน another test process

  • Portable: Docker images portable และรันใน environment ใดๆ ได้ นี่ช่วยใน CI เพราะเราสามารถ reuse image เดียวกันรัน tests ใน local และ CI environments

  • Versioning: การใช้ multiple applications หรือ upgrade dependencies ต้องการ different versions ของ dependencies ใน local machine นี่ยากมากที่จะ manage โดยไม่มี Docker ด้วย Docker เราสามารถมี different containers รัน different versions เรายังสามารถรัน tests บน different versions และ verify things

  • Easy management of microservices: กับ microservices testing ก็ distributed และ complicated นี้หมายถึงเราต้อง manage dependent microservice Docker และ Docker Compose ช่วยจัดการ service dependencies

Pre-requisites (ข้อกำหนดเบื้องต้น)

ลองทำดู ต้องแน่ใจว่าต่อไปนี้ setup แล้ว:

  • Docker
  • Docker-compose
  • Ruby 2.7 (Optional เนื่องจากเราจะเพิ่ม Ruby ใน Docker container แตจะช่วยทดสอบ)
  • Rails (5.1+ recommended)

Dockerize the App

เริ่มด้วยการสร้าง simple Rails app และ containerize it ผมเริ่มกับ fresh Rails app คุณก็ containerize existing Rails app ได้

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 ที่เรา define มี Ruby 2.7 base image เราต้องการ NodeJS และ Yarn ดังนั้นขั้นตอนต่อไปคือติดตั้งพวกมัน เมื่อติดตั้งเสร็จ เรารัน bundle install และ yarn install สุดท้าย copy code ทั้งหมดและรัน Rails server พร้อม port 3000 exported นี่คือ Dockerfile เรียบง่าย ด้วยนี้ Rails app ของเรา dockerized แล้ว

ตอนนี้เราสามารถสร้างและรัน docker image เพื่อให้แน่ใจว่ามันรันได้

Build docker image:

docker build . -t calculator 

Run container:

docker run -p 3000:3000 calculator 

สร้าง Model พร้อม Calculation Logic

มาสร้าง model ชื่อ calculation ที่เราจะเพิ่ม calculation logic เราจะใช้ model นี้เขียน logic และ tests สำหรับพวกมัน เราจะดูว่าจะ manage dependencies ของ tests เหล่านี้ด้วย Docker Compose อย่างไร

เรารัน Rails กับ SQLite อยู่ ให้เปลี่ยนเป็น Postgres แทน SQLite ทำได้ง่ายด้วยคำสั่ง:

rails db:system:change --to=postgresql 

Generate calculation model:

bundle exec rails generate model calculation 

เพิ่ม fields ใน calculation schema:

# 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 

ต่อมา ลองรัน database migration ภายใน container:

docker-compose exec web rails db:migrate 

เนื่องจาก database ไม่ได้รันภายใน container การรันคำสั่งนี้จะ throw error

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 image เป็นอีก image และเพิ่ม network ระหว่างพวกมัน เพื่อจัดการ container communication นี้ เราสามารถใช้ Docker Compose

การใช้ Docker Compose จัดการ Multiple Containers

เมื่อ Rails app containerized แล้ว เราสามารถเพิ่ม dependencies ให้ service ด้วย Docker Compose Dependency บน application คือ Postgres

Postgres Docker image available publicly ดังนั้นเราไม่ต้องสร้างเอง อย่างไรก็ตาม เราต้องจัดการ database container และ Rails app container ของเรา

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 และเปลี่ยน database ไป host อื่น host จะเป็นชื่อที่ระบุใน service ใน Docker Compose file ในกรณีเรา host คือ db ตรวจสอบว่า DB password เหมือนใน postgres service และ web service เปลี่ยน username, password และ database name ตามที่ระบุใน Docker Compose file

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

ตอนนี้เราสามารถเริ่ม containers ด้วยคำสั่งเดียว:

docker-compose up 

นี่จะเริ่ม database และ Rails server ทั้งคู่ เราสามารถรัน migration command ตอนนี้ และมันควร connect ไป Postgres และรัน migration

การเพิ่ม Tests

ตอนนี้ setup พร้อมแล้ว มาเขียน simple method ภายใน model และ test method:

# calculation.rb class Calculation < ApplicationRecord def self.sum(x, y) result = x + y Calculation.create(x: x, y: y, result: result) result end end 

เมธอด sum นี้ไม่ได้แค่บวกตัวเลข แต่ยัง save ตัวเลขไป database ดังนั้นการ test เมธอดนี้ต้องมี database instance running

Test นี้จะเป็น integration test เนื่องจากเราต้อง connect ไป database

เราจะใช้ Mini-test เขียน test ซึ่งเป็น Rails default

# 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 

Run test:

docker-compose exec web rails test 

ใน test ด้านบน เรากำลัง test ว่า sum method บวก values และ save values ใน database ด้วย Docker Compose เรามีวิธีง่ายมาก connect ไป database

ที่นี่ method dependent on database Dependency อาจไม่ใช่แค่ database แตเป็น third-party service ที่ให้ REST API ดังนั้นลองใช้ third-party service ที่ให้ sum method ซึ่งเราสามารถใช้แทนการเขียนเอง

# 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 ที่เราทำสำหรับ database as a dependency เราต้อง ensure ว่า endpoints เหล่านี้ valid แตเราไม่ต้องการ call actual service ระหว่าง test สำหรับกรณีนี้ เราสามารถสร้าง mock/stub tests แต tests นั้นจะไม่ใช่ integration test หากเราทำอย่างนั้น เราอยากให้ test 実用的 มากที่สุด สำหรับวัตถุประสงค์นี้ เราสามารถสร้าง mock API endpoint ซึ่งเราจะรันใน container และ call ไป mock container API service ซึ่งจะ respond กลับมาด้วย result

มาปรับ 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 # 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 

ที่นี่ เราแก้ test case ให้ test แค่ว่า result จาก sum API ถูก save ใน database อย่างถูกต้อง เราไม่ต้อง test ว่า actual value ของ sum ถูกต้อง เพราะ external service จัดการ และเรา trust พวกเขา

เพื่อ generate mock server เราจะใช้ openAPI มาสร้าง simple swagger definition:

สร้างโฟลเดอร์ใหม่ใน root directory ชื่อ 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 

เพื่อรัน server นี้จาก specification เราสามารถใช้ mock service provider ใดๆ ผมจะใช้ tool ชื่อ prism มี docker image พร้อม ซึ่งเราสามารถเพิ่มใน docker-compose file:

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 

ตอนนี้ รัน test และดูว่าทำงานเป็นไปตามคาดหรือไม่:

> 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 

Yeah! ตอนนี้เรามี test running เมธอด connect ไป sum service Docker image หาผลรวม และ connect ไป Postgres save data Dependencies ทั้งหมดจัดการโดย Docker Compose ดังนั้นเราไม่ต้องกังวล dependencies ที่ติดตั้งก่อนหน้า การย้าย test ไป machine ใดๆ จะทำงานโดยไม่ต้อง install dependencies เครื่องจักรต้องการแค่ docker

หาก application ของคุณ depend บน dependencies อื่นๆ เช่น Redis หรือ Memcached พวกมันหาได้ใน dockerhub เราสามารถเพิ่ม images เหล่านี้ใน Docker Compose file ตามต้องการ

Parallel Tests

Rails 5.1.5+ รองรับ running tests in parallel โดย default tests รัน parallel จาก Rails 6 ตามจำนวน processors ขณะรัน test มันสร้าง database instances ตามจำนวน parallel tests หากเรามี four processors มันสร้าง databases "calculator_test-0", calculator_test-1, calculator_test-2, และ calculator_test-3 หากไป postgres cli และ check databases จะเห็น:

> \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 หรือ mini-tests หรือมี older Rails version คุณยัง run tests in parallel ได้หากเขียนด้วย Docker Rails auto create databases สำหรับ parallel tests แตถ้ามี dependencies อื่นๆ เช่น Redis หรือ memcached อาจต้อง manage manually

เนื่องจากเราจัดการ dependencies ทั้งหมดแล้ว เราสามารถรัน Docker Compose ด้วย arguments ต่างๆ เพื่อรัน tests in parallel สำหรับวัตถุประสงค์นี้ เราสามารถระบุว่าเราอยากรัน tests บน folders ไหนใน parallel สร้าง multiple Docker Compose files และรันพวกมัน parallel

การเพิ่ม Makefile เพื่อลดความซับซ้อนของคำสั่ง

เนื่องจากเราใช้ Docker และ Docker Compose commands รัน tests คำสั่งยาว ยากจดจำและรันขณะ development ต่อวัน เพื่อลดให้เป็น simple command ให้เราใช้ Makefile Makefile คือ simple text file ใช้ reference target command execution

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

เราเพิ่ม commands บางอย่างใน makefile สามารถ extend ตาม application ต้องการ เพิ่ม makefile ใน root directory ของ Rails application เมื่อมี makefile นี้ เราสามารถรัน test ด้วยคำสั่ง:

Boot containers:

> make up 

Run test:

> make test 

การใช้ Docker สำหรับ Local Development

เรายังสามารถใช้ Docker ขณะ develop application นี่ช่วย ensure application behave consistently across testing, development และ production มาทบทวนสิ่งที่ต้องเปลี่ยนเพื่อใช้ container ด้านบนสำหรับ local development

Volume Mount

ขณะรัน application locally เราอยากให้ application reflect changes ใน local server เมื่อเราทำ changes ใน code ในสถานการณ์ปัจจุบัน code ถูก copy จาก machine ไป Docker และ server เริ่ม ดังนั้นหากเราทำ changes ไฟล์ใน local machine พวกมันไม่ reflect ใน Docker เพื่อ ensure code always in sync เราสามารถใช้ volume mount

ใน Docker Compose file ให้เพิ่ม volumes:

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 

ตอนนี้ หากเราทำ changes อะไรก็ตามไปที่ server changes จะ reflect ลองดูโดยสร้าง controller และเรียก sum method:

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

เพิ่ม root route:

# 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 

ตอนนี้ หากเรากลับไป check app ใน browser เราได้ expected response:

ทดสอบ Rails App ใน Docker อย่างง่ายดาย: คู่มือทีละขั้นตอน

สังเกตว่าเราเริ่ม server ด้วย mock sumservice ดังนั้นไม่ว่าเราจะใส่ query parameter อะไรใน URL มันจะ return 2 เสมอ นี่ไม่ดูเป็น good way สำหรับ development แต่การใช้ mock service provider มี advantages ตอนพัฒนา microservices อาจมี dependent services มากมาย ซึ่งเราต้อง boot up ก่อนเริ่ม service นี่ช่วยเพิ่ม productivity ระหว่าง development เราไม่ concerned กับ other service แตแค่ service ที่เรากำลังพัฒนา

หากเราอยาก final verification ว่าทำงานกับ actual service อย่างไร เราสามารถทำได้โดยสร้าง Docker Compose file ใหม่และแทนที่ด้วย actual image ของ service หากเป็น internal service เราสามารถแทนที่ด้วย latest stable Docker image ผมแนะนำให้มี mock service แม้ใน development environment

.dockerignore

เมื่อ application โต dependencies จะทำให้ Docker build context ใหญ่ขึ้น ด้วย larger build context ใช้เวลา build docker image มากขึ้น แม้ volume mount ก็อาจ delay ด้วย increased size ของ application ในกรณีนี้ เราสามารถเพิ่ม unwanted files ไป .dockerignore file เพื่อลด build context

.git* log/* README.md node_modules 

Entrypoint

ขณะ Rails server รันใน container เราบางครั้งได้ error message ว่า server running แล้ว เพราะ PID file ไม่ถูกลบเมื่อ container exited เพื่อ remove error นี้ เราสามารถเพิ่ม ENTRYPOINT ซึ่งจะ remove server.pid file

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"] 

สร้าง file 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 "$@" 

Make it executable

chmod +x entrypoint.sh 

ตอนนี้ เมื่อเรารัน Docker image เราจะไม่เจอ issue นี้

สรุป

แยก integration tests และ unit tests สำคัญมาก ขณะเขียน unit tests เราสามารถ mock external dependencies เช่น databases นี่ช่วย test code ใน isolation ส่วนเท่ากันสำคัญคือรัน integration tests ระหว่าง core business logic และ dependencies Dependencies เช่น databases และ external services สามารถ test ใน integration ด้วย Docker และ Docker Compose การแยกสองอย่างนี้เป็น good practice เราควรสามารถรันแยกกันได้ การมี unit tests มากและ integration tests น้อยทำให้ tests รันเร็วและ reliable มากขึ้น

บาง advantages ของ workflow นี้:

  • Segregation ระหว่าง unit และ integration tests
  • เนื่องจาก CI services ทั้งหมดรันบน containers tests รัน locally และใน CI จะมี behavior เดียวกัน นี่ช่วย ensure consistency ของ test behavior ใน local machine และ CI server
  • ใช้ containers deploy application ช่วย ensure consistency ใน production server
  • Reliable tests เนื่องจาก dependencies managed ดี
  • Portable tests ต้องการ effort น้อยใน setup เมื่อใช้หลาย developers