0
use Test::Base; Tatsuhiko Miyagawa   [email_address] Six Apart, Ltd. / Shibuya Perl Mongers Shibuya.pm Tech Talks #7
<ul><li>Test::Base </li></ul><ul><li>とは </li></ul>
<ul><li>データドリブン </li></ul><ul><li>テストベースクラス </li></ul>
<ul><li>by Ingy döt Net </li></ul>
<ul><li>use Test::More? </li></ul>
<ul><li>use Test::Base! </li></ul><ul><li>Test::More  と互換のあるインターフェース </li></ul>
Test::More compatible <ul><li>use Test::More; </li></ul><ul><li>plan tests => 2; </li></ul><ul><li>sub camelize { </li></u...
Test::More compatible <ul><li>use Test::Base; </li></ul><ul><li>plan tests => 2; </li></ul><ul><li>sub camelize { </li></u...
Test::Base-y code <ul><li>use Test::Base; </li></ul><ul><li>sub camelize { </li></ul><ul><li>local $_ = shift; </li></ul><...
Test::Base code <ul><li># 01-json.t </li></ul><ul><li>use Test::Base; </li></ul><ul><li>use JSON::Syck; </li></ul><ul><li>...
TAP compatible <ul><li>% prove –l 01-json.t </li></ul><ul><li>01-json....ok </li></ul><ul><li>All tests successful. </li><...
use Test::Base <ul><li># 01-json.t </li></ul><ul><li>use Test::Base; </li></ul><ul><li>use JSON::Syck; </li></ul><ul><li>s...
Block names <ul><li># 01-json.t </li></ul><ul><li>use Test::Base; </li></ul><ul><li>use JSON::Syck; </li></ul><ul><li>sub ...
Filters <ul><li># 01-json.t </li></ul><ul><li>use Test::Base; </li></ul><ul><li>use JSON::Syck; </li></ul><ul><li>sub json...
<ul><li>perldoc Test::Base::Filter </li></ul>
Define Filters <ul><li># 01-json.t </li></ul><ul><li>use Test::Base; </li></ul><ul><li>use JSON::Syck; </li></ul><ul><li>s...
Filter arguments === filter args --- input lines array tail=2 Join foo Bar baz --- expected chomp regexp=xis bar.*baz
filters __DATA__ === test 1 --- input  foo bar baz xxx --- expected  quox yyy === test 2 --- input  foo bar baz xxx --- ex...
filters filters { input => [ 'foo', 'bar', 'baz' ], expected => 'quox' }; __DATA__ === test 1 --- input xxx --- expected y...
run_is <ul><li># 01-json.t </li></ul><ul><li>use Test::Base; </li></ul><ul><li>use JSON::Syck; </li></ul><ul><li>sub json ...
Auto-diff 01-json....NOK 1 #  Failed test ' # @@ -1,2 +1,2 @@ # -{&quot;foo&quot;:&quot;bar&quot;} # +{ foo => &quot;bar&q...
<ul><li>run_is </li></ul><ul><li>run_like </li></ul><ul><li>run_unlike </li></ul><ul><li>run_is_deeply </li></ul><ul><li>r...
run_is default blocks <ul><li># 01-json.t </li></ul><ul><li>use Test::Base; </li></ul><ul><li>use JSON::Syck; </li></ul><u...
run_is default blocks <ul><li># 01-json.t </li></ul><ul><li>use Test::Base; </li></ul><ul><li>use JSON::Syck; </li></ul><u...
run_compare <ul><li># 01-json.t </li></ul><ul><li>use Test::Base; </li></ul><ul><li>use JSON::Syck; </li></ul><ul><li>sub ...
run_compare is default! # 01-json.t use Test::Base; use JSON::Syck; sub json { JSON::Syck::Dump($_[0]) } __END__ === --- i...
run # 01-json.t use Test::Base; use JSON::Syck; plan tests => 1 * blocks; run { my $block = shift; is JSON::Syck::Dump($bl...
blocks() # 01-json.t use Test::Base; use JSON::Syck; plan tests =>  1 * blocks; for my $block (blocks) { is JSON::Syck::Du...
Block specific use Test::Base; run_compare; __END__ === --- ONLY --- input eval json { foo => &quot;bar&quot; } --- expect...
Block specific use Test::Base; run_compare; __END__ === --- SKIP --- input eval json { foo => &quot;bar&quot; } --- expect...
Subclassing Test::Base # t/TestJSON.pm package t::TestJSON; use Test::Base -Base; use JSON::Syck; package t::TestJSON::Fil...
In your CPAN modules use inc::Module::Install; name 'Foo-Bar'; all_from 'lib/Foo/Bar.pm'; use_test_base; WriteAll;
<ul><li>Tips </li></ul>
Spiffy XXX XXX $foo = $bar; WWW $bar; YYY $baz; ZZZ $quox;
no chomp filters use Test::Base; filters { input => 'chomp', expected => 'chomp' } __END__ === --- input foo --- expected ...
no chomp filters use Test::Base; __END__ === --- input: foo --- expected: bar === --- input: fooaba --- expected: bzaahiepa
success tests vs. error tests # t/01-success.t run_is 'input' => 'expected'; # t/02-failure.t run { my $block = shift; eva...
Test::Base  に向かないテスト <ul><li>複雑な API </li></ul><ul><li>オブジェクト状態が変化 </li></ul>
<ul><li>Test::Base  で </li></ul><ul><li>うまくテストできない </li></ul><ul><li>= 複雑な API </li></ul>
<ul><li>Design your API </li></ul><ul><li>Sufficiently  </li></ul><ul><li>Advanced. </li></ul><ul><li>© Damian Conway </li...
<ul><li>References </li></ul><ul><li>perldoc Test::Base </li></ul><ul><li>http://search.cpan.org/~miyagawa/?R=D </li></ul>
<ul><li>JSAN </li></ul><ul><li>Test.Base.js </li></ul><ul><li>(PMConnect?) </li></ul>
<ul><li>Refactoring Example </li></ul><ul><li>http://yapc.kwiki.org/data-driven-testing/slide10.html </li></ul>
Upcoming SlideShare
Loading in...5
×

Test::Base

4,533

Published on

Shibuya.pm tech talk #6

Published in: Technology
1 Comment
1 Like
Statistics
Notes
No Downloads
Views
Total Views
4,533
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
71
Comments
1
Likes
1
Embeds 0
No embeds

No notes for slide

Transcript of "Test::Base"

  1. 1. use Test::Base; Tatsuhiko Miyagawa [email_address] Six Apart, Ltd. / Shibuya Perl Mongers Shibuya.pm Tech Talks #7
  2. 2. <ul><li>Test::Base </li></ul><ul><li>とは </li></ul>
  3. 3. <ul><li>データドリブン </li></ul><ul><li>テストベースクラス </li></ul>
  4. 4. <ul><li>by Ingy döt Net </li></ul>
  5. 5. <ul><li>use Test::More? </li></ul>
  6. 6. <ul><li>use Test::Base! </li></ul><ul><li>Test::More と互換のあるインターフェース </li></ul>
  7. 7. Test::More compatible <ul><li>use Test::More; </li></ul><ul><li>plan tests => 2; </li></ul><ul><li>sub camelize { </li></ul><ul><li>local $_ = shift; </li></ul><ul><li>s/_(w)/uc($1)/eg; </li></ul><ul><li>$_; </li></ul><ul><li>} </li></ul><ul><li>is camelize(&quot;foo_bar&quot;), &quot;fooBar&quot;; </li></ul><ul><li>is camelize(&quot;foo_bar_baz&quot;), &quot;fooBarBaz&quot;; </li></ul>
  8. 8. Test::More compatible <ul><li>use Test::Base; </li></ul><ul><li>plan tests => 2; </li></ul><ul><li>sub camelize { </li></ul><ul><li>local $_ = shift; </li></ul><ul><li>s/_(w)/uc($1)/eg; </li></ul><ul><li>$_; </li></ul><ul><li>} </li></ul><ul><li>is camelize(&quot;foo_bar&quot;), &quot;fooBar&quot;; </li></ul><ul><li>is camelize(&quot;foo_bar_baz&quot;), &quot;fooBarBaz&quot;; </li></ul>
  9. 9. Test::Base-y code <ul><li>use Test::Base; </li></ul><ul><li>sub camelize { </li></ul><ul><li>local $_ = shift; </li></ul><ul><li>s/_(w)/uc($1)/eg; </li></ul><ul><li>$_; </li></ul><ul><li>} </li></ul><ul><li>filters { input => 'camelize' } </li></ul><ul><li>__DATA__ </li></ul><ul><li>=== </li></ul><ul><li>--- input: foo_bar </li></ul><ul><li>--- expected: fooBar </li></ul><ul><li>=== </li></ul><ul><li>--- input: foo_bar_baz </li></ul><ul><li>--- expected: fooBarBaz </li></ul>
  10. 10. Test::Base code <ul><li># 01-json.t </li></ul><ul><li>use Test::Base; </li></ul><ul><li>use JSON::Syck; </li></ul><ul><li>sub json { JSON::Syck::Dump($_[0]) } </li></ul><ul><li>run_is 'input' => 'expected'; </li></ul><ul><li>__END__ </li></ul><ul><li>=== Simple JSON Test </li></ul><ul><li>--- input eval json </li></ul><ul><li>{ foo => &quot;bar&quot; } </li></ul><ul><li>--- expected chomp </li></ul><ul><li>{&quot;foo&quot;:&quot;bar&quot;} </li></ul>
  11. 11. TAP compatible <ul><li>% prove –l 01-json.t </li></ul><ul><li>01-json....ok </li></ul><ul><li>All tests successful. </li></ul><ul><li>Files=1, Tests=1, 0 wallclock secs ( 0.10 cusr + 0.02 csys = 0.12 CPU) </li></ul>
  12. 12. use Test::Base <ul><li># 01-json.t </li></ul><ul><li>use Test::Base; </li></ul><ul><li>use JSON::Syck; </li></ul><ul><li>sub json { JSON::Syck::Dump($_[0]) } </li></ul><ul><li>run_is 'input' => 'expected'; </li></ul><ul><li>__END__ </li></ul><ul><li>=== Simple JSON Test </li></ul><ul><li>--- input eval json </li></ul><ul><li>{ foo => &quot;bar&quot; } </li></ul><ul><li>--- expected chomp </li></ul><ul><li>{&quot;foo&quot;:&quot;bar&quot;} </li></ul>
  13. 13. Block names <ul><li># 01-json.t </li></ul><ul><li>use Test::Base; </li></ul><ul><li>use JSON::Syck; </li></ul><ul><li>sub json { JSON::Syck::Dump($_[0]) } </li></ul><ul><li>run_is ' input ' => ' expected '; </li></ul><ul><li>__END__ </li></ul><ul><li>=== Simple JSON Test </li></ul><ul><li>--- input eval json </li></ul><ul><li>{ foo => &quot;bar&quot; } </li></ul><ul><li>--- expected chomp </li></ul><ul><li>{&quot;foo&quot;:&quot;bar&quot;} </li></ul>
  14. 14. Filters <ul><li># 01-json.t </li></ul><ul><li>use Test::Base; </li></ul><ul><li>use JSON::Syck; </li></ul><ul><li>sub json { JSON::Syck::Dump($_[0]) } </li></ul><ul><li>run_is 'input' => 'expected'; </li></ul><ul><li>__END__ </li></ul><ul><li>=== Simple JSON Test </li></ul><ul><li>--- input eval json </li></ul><ul><li>{ foo => &quot;bar&quot; } </li></ul><ul><li>--- expected chomp </li></ul><ul><li>{&quot;foo&quot;:&quot;bar&quot;} </li></ul>
  15. 15. <ul><li>perldoc Test::Base::Filter </li></ul>
  16. 16. Define Filters <ul><li># 01-json.t </li></ul><ul><li>use Test::Base; </li></ul><ul><li>use JSON::Syck; </li></ul><ul><li>sub json { JSON::Syck::Dump($_[0]) } </li></ul><ul><li>run_is 'input' => 'expected'; </li></ul><ul><li>__END__ </li></ul><ul><li>=== Simple JSON Test </li></ul><ul><li>--- input eval json </li></ul><ul><li>{ foo => &quot;bar&quot; } </li></ul><ul><li>--- expected chomp </li></ul><ul><li>{&quot;foo&quot;:&quot;bar&quot;} </li></ul>
  17. 17. Filter arguments === filter args --- input lines array tail=2 Join foo Bar baz --- expected chomp regexp=xis bar.*baz
  18. 18. filters __DATA__ === test 1 --- input foo bar baz xxx --- expected quox yyy === test 2 --- input foo bar baz xxx --- expected quox yyy === test 3 --- input foo bar baz xxx --- expected quox yyy
  19. 19. filters filters { input => [ 'foo', 'bar', 'baz' ], expected => 'quox' }; __DATA__ === test 1 --- input xxx --- expected yyy === test 2 --- input xxx --- expected yyy === test 3 --- input xxx --- expected yyy
  20. 20. run_is <ul><li># 01-json.t </li></ul><ul><li>use Test::Base; </li></ul><ul><li>use JSON::Syck; </li></ul><ul><li>sub json { JSON::Syck::Dump($_[0]) } </li></ul><ul><li>run_is 'input' => 'expected'; </li></ul><ul><li>__END__ </li></ul><ul><li>=== </li></ul><ul><li>--- input eval json </li></ul><ul><li>{ foo => &quot;bar&quot; } </li></ul><ul><li>--- expected chomp </li></ul><ul><li>{&quot;foo&quot;:&quot;bar&quot;} </li></ul>
  21. 21. Auto-diff 01-json....NOK 1 # Failed test ' # @@ -1,2 +1,2 @@ # -{&quot;foo&quot;:&quot;bar&quot;} # +{ foo => &quot;bar&quot; } # xxx # ' Requires Algorithm::Diff Turn off with no_diff()
  22. 22. <ul><li>run_is </li></ul><ul><li>run_like </li></ul><ul><li>run_unlike </li></ul><ul><li>run_is_deeply </li></ul><ul><li>run_compare </li></ul>
  23. 23. run_is default blocks <ul><li># 01-json.t </li></ul><ul><li>use Test::Base; </li></ul><ul><li>use JSON::Syck; </li></ul><ul><li>sub json { JSON::Syck::Dump($_[0]) } </li></ul><ul><li>run_is; </li></ul><ul><li>__END__ </li></ul><ul><li>=== </li></ul><ul><li>--- input eval json </li></ul><ul><li>{ foo => &quot;bar&quot; } </li></ul><ul><li>--- expected chomp </li></ul><ul><li>{&quot;foo&quot;:&quot;bar&quot;} </li></ul>
  24. 24. run_is default blocks <ul><li># 01-json.t </li></ul><ul><li>use Test::Base; </li></ul><ul><li>use JSON::Syck; </li></ul><ul><li>sub json { JSON::Syck::Dump($_[0]) } </li></ul><ul><li>run_is; </li></ul><ul><li>__END__ </li></ul><ul><li>=== </li></ul><ul><li>--- xxx eval json </li></ul><ul><li>{ foo => &quot;bar&quot; } </li></ul><ul><li>--- yyy chomp </li></ul><ul><li>{&quot;foo&quot;:&quot;bar&quot;} </li></ul>
  25. 25. run_compare <ul><li># 01-json.t </li></ul><ul><li>use Test::Base; </li></ul><ul><li>use JSON::Syck; </li></ul><ul><li>sub json { JSON::Syck::Dump($_[0]) } </li></ul><ul><li>run_compare; </li></ul><ul><li>__END__ </li></ul><ul><li>=== </li></ul><ul><li>--- input eval json </li></ul><ul><li>{ foo => &quot;bar&quot; } </li></ul><ul><li>--- expected chomp </li></ul><ul><li>{&quot;foo&quot;:&quot;bar&quot;} </li></ul><ul><li>=== </li></ul><ul><li>--- input eval json </li></ul><ul><li>{ foo => [ &quot;bar&quot;, &quot;baz&quot; ] } </li></ul><ul><li>--- expected regexp </li></ul><ul><li>bar.*baz </li></ul>
  26. 26. run_compare is default! # 01-json.t use Test::Base; use JSON::Syck; sub json { JSON::Syck::Dump($_[0]) } __END__ === --- input eval json { foo => &quot;bar&quot; } --- expected chomp {&quot;foo&quot;:&quot;bar&quot;} === --- input eval json { foo => [ &quot;bar&quot;, &quot;baz&quot; ] } --- expected regexp bar.*baz
  27. 27. 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 => &quot;bar&quot; } --- expected chomp {&quot;foo&quot;:&quot;bar&quot;}
  28. 28. 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 => &quot;bar&quot; } --- expected chomp {&quot;foo&quot;:&quot;bar&quot;}
  29. 29. Block specific use Test::Base; run_compare; __END__ === --- ONLY --- input eval json { foo => &quot;bar&quot; } --- expected chomp {&quot;foo&quot;:&quot;bar&quot;} === --- input eval json { foo => [ &quot;bar&quot;, &quot;baz&quot; ] } --- expected regexp bar.*baz
  30. 30. Block specific use Test::Base; run_compare; __END__ === --- SKIP --- input eval json { foo => &quot;bar&quot; } --- expected chomp {&quot;foo&quot;:&quot;bar&quot;} === --- input eval json { foo => [ &quot;bar&quot;, &quot;baz&quot; ] } --- expected regexp bar.*baz
  31. 31. 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 => &quot;bar&quot; } --- expected …
  32. 32. In your CPAN modules use inc::Module::Install; name 'Foo-Bar'; all_from 'lib/Foo/Bar.pm'; use_test_base; WriteAll;
  33. 33. <ul><li>Tips </li></ul>
  34. 34. Spiffy XXX XXX $foo = $bar; WWW $bar; YYY $baz; ZZZ $quox;
  35. 35. no chomp filters use Test::Base; filters { input => 'chomp', expected => 'chomp' } __END__ === --- input foo --- expected bar === --- input fooaba --- expected bzaahiepa
  36. 36. no chomp filters use Test::Base; __END__ === --- input: foo --- expected: bar === --- input: fooaba --- expected: bzaahiepa
  37. 37. success tests vs. error tests # t/01-success.t run_is 'input' => 'expected'; # t/02-failure.t run { my $block = shift; eval { … }; run_like $@, $block->expected; } ;
  38. 38. Test::Base に向かないテスト <ul><li>複雑な API </li></ul><ul><li>オブジェクト状態が変化 </li></ul>
  39. 39. <ul><li>Test::Base で </li></ul><ul><li>うまくテストできない </li></ul><ul><li>= 複雑な API </li></ul>
  40. 40. <ul><li>Design your API </li></ul><ul><li>Sufficiently </li></ul><ul><li>Advanced. </li></ul><ul><li>© Damian Conway </li></ul>
  41. 41. <ul><li>References </li></ul><ul><li>perldoc Test::Base </li></ul><ul><li>http://search.cpan.org/~miyagawa/?R=D </li></ul>
  42. 42. <ul><li>JSAN </li></ul><ul><li>Test.Base.js </li></ul><ul><li>(PMConnect?) </li></ul>
  43. 43. <ul><li>Refactoring Example </li></ul><ul><li>http://yapc.kwiki.org/data-driven-testing/slide10.html </li></ul>
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×