Catalystでテストする testデビュー

Testなんて今までろくに使ったことがなかったのですが、YAPCの牧さんのみて、これはやらんといかんよねー。 手間排除できそうだし、ミスも減りそうだしーいいことずくめっぽいZO!って事でCatalystでテストデビュー

いきなりエラーの巻

巻さんお資料の通りとりあえず既存のCatalystアプリでテストしてみた

Perl Makefile.PL
make
make test

が、いきなりエラー

[info] myapp powered by Catalyst 5.7012
t/controller_logic.......ok 1/3[info] *** Request 1 (1.000/s) [22955] [Fri May 23 21:21:39 2008] ***
[debug] "GET" request for "logic" from "127.0.0.1"
[debug] Arguments are "/logic"
[error] Unknown resource "logic"
[error] Unknown resource "logic"

コントローラーlogicにlogicでアクセスできんよって事で、そうですそれが何か?って事だけど、これはテストを修正すべきなのか、Catalystを修正すべきか?

そのほかにもsettingコントローラにsettingリソースが見つからないよと怒られた。


[debug] Arguments are "/setting"
[error] Unknown resource "setting"
[error] Unknown resource "setting"

sub index: Private {}をおいた。 indexなくてもいいじゃない!人間だもの

ようやくまっさらな状態でテストが通る。

t/02pod..................skipped
        all skipped: set TEST_POD to enable this test
t/03podcoverage..........skipped
        all skipped: set TEST_POD to enable this test

PODはskipでおっけー

ではテストファイルをみてみる
MyApp/t/controller_setting.tファイルをみてみた。

ok( request('/setting')->is_success, 'Request should succeed' );

!! /settingにアクセスしようとしていたのはこいつだった!というか俺あほすぎ
でもようやくわかってきた 
ok( request('パス')->is_success, 'Request should succeed' );
ってやってちゃんとレスポンスが返ってくれば正しく動作するかどうかをテストできることがわかった。

ここまできてようやくCatalyst::Manual::Tutorial::Testingを読んだ
http://search.cpan.org/~zarquon/Catalyst-Manual-5.7011/lib/Catalyst/Manual/Tutorial/Testing.pod

There are a variety of ways to run Catalyst and Perl tests (for example, perl Makefile.PL and make test), but one of the easiest is with the prove command. For example, to run all of the tests in the t directory, enter:

    $ prove --lib lib t

perl Makefile.PL; make; make testはやる必要なくて
prove --lib lib t で ./t/ディレクトリの中のテストファイルをすべて実行してくれるようだ。

CATALYST_DEBUG=0 prove --lib lib t

これでテストサーバのデバッグ機能をOFFにして余計なメッセージを表示させないようにできる

CATALYST_DEBUG=0 TEST_POD=1 prove --lib lib -v t

さらに-vをつけることでテストケース毎に表示するようになった。

おれおれテストを書く

CatalystHelperが書き出してくれるデフォルトテストの中はこの通り

use strict;
use warnings;
use Test::More tests => 3;

BEGIN { use_ok 'Catalyst::Test', 'myapp' }
BEGIN { use_ok 'myapp::Controller::setting' }

ok( request('/setting')->is_success, 'Request should succeed' );

Catalyst::Test

  • get

ok( gett('/setting')->is_success, 'Request GET should succeed' );

GETでテスト ゲッツ!

  • request

ok( request('/setting')->is_success, 'Request should succeed' );

テストに書いてあったまんま、パスにリクエストする

  • local_request

不明?

  • remote_request

リモートからのリクエスト? LWP使用

結局Catalyst::Testはウェブレイヤーのテスト(コントローラのテスト)が目的なので、ロジックのテストは無理。

Catalyst::Manual::Tutorial::Testing これをみるとTest::WWW::Mechanize::Catalystでいろいろできるようだけど、結局これもウェブレイヤーでのテストという事で、実際の環境に近いところでのテスト用だと考えればいいいっぽい。

純粋なロジック部分をテストするにはどうするんだ?って事で、牧さんのスライド、ぐぐって調べてみる限り、Catalystとは分離して書くのが良さそうだ。Catalyst::Model::Adaptorつかえって事のようで。

それとついつい$c->stashをグローバル変数のように使ってしまう。 こうなるとものすごくテスト、デバッグがしにくい。 これは駄目。

http://blog.hide-k.net/archives/2007/10/catalystmodelad.php

MyApp/HogeMoge.pm .... ロジック
MyApp/Model/HogeMoge.pm .... HogeMogeクラス Model Adapterのヘルパーが作ってくれる

などとするとすっきりしそうです。

とここまできて思ったことは、Catalystでテストを行おうとすると、ロジック部分がCatalystに依存していると、テストしにくい。 Model::Adaptor使えばいいんだろうが、弊害もありそうな気がする。 一番いいのはテストサーバ経由(ウェブ経由)しないテストがかければいいんじゃね?って事で、次はそれに挑戦してみようと思う。

思ったこと。
アプリよりテストを先に書くといいのかもしれない。
いまさらだけど、テストは書くべし。
テストを軽くやろうと思ったら、設計やらなにやらいろいろと勉強になりました。
今までのやり方ではあかんなと思いました。是非テスト書いた方がいいよと書いてみるテスト