nginxモジュールのテストを書く
はじめに
唐突ですが、仕事でシステムの構成を考えていると、nginxを拡張したいなーとか思うことってあると思います。nginxはC言語で割と簡単に拡張モジュールを書くことができます。(今回は拡張モジュールの書き方については触れませんが・・・)
だがしかし、仕事なんだからテストコードは必須だよね(迫真)。既存のnginx用のモジュールのコードを眺めてみると、謎の`t`フォルダにテストコードが入っています。
`t`ってなんだよ`t`って!中身もhogehoge.tとかなってるし、t言語なんかあるの? というところから始まり、なんとかテストを書いて実行できるようになったので方法をまとめておきます。
具体的にはperlのテストフレームワークと agentzh/test-nginx · GitHub を利用してテストを書いていきます。
テストの準備
必要なもの
nginxのテストをするために必要なソフトウェアやライブラリです。URLを掲載していないものはUbuntu13.10の公式リポジトリからSynapticを使ってインストールしました。
nginxのコンパイルに必要なもの
- nginx (http://nginx.org/download/)
- echo-nginx-module (https://github.com/agentzh/echo-nginx-module)
- memc-nginx-module (https://github.com/agentzh/memc-nginx-module)
テストを実行する上でecho-nginx-moduleとmemc-nginx-moduleは不可欠でした。
※`/home/develop` 下にecho-nginx-moduleとmemc-nginx-moduleをcloneしていると想定して記事を書いています。
perlでテストを実行するために必要なもの
- perl
- prove
- libtest-base-perl
- libtest-longstring-perl
- test-nginx (https://github.com/agentzh/test-nginx)
test-nginxは適当なディレクトリにcloneしておき、テスト実行時にディレクトリを指定します。
※`/home/develop' 下にtest-nginxをcloneしていると想定して記事を書いています。
テストコードの書き方
nginxモジュールのプロジェクトディレクトリに`t/`というディレクトリを作り、その中に`{任意の名前}.t`という形でテストコードを書いていきます。
use Test::Nginx::Socket; # テストの実行回数の設定。 repeat_each(3); plan tests => repeat_each() * 2 * blocks(); # 文字の表示をわかりやすくする。 no_long_string(); # テストの実行 run_tests(); __DATA__ === TEST 1: ハローワールドのテスト --- config location /hello { echo hello_world; } --- request GET /hello HTTP/1.0 --- response_body hello_world --- error_code: 200
`--- config` にnginxの設定を記述し、`---request` でテストとして実行するリクエストを記述します。
次に、リクエストに対して`--- response_body` で期待するレスポンスを記述し、 `--- error_code` に期待するレスポンスコードを記述します。
こんなに簡単にかけるテストは見たことはありません!幸せ。
テストの実行
大まかな流れ
nginxのテストの大まかな流れは次のとおりです。
nginxのコンパイル
テストを実行するために、自分のモジュールを組み込んだnginxをコンパイルします。私の場合は次のようなオプションでコンパイルしました。
CFLAGS="-O1 -Wall -g" ./configure --add-module=[自分のモジュール] --add-module=/home/develop/echo-nginx-module --add-module=/home/develop/memc-nginx-module --prefix=/home/develop/nginx --with-debug
特筆すべき点は下記2点です。
- CFLAGSはvalgrindを利用してプロファイリングを行うことを想定しています。
- プレフィックスをつけて通常使用するnginxとは分けました。(当然といえば当然ですね。)
proveでテストの実行
まず、先ほどコンパイルしたnginxにパスを通します。
export PATH=/home/develop/nginx/sbin:$PATH
そしてテストを実行します。
prove -I/home/develop/test-nginx/lib -r t
proveを実行する際にtest-nginxをincludeのがポイントです。
valgrindでプロファイリングする場合
メモリリークや実行速度についての解析をvalgrindを用いて行う場合にはTEST_NGINX_USE_VALGRINDという環境変数にオプションを記述します。
TEST_NGINX_USE_VALGRIND="{オプション}" prove -I/home/develop/test-nginx/lib -r t
メモリリークのテストをする場合にはこんなかんじでしょうか。
TEST_NGINX_USE_VALGRIND="-v --tool=memcheck --leak-check=full" prove -I/home/develop/test-nginx/lib -r t