11

以下の単純なMojoliciousコントローラーを作成しました。

package SampleApp::Pages;

# $Id$

use strict;
use warnings;

our $VERSION = '0.01';

use Mojo::Base 'Mojolicious::Controller';

sub home {
    my $self = shift;

    $self->render( 'title' => 'Home' );

    return;
}

sub contact {
    my $self = shift;

    $self->render( 'title' => 'Contact' );

    return;
}

sub about {
    my $self = shift;

    $self->render( 'title' => 'About' );

    return;
}

1;

対応する単体テストは次のようになります。

package Test::SampleApp::Pages;

# $Id$

use strict;
use warnings;

our $VERSION = '0.01';

use Carp;
use English '-no_match_vars';
use Readonly;
use Test::Mojo;
use Test::Most;

use base 'Test::Class';

Readonly my $SERVER_OK => 200;

sub startup : Tests(startup) {
    eval {
        require SampleApp;

        SampleApp->import;

        1;
    } or Carp::croak($EVAL_ERROR);

    return;
}

sub get_home : Tests(4) {
    my $test = shift;
    my $mojo = $test->mojo;

    $mojo->get_ok('/pages/home')->status_is($SERVER_OK);

    $mojo->text_is(
        'title',
        $test->base_title . ' | Home',
        '... and should have the right title'
    );

    $mojo->content_like(
        qr/<body>(?:\s*\S+\s*)+<\/body>/msx,
        '... and should have a non-blank body'
    );

    return;
}

sub get_contact : Tests(3) {
    my $test = shift;
    my $mojo = $test->mojo;

    $mojo->get_ok('/pages/contact')->status_is($SERVER_OK);

    $mojo->text_is(
        'title',
        $test->base_title . ' | Contact',
        '... and should have the right title'
    );

    return;
}

sub get_about : Tests(3) {
    my $test = shift;
    my $mojo = $test->mojo;

    $mojo->get_ok('/pages/about')->status_is($SERVER_OK);

    $mojo->text_is(
        'title',
        $test->base_title . ' | About',
        '... and should have the right title'
    );

    return;
}

sub base_title {
    my ( $self, $base_title ) = @_;

    if ( defined $base_title ) {
        $self->{base_title} = $base_title;
    }

    return $self->{base_title};
}

sub mojo {
    my ( $self, $mojo ) = @_;

    if ( defined $mojo ) {
        $self->{mojo} = $mojo;
    }

    return $self->{mojo};
}

sub setup : Tests(setup) {
    my $test = shift;

    $test->base_title('Mojolicious Sample App');

    $test->mojo( Test::Mojo->new( app => 'SampleApp', max_redirects => 1 ) );

    return;
}

1;

私たちにとって、これは単体テストではなく機能テストに似ています

コントローラーのメソッドを呼び出してhome、サーバー インスタンスの起動を必要としない出力をテストする方法はありますTest::Mojoか?

4

1 に答える 1

21

コントローラーの配線をテストするには、次のようなコードを使用します。

t/pages.tおなじみのフロントマターから始めます。

use Mojolicious;
use Test::More;

SampleApp::Pagesへの呼び出しを記録するテスト サブクラスを作成しますrender

package TestingPages;
use Mojo::Base 'SampleApp::Pages';

has 'render_called';
has 'render_arg';

sub render {
  my($self,%arg) = @_;
  $self->render_called(1);
  $self->render_arg({ %arg });
}

あなたの質問は を使用Test::Classしたので、そのテーマを続けてください。

package Test::SampleApp::Pages;

use base 'Test::Class';
use Test::More;

引数なしでは最新の例外が伝播されるため、明示的dieに記述する必要がないことに注意してください。$@

sub startup : Test(startup) {
  eval { require SampleApp::Pages; SampleApp::Pages->import; 1 } or die;
}

setup、テスト サブクラスをインスタンス化し、それを Mojolicious インスタンスに接続して、ロギングをオフにします。

sub setup : Test(setup) {
  my($self) = @_;

  my $c = TestingPages->new(app => Mojolicious->new);
  $c->app->log->path(undef);
  $c->app->log->level('fatal');
  $self->{controller} = $c;
}

ホーム テストで、コントローラーのhomeメソッドを呼び出して結果を調べます。

sub home : Tests(2) {
  my($self) = @_;
  my $c = $self->{controller};
  $c->home;
  is $c->render_called, 1, "render called";
  is $c->render_arg->{title}, "Home", "correct title arg";
}

最後に、テストを実行します。

package main;
Test::SampleApp::Pages->runtests;

出力:

$ ./sampleapp.pl テスト
「/tmp/sampleapp/t」からテストを実行しています。
t/pages.t ..わかりました   
すべてのテストが成功しました。
ファイル=1、テスト=2、ウォールクロック 1 秒 (0.03 usr 0.02 sys + 0.24 cusr 0.03 csys = 0.32 CPU)
結果:合格

やり方がわかったので、問題は、それがすべての手間をかける価値があるかどうかです。コントローラは簡単な配線にする必要があります。コントローラーの複雑さが、テストがはるかに簡単なモデルに本当に属しているかどうかを検討してください。

于 2011-07-04T13:35:27.530 に答える