Hatak::Techlog

Verba volant, scripta manent.

テストのために Redis を立ち上げたかった

ミドルウェアを使った処理のテストでは、テストのための設定でその時限りのデーモンを立ち上げて使いたいものです。 例えば MySQL であれば Test::mysqld 、memcached であれば Test::TCP などを使うことで手軽にデーモンを立ち上げる仕掛けを作ることができます。これを prove にフックさせたりすると、マニュアルでテスト用のデーモンを立ち上げる必要がなくなるという方法がとれます。

Redis を使った処理のテストを書く必要があり、これと同じような方法で立ち上げる設定を作ろうとしました。 デフォルトとは異なるポートで Redis のサーバを立ち上げてあげればいいのですが、redis-server コマンドは起動時の引数で直接ポート指定ができず設定ファイルとして渡す必要があります。ちょっと面倒だな、と思って手抜きをしようと探したところ、p5-Redis のテストコードの中に目的のものを見つけました。

このモジュールを use して、テスト開始時に呼び出して Redis のデーモンを起動、テスト終了後にデーモンを終了してあげればよさそうです。 フレームワークとして Amon2 を使っていたので、t::Util のようなモジュールを作って必要なテストで use してあげるような仕組みでやってみました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package t::Util;

use Test::SpawnRedisServer;

my $REDIS;
use MyApp;

{
    # start redis-server with Test::SpawnRedisServer (via p5-Redis)
    $ENV{REDIS_DEBUG} = 1;

    ($REDIS, $ENV{TEST_REDIS}) = redis();
    my $c = MyApp->new();
    $c->setup_schema();
}

END {
    # stop redis-server
    $REDIS->() if $REDIS;
}

1;

$ENV{TEST_REDIS} に格納されるのは “127.0.0.1:11121″ のような接続先アドレスなので、Redis への接続時に使われるように設定しました。

config はこんな感じ。

1
2
3
4
5
6
die unless (defined $ENV{TEST_REDIS});
+{
    "Redis" => {
        server => $ENV{TEST_REDIS},
    },
}

コンストラクタはこんな感じ。(Teng とかとほぼ同じですが。。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package MyApp 0.01;

use v5.14;
use parent qw/Amon2/;

use Redis;

sub redis {
    my $self = shift;
    if ( !defined $self->{redis} ) {
        my $conf = $self->config->{Redis} or die 'missing configuration for "Redis"';
        $self->{redis} = Redis->new(%{$conf});
    }
    return $self->{redis};
}

1;

これで無事、テストを走らせるときに一緒に Redis が立ち上がるようになりました。

1
2
3
4
5
6
7
8
9
10
11
12
use strict;
use warnings;

use t::Util;
use Test::More;
use MyApp;

my $c = MyApp->bootstrap;

is($c->redis->ping, "PONG");

done_testing;

めでたしめでたし。

と思ったら、ちゃんと Test::RedisServer というモジュールがつくられていました。

こちらだと Test::mysqld と同じように書けるのですっきりして見やすそうです。typester++