鈍足ランナーのIT日記

走るのが好きな5流のITエンジニアのブログ。

趣味の範囲は広いけど、どれも中途半端なクソブロガー楽しめるWebアプリを作ってあっと言わせたい。サーバーサイドPerl(Mojolicious)、クライアントサイドVue.js。Arduinoにも触手を伸ばす予定。

Websocketのテストするのに、Test::Mojoに挑戦してみた

テストコードがなかったので、テストの練習がてら書いてみた。

Mojoliciousのバージョンあげたら。json_message_likeというのが 生えていて滅茶苦茶便利っぽい。

後は、Redisデータベースを初期化したいんだけど。テスト機だから 初っ端で全部消しちゃえばいいかな。(なんか安直)

もう少し、テストを充実させていこうと思う。

use Mojo::Base -strict;

use Test::More;
use Test::Mojo;
use utf8;

# dokechinさん入室、お部屋のメンバも通知されること
my $td = Test::Mojo->new('Chat::Web');

$td->websocket_ok('/hoge/echo')
  ->send_ok('name  dokechin')
  ->message_ok()
  ->json_message_is( "/name" => "dokechin")
  ->json_message_like( "/hms" => qr/^\d\d:\d\d:\d\d$/)
  ->json_message_is( "/message" => '入室しました。')
  ->message_ok()
  ->json_message_is( "/names" => ["dokechin"]);

# ロビーにhogeルーム開設通知
my $tl = Test::Mojo->new('Chat::Web');

$tl->websocket_ok('/notify')
  ->send_ok('rooms')
  ->message_ok()
  ->json_message_is( "/rooms/0" => {name => "hoge"});

# papixさん入室、、お部屋のメンバも通知されること
my $tp = Test::Mojo->new('Chat::Web');

$tp->websocket_ok('/hoge/echo')
  ->send_ok('name  papix')
  ->message_ok()
  ->json_message_is( "/name" => "papix")
  ->json_message_like( "/hms" => qr/^\d\d:\d\d:\d\d$/)
  ->json_message_is( "/message" => '入室しました。')
  ->message_ok()
  ->json_message_is( "/names" => ["dokechin","papix"]);

# papixさん入室がdokechinさんに伝わる
$td->message_ok()
  ->json_message_is( "/name" => "papix")
  ->json_message_like( "/hms" => qr/^\d\d:\d\d:\d\d$/)
  ->json_message_is( "/message" => '入室しました。');

done_testing();

しかし、大きな問題が・・・

1つのsendで、2つのメッセージを受けるんですが、 メッセージを受信する順番が一意に決まらない。どちらが 先にくるかは運次第。Test::Mojoを使ってうまいとこ これを解決しなくてはいけない。さぁ。どうするか・・・ 考えて、考えた末に出した方法は・・・

メッセージを長さでソートしてから、詰めなおして テストするという技を開発しました。

my $messages = sub {
    my ($t) = @_;
    my $m1 = $t->message_ok()->message;
    my $m2 = $t->message_ok()->message;

    my @sorted = sort { length($a) <=> length($b)} ($m1->[1],$m2->[1]);

    $t->message([text => $sorted[0]]);

    $t->json_message_is( "/names" => ["dokechin"]);

    $t->message([text => $sorted[1]]);
    
    $t->json_message_is( "/name" => "dokechin")
      ->json_message_like( "/hms" => qr/^\d\d:\d\d:\d\d$/)
      ->json_message_is( "/message" => '入室しました。');
};

$td->websocket_ok('/hoge/echo')
  ->send_ok('name  dokechin')
  ->$messages();