Help us understand the problem. What is going on with this article?

Dockerをテスト駆動開発していくための最小限のTips

More than 1 year has passed since last update.

image.png

アプリケーション開発では テスト駆動開発(Test Driven Development: TDD) はもう一般的になってきましたね。テストコードがないと継続的に開発ができなくて怖いですよね・・・

TDDの基本的な考え方は以下のような流れです。

  1. アプリケーションがあるべき姿を満たすようにテストを書く
  2. テストを実行して 失敗(RED)になることを確認する
  3. アプリケーションを実装してテストを 成功(GREEN)にする
  4. リファクタリングを行う

つまり REDGREENリファクタリング のサイクルを繰り返すことがテスト駆動開発です。

テスト駆動開発を行う目的は多々あるかと思いますが、
「キレイな実装をし、メンテしやすいコードを維持しながら継続的に開発を行うため」
というのが主な目的かと私は考えています。

さて、今回話題にあげたいのがインフラをどのようにして、テスト駆動開発の流れに乗せて開発するかです。
インフラのテストというとまだまだ未開拓な領域も多く、手が出しづらいのが現状ではないでしょうか?
今回はDockerのテストに焦点を当てて、最小限これだけやればDockerのTDD開発ができるぞ!という方法を考えてみました。

Dockerfile

Dockerfileは純粋な centos イメージ からスタートしていきます。
今回は centosイメージ に git をインストールしていく開発フローをTDDで進めていきます。

はじめのDockerfile
FROM centos

使用するツール

  • serverspec
  • docker-api

serverspecを使用しますので ruby です。
まずはGemfileに必要なgemを列挙してbundle installしましょう。

Gemfile
source "https://rubygems.org"

gem 'serverspec'
gem 'docker-api'
bash
$ bundle install

ちなみにディレクトリ構成を先にご紹介しておくとこんな感じです。

bash
$ tree
.
├── Dockerfile
├── Gemfile
├── Gemfile.lock
├── README.md
└── spec
    ├── spec_helper.rb
    └── web
        └── git_spec.rb

spec_helper.rb

spec_helper.rb
require 'serverspec'
require 'docker'

set :backend, :docker
set :docker_image, 'web'

今回のミソはこの部分かもしれません。
spec_helper.rbにこのように書いておくと、 serverspec がテスト対象の docker image を特定してくれます。
今回は実行する対象の docker image の名前をwebとしておきました。
なので、まずは docker image を web という名前をつけて作っておきましょう。
まだこの状態では純粋な centos が入った docker image が web という名前でできているだけです。

bash
# docker imageをwebという名前をつけてビルドする
$ docker build -t web .
Sending build context to Docker daemon   59.9kB
Step 1/1 : FROM centos
 ---> 49f7960eb7e4
Successfully built 49f7960eb7e4
Successfully tagged web:latest

# docker imageの一覧を確認
$ docker images
REPOSITORY                                               TAG                 IMAGE ID            CREATED             SIZE
web                                                      latest              49f7960eb7e4        5 weeks ago         200MB

テストを失敗させる RED

さて、前置きは整いましたのでここからいよいよテストコードを書いていきましょう。
まずはテストを実行して RED にするところまでもっていきます。

git_spec.rb
require 'spec_helper'

describe package('git') do
  it { should be_installed }
end

単純に git がインストールされて入ればOKですのでこれで十分ですね。
テストを実行して RED になることを確認します。

bash
$ bundle exec rspec

Package "git"
  should be installed (FAILED - 1)

Failures:

  1) Package "git" should be installed
     Failure/Error: it { should be_installed }
       expected Package "git" to be installed

     # ./spec/web/git_spec.rb:4:in `block (2 levels) in <top (required)>'

Finished in 1.09 seconds (files took 0.42839 seconds to load)
1 example, 1 failure

Failed examples:

rspec ./spec/web/git_spec.rb:4 # Package "git" should be installed

Dockerfileを書いていく

テストが RED になっていることを確認しましたので、これを GREEN にしなければなりません。
ここからやっと、Dockerfileを書いていくフェーズになります。

bash
$ emacs Dockerfile
Dockerfile
  FROM centos
+ RUN yum install -y git

gitを入れるだけなのでとても簡単です。
yum installするだけです。

テストを成功させる GREEN

Dockerfileができあがりましたので、あとはテストを GREEN にしましょう。
まずは先程作ったDockerfileからdocker imageをビルドします。

bash
# docker imageをwebという名前をつけてビルドする
$ docker build -t web .
bash
$ rspec

Package "git"
  should be installed

Finished in 1.13 seconds (files took 0.89826 seconds to load)
1 example, 0 failures

テストがGREENになりました。完成です。
以上で、Dockerに対するTDDの流れが実現できました。
そこまで複雑なことはしなくてもよいので、とても簡単ですね。

Travis CI を使って自動テストできるようにする

実際にチームでプロダクトを開発する際にはCIツールに頼るのが一般的です。

今回はCIツールとして、Travice CIを使ってみます。
使用方法とかはググってもらえればたくさん出てくると思うので省略しますが
Settings → Integration & Service から Add Serviceのプルダウンを押すと
Travis CIが出てきますので、そこからポチポチ設定すればできるはずです。

image.png

.travis.yml

まずはビルドの設定をしましょう。
.travis.ymlというファイルを作ってGithubのリポジトリの直下に置いておけば自動的に読み込んでビルドを行ってくれます。

ローカルでTDDをやった時の流れに従って、rspecによるテストを実行する前にdocker imageをビルドしておきましょう。
before_installで指定すればscriptより先に実行してくれるので、ここにdocker buildと書いてしまえばいいです。

.travis.yml
sudo: required
language: ruby
cache: bundler
service: docker
before_install:
    - docker build -t web .
script:
    - bundle exec rspec

Githubで開発をしてみる

Githubで適当なプルリクエストを立ててみましょう。
TravisCIがコミットごとに自動でテストを実行し、その結果を返しているのがわかります。

スクリーンショット 2018-07-10 22.55.39.png

Travis CIの画面

ちなみにテストで失敗した or 成功したという結果はTravis CIではこのようなログで確認することができます。

errorの場合

travis_error.png

passの場合

travis_passed.png

まとめ

  1. テスト駆動開発(TDD)を行うことで、メンテしやすいコードを維持しながら継続的に開発を行える
  2. インフラ(Docker)でもTDDできるよ
  3. TravisCIとか使うとGithubでの開発が捗っていい感じ

今回はDockerを例にとりましたが
Vagrantとかを使えば仮想環境でももちろんこのテクニックは応用できそうです。

これからはインフラもあたりまえにテストを書いていく時代ですよ:smirk:

G-awa
物性物理学、分子動力学の研究をやってました。サイエンス出身、スパコンが好きです。 java, spring, ruby, rails, python, nodejs, react, react native, aws, devopsあたりが得意です。NoOpsを目指して葛藤している4年目エンジニアです。
intec
未来を「ひらく」、技術で「つなぐ」、世界を「変える」、豊かなデジタル社会の一翼を担う会社です。※各記事の内容は個人の見解であり、所属する会社の公式見解ではありません。
https://www.intec.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした