波打際のブログさん

主に、プログラミング備忘録など。

nginxモジュールのテストを書く

はじめに

 唐突ですが、仕事でシステムの構成を考えていると、nginxを拡張したいなーとか思うことってあると思います。nginxはC言語で割と簡単に拡張モジュールを書くことができます。(今回は拡張モジュールの書き方については触れませんが・・・)

 だがしかし、仕事なんだからテストコードは必須だよね(迫真)。既存のnginx用のモジュールのコードを眺めてみると、謎の`t`フォルダにテストコードが入っています。
`t`ってなんだよ`t`って!中身もhogehoge.tとかなってるし、t言語なんかあるの? というところから始まり、なんとかテストを書いて実行できるようになったので方法をまとめておきます。

 具体的にはperlのテストフレームワークagentzh/test-nginx · GitHub を利用してテストを書いていきます。

さっきからPerlっていう単語が・・・

 あれって2000年前半にオワコンの技術じゃ・・・と思う人も思いますが、割と進化を続けているようです。(Perlのエロ人、こんな説明ですみません、CGI時代にPerlをちょっと触ったにわかです許して下しあ><)

Perl使ったことないんだけど

 今回紹介するテスト方法はPerlのコードをガリガリ書く必要はないので安心してください。(ここまで簡単にかけるテストフレームワークはむしろ初めてでした。)

テストの準備

必要なもの

 nginxのテストをするために必要なソフトウェアやライブラリです。URLを掲載していないものはUbuntu13.10の公式リポジトリからSynapticを使ってインストールしました。

nginxのコンパイルに必要なもの

 テストを実行する上でecho-nginx-moduleとmemc-nginx-moduleは不可欠でした。
※`/home/develop` 下にecho-nginx-moduleとmemc-nginx-moduleをcloneしていると想定して記事を書いています。

perlでテストを実行するために必要なもの

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のテストの大まかな流れは次のとおりです。

  1. 自分のモジュールを組み込んだnginxをコンパイル&インストールする。
  2. コンパイルしたnginxのパスを通す。
  3. プロジェクトのディレクトリでproveを実行する。

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