読者です 読者をやめる 読者になる 読者になる

inifileを使ってServerspecのテストを書いてみる part3

気づいたらしばらくぶりの更新になってしまいました。。。


今日は、inifileを使ってテストを記述した場合と、should matchを使ってテストを記載した場合を比較していみたいと思います。

個人的にinifileの方が優れていると思う点は、以下の通りです。

  1. 正規表現の考慮が減るのでテストを記述しやすい
  2. 揺らぎやすい表記を無視してテストできる(=前後の空白など)
  3. どこがNGなのかわかりやすい

正規表現の考慮が減るのでテストを記述しやすい

php.iniのパラメータの一つである、session.save_pathを例にとります。
テストコードで比較するとこんな感じです。

should matchの場合

    its(:content) { should match %r{^session.save_path = "\/var\/lib\/php\/session"$} }

inifileの場合

      expect(conf['Session']['session.save_path']).to eq "/var/lib/php/session"

正規表現を使って記述する必要があるので、パスを表す/をエスケープしたり、テストしたい記述の先頭に^末尾に$をつけて、記述の前後に余計な文字が含まれている場合に誤検知しないようにするなど、考慮するポイントが様々あります。
正規表現の方がいい場面もあるかもしれませんが、inifileの場合は正規表現で表す必要は無くなります。
直感的にあるべき姿をイメージしやすいのはinifileを使った書き方ではないかと思います。

揺らぎやすい表記を無視してテストできる

例えばphp.iniの設定がこのようになっていたとします。

short_open_tag=Off

should matchだと=の前後の空白も考慮して描かないとNGになってしまいますが(本来はOKであってほしい)、inifileならOKで検出してくれます。

Package "php"
  should be installed

php.ini
  File "/etc/php.ini"
    should be file
    configures check php.ini

Finished in 1.84 seconds (files took 3.82 seconds to load)
3 examples, 0 failures

こういったケースもあるので、inifileをテストに活用するのはアリだと思っています。
(コーディング規約の統一という意味では、NGで拾いたいという考え方もあるかもしれません。)

どこがNGなのかわかりやすい

例えば、php.iniの設定で行末に余計な文字を入れてしまったとしましょう。

short_open_tag = Offf

should matchを使った場合

  1) php.ini File "/etc/php.ini" content should match /^short_open_tag = Off$/
     On host `WEB01'
     Failure/Error: its(:content) { should match %r{^short_open_tag = Off$} }
       expected "[PHP]\n\n;;;;;;;;;;;;;;;;;;;\n; About php.ini   ;\n;;;;;;;;;;;;;;;;;;;\n; PHP's initialization file,... shared memory segment\n;sysvshm.init_mem = 10000\n\n\n; Local Variables:\n; tab-width: 4\n; End:\n" to match /^short_open_tag = Off$/
       Diff:
       @@ -1,2 +1,1660 @@
       -/^short_open_tag = Off$/
...
php.iniのファイルの内容がずらっと出る
...

間違っているテストケースはわかりますが、どこがどう間違っているのか一見わかりません。

inifileの場合

  1) files File "/etc/php.ini" configures check
     On host `WEB01'
     Failure/Error: expect(conf['PHP']['short_open_tag']).to eq 'Offf'

       expected: "Off"
            got: "Offf"

       (compared using ==)
       sudo -p 'Password: ' env PATH="/sbin:/usr/sbin:$PATH" /bin/sh -c cat\ /etc/php.ini\ 2\>\ /dev/null\ \|\|\ echo\ -n
       [PHP]

expectedgotの部分を見れば、期待される値(Off)に対してどんな値が得られたか(Offf)がすぐわかるので、NGの原因を掴みやすいと思います。

逆にinifileを使わないほうが良い場面

inifileは、セクションとキーで構成されるファイルを扱うものなので、そうでない設定ファイルには適用できないと思います。
例えばhttpd.confなどが挙げられます。
この辺は未検証なので断言できませんが、多分できないでしょう。

テスト対象の設定ファイルに応じて、inifileshould matchを使い分けたいところです。