use Test::Base;
Tatsuhiko Miyagawa
miyagawa@gmail.com
Six Apart, Ltd. / Shibuya Perl Mongers

Shibuya.pm Tech Talks #7

Test::BaseとはTatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

データドリブン
テストベースクラス
Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

by Ingy döt Net
Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

use Test::More?

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

use Test::Base!
Test::More

Tatsuhiko Miyagawaと互換のあるインターフェース

2007/10/10 Shibuya.pm #7

Test::More compatible
use Test::More;plan tests => 2;
sub camelize {
local $_ = shift;s/_(¥w)/uc($1)/eg;$_;}is camelize("foo_bar"), "fooBar";is camelize("foo_bar_baz"), "fooBarBaz";

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

Test::More compatible
use Test::Base;plan tests => 2;
sub camelize {
local $_ = shift;s/_(¥w)/uc($1)/eg;$_;}is camelize("foo_bar"), "fooBar";is camelize("foo_bar_baz"), "fooBarBaz";

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

Test::Base-y code
use Test::Base;sub camelize {
local $_ = shift;s/_(¥w)/uc($1)/eg;$_;}filters { input => 'camelize' }__DATA__===--- input: foo_bar--- expected: fooBar===--- input: foo_bar_baz--- expected: fooBarBaz

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

Test::Base code
# 01-json.t
use Test::Base;
use JSON::Syck;sub json { JSON::Syck::Dump($_[0]) }run_is 'input' => 'expected';__END__=== Simple JSON Test--- input eval json
{ foo => "bar" }--- expected chomp{"foo":"bar"}

TatsuhikoMiyagawa

2007/10/10 Shibuya.pm #7

TAP compatible% prove –l 01-json.t
01-json....okAll tests successful.
Files=1, Tests=1, 0 wallclock secs ( 0.10 cusr +0.02 csys = 0.12 CPU)

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

use Test::Base# 01-json.t
use Test::Base;
use JSON::Syck;sub json { JSON::Syck::Dump($_[0]) }run_is 'input' => 'expected';__END__=== Simple JSON Test--- input eval json
{ foo => "bar" }--- expected chomp{"foo":"bar"}

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

Block names# 01-json.t
use Test::Base;
use JSON::Syck;sub json { JSON::Syck::Dump($_[0]) }run_is 'input' => 'expected';__END__=== Simple JSON Test--- input eval json
{ foo => "bar" }--- expected chomp{"foo":"bar"}

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

Filters# 01-json.t
use Test::Base;
use JSON::Syck;sub json { JSON::Syck::Dump($_[0]) }run_is 'input' => 'expected';__END__=== Simple JSON Test--- input eval json
{ foo => "bar" }--- expected chomp{"foo":"bar"}

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

perldoc Test::Base::Filter

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

Define Filters# 01-json.t
use Test::Base;
use JSON::Syck;sub json { JSON::Syck::Dump($_[0]) }run_is 'input' => 'expected';__END__=== Simple JSON Test--- input eval json
{ foo => "bar" }--- expected chomp{"foo":"bar"}

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

Filter arguments=== filter args--- input lines array tail=2 JoinfooBarbaz--- expected chomp regexp=xisbar.*baz

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

filters__DATA__=== test 1--- input foo bar bazxxx--- expected quox
yyy=== test 2--- input foo bar bazxxx--- expected quox
yyy=== test 3--- input foo bar bazxxx--- expected quox
yyy

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

filters
filters { input => [ 'foo', 'bar', 'baz' ], expected => 'quox' };__DATA__=== test 1--- inputxxx--- expectedyyy=== test 2--- inputxxx--- expectedyyy=== test 3--- inputxxx--- expectedyyy

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

run_is# 01-json.t
use Test::Base;
use JSON::Syck;sub json { JSON::Syck::Dump($_[0]) }run_is 'input' => 'expected';__END__===--- input eval json
{ foo => "bar" }--- expected chomp{"foo":"bar"}

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

Auto-diff
01-json....NOK 1#Failed test '# @@ -1,2 +1,2 @@# -{"foo":"bar"}# +{ foo => "bar" }# xxx# 'Requires Algorithm::Diff
Turn off with no_diff()

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

run_isrun_like
run_unlike
run_is_deeply
run_compare
Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

run_is default blocks# 01-json.t
use Test::Base;
use JSON::Syck;sub json { JSON::Syck::Dump($_[0]) }run_is;__END__===--- input eval json
{ foo => "bar" }--- expected chomp{"foo":"bar"}

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

run_is default blocks# 01-json.t
use Test::Base;
use JSON::Syck;sub json { JSON::Syck::Dump($_[0]) }run_is;__END__===--- xxx eval json
{ foo => "bar" }--- yyy chomp{"foo":"bar"}

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

run_compare# 01-json.t
use Test::Base;
use JSON::Syck;sub json { JSON::Syck::Dump($_[0]) }run_compare;__END__===--- input eval json
{ foo => "bar" }--- expected chomp{"foo":"bar"}===--- input eval json
{ foo => [ "bar", "baz" ] }--- expected regexp
bar.*bazTatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

run_compare is default!
# 01-json.t
use Test::Base;
use JSON::Syck;sub json { JSON::Syck::Dump($_[0]) }__END__===--- input eval json
{ foo => "bar" }--- expected chomp{"foo":"bar"}===--- input eval json
{ foo => [ "bar", "baz" ] }--- expected regexp
bar.*bazTatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

run# 01-json.t
use Test::Base;
use JSON::Syck;plan tests => 1 * blocks;
run {my $block = shift;
is JSON::Syck::Dump($block->input), $block->expected, $block->name;};__END__===--- input eval{ foo => "bar" }--- expected chomp{"foo":"bar"}

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

blocks()# 01-json.t
use Test::Base;
use JSON::Syck;plan tests => 1 * blocks;
for my $block (blocks) {is JSON::Syck::Dump($block->input), $block->expected, $block->name;}__END__===--- input eval{ foo => "bar" }--- expected chomp{"foo":"bar"}

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

Block specificuse Test::Base;
run_compare;__END__===--- ONLY--- input eval json
{ foo => "bar" }--- expected chomp{"foo":"bar"}===--- input eval json
{ foo => [ "bar", "baz" ] }--- expected regexp
bar.*bazTatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

Block specificuse Test::Base;
run_compare;__END__===--- SKIP--- input eval json
{ foo => "bar" }--- expected chomp{"foo":"bar"}===--- input eval json
{ foo => [ "bar", "baz" ] }--- expected regexp
bar.*bazTatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

Subclassing Test::Base# t/TestJSON.pm
package t::TestJSON;use Test::Base -Base;
use JSON::Syck;package t::TestJSON::Filter;
use Test::Base::Filter –base;sub json { JSON::Syck::Dump($_[0]) }# t/01-json.t
use t::TestJSON;__END__===--- input eval json
{ foo => "bar" }--- expected…
Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

In your CPAN modules
use inc::Module::Install;
name 'Foo-Bar';
all_from 'lib/Foo/Bar.pm';
use_test_base;WriteAll;

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

Tips

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

Spiffy XXX

XXX $foo = $bar;
WWW $bar;
YYY $baz;
ZZZ $quox;

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

no chomp filters
use Test::Base;filters { input => 'chomp', expected => 'chomp' }__END__===--- inputfoo--- expectedbar===--- input
fooaba--- expectedbzaahiepa
Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

no chomp filters
use Test::Base;__END__===--- input: foo--- expected: bar===--- input: fooaba--- expected: bzaahiepa

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

success tests vs. error tests# t/01-success.t
run_is 'input' => 'expected';# t/02-failure.trun {my $block = shift;eval { … };run_like $@, $block->expected;};

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

Test::Base に向かないテスト

複雑なAPI
オブジェクト状態が変化
Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

でうまくテストできない＝ 複雑なAPI
Test::BaseTatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

Design your API
SufficientlyAdvanced.
© Damian Conway

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

References
perldoc Test::Base
http://search.cpan.org/~miyagawa/?R=D

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

JSANTest.Base.js(PMConnect?)

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7

Refactoring Example
http://yapc.kwiki.org/data-driven-testing/slide10.html

Tatsuhiko Miyagawa

2007/10/10 Shibuya.pm #7