はじめに

手順書を書く時に「xxx の出力結果が xxx であることを目視で確認する.」と書いていて, 自分で自分に以下のようなツッコミを入れた.

俺の目は本当に正しいのか…このままだと, 出力結果が xxx であることを保証するのは, 俺の目だけなんだな…

そこで自分は手順書を書く手を止めた.

そこで, assert 文を利用することにした

このような場合, Servrespec を利用すべきなのかもしれないが… python の assert 文で確認するように手順書を書き換えることにした.

assert 文は unittest 内で利用するもんだと思っていたけど, 以下のように利用することで普通の Python スクリプトや Python のワンライナーからでも利用することが出来る.

# assert 条件, '条件が false だった時のメッセージ'
assert 'foo' == 'foo', 'Does not match!!'

利用例

利用例の環境

sh-4.1# cat /etc/system-release
CentOS release 6.9 (Final)
sh-4.1# python --version
Python 2.6.6

設定ファイル

ちょっと極端な例だけど, Apache の DocumentRoot をデフォルト /var/www/html から /tmp/var/www/html に変更する設定を /etc/httpd/conf.d/sample.conf に設定する.

.sh-4.1# cat << EOF > /etc/httpd/conf.d/sample.conf
> DocumentRoot "/tmp/var/www/html"
> EOF

今までの自分なら手順書には以下のように書くかもしれない.

以下のコマンドを実行して, 'DocumentRoot "/tmp/var/www/html"' と出力されることを目視で確認する.

~~~
cat /etc/httpd/conf.d/sample.conf
~~~

この手順を以下のように書き直したい.

以下のコマンドを実行して, 'AssertionError: Error' が出力されないことを確認する.

~~~
cat /etc/httpd/conf.d/sample.conf | python -c "import sys; assert sys.stdin.read().strip() == 'DocumentRoot \"/tmp/var/www/html\"', 'Error'"
~~~

実際に試すと以下のように…

sh-4.1# cat /etc/httpd/conf.d/sample.conf | python -c "import sys; assert sys.stdin.read().strip() == 'DocumentRoot \"/tmp/var/www/html\"', 'Error'"
sh-4.1#

条件が true となるので AssertionError は出力されない. これを意図的に, 以下のように弄って実行すると…

sh-4.1# cat /etc/httpd/conf.d/sample.conf | python -c "import sys; assert sys.stdin.read().strip() == 'DocumentRoot \"/var/www/html\"', 'Error'"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AssertionError: Error

設定ファイルの内容と一致していない時だけ警告しているので, 出力を目視で手順書と比較する作業が無くなる.

コマンドの出力結果

Apache に必要なモジュールが組み込まれているかを確認したい場合. 例えば, mod_ssl が組み込まれているかな…

sh-4.1# apachectl -M 2>/dev/null | grep ssl
 ssl_module (shared)

今までの自分なら手順書には以下のように書くかもしれない.

以下のコマンドを実行して, 'ssl_module (shared)' と出力されることを目視で確認する.

~~~
apachectl -M 2>/dev/null | grep ssl
~~~

この手順を以下のように書き直したい.

以下のコマンドを実行して, 'AssertionError: mod_ssl is not included' が出力されないことを確認する.

~~~
apachectl -M 2>dev/null | grep ssl_module | python -c "import sys; assert sys.stdin.read().strip() == 'ssl_module (shared)', 'mod_ssl is not included'"
~~~

実際に試すと以下のように…

sh-4.1# apachectl -M 2>/dev/null | grep ssl_module | python -c "import sys; assert sys.stdin.read().strip() == 'ssl_module (shared)', 'mod_ssl is not included'"
sh-4.1#

条件が true となるので AssertionError は出力されない. mod_ssl をアンインストールして実行すると…

sh-4.1# apachectl -M 2>/dev/null | grep ssl_module | python -c "import sys; assert sys.stdin.read().strip() == 'ssl_module (shared)', 'mod_ssl is not included'"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
AssertionError: mod_ssl is not included

イイ感じで AssertionError が出てくれる. あるべき状態を確認する意味で AssertionError をチェックした方が自然のような気がする.

ということで

設定ファイルやコマンドの出力結果を目視で確認するのは止めたいと思ったので Python の assert 文を使ってみた. このやり方だと, 複数行の結果をチェックしなきゃいけない時に, ワンライナーで済まない (辛い) ことがあるかもしれないので工夫は必要だと思うけど, 人間の目でチェックするよりもコードに任せてしまうことで, その手順書を用いた作業のクオリティを挙げらるんではないかなと思う…

とは言え, Serverspec を使うとより良いのかもしれない. (手順書の書き方も変わるのかもしれないと思ったり)

元記事はこちら

手順書に「xxxxx と出力されることを目視で確認する」と書くの止めたい