Skip Menu |

This queue is for tickets about the Test-Tester CPAN distribution.

Report information
The Basics
Id: 70766
Status: open
Priority: 0/
Queue: Test-Tester

People
Owner: Nobody in particular
Requestors: ether [...] cpan.org
RWSTAUNER [...] cpan.org
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 0.107
Fixed in: (no value)



Subject: Tested tests that call plan() cause confusing problems
If any of the tests being tested call plan() it causes lots of (very confusing) problems. Defining a dummy plan() function on Test::Tester::Delegate or Test::Tester::Capture made things work ok for me (no pun intended). I didn't notice any mention of plan() in Test::Tester so I didn't know if this was known-behavior or simply hadn't been addressed. I don't know if the solution is to define that function (and possibly do something with the values) or to merely document that it may be necessary. I am not sure how this would affect any subtests that get run inside of run_tests() and I am not sure if there would be a general practice that would be useful for most situations. Perhaps there is not and it should simply be a warning in the documentation that says that plans may need to be handled specially. The example where I hit this issue: I was specifically testing that Test::Spelling was operating on the files I configured... calling pod_file_spelling_ok() is a simple test and works just fine. However, all_pod_files_spelling_ok() sets the plan to the number of files it finds because it assumes it is the only test being run in the file. I have attached a test file that demonstrates the issue (and its output). Any thoughts?
Subject: tester-plan-output.txt
ok 1 - Test 'check single' completed ok 2 - Test 'check single' no premature diagnostication ok 3 - Test 'check single' result count ok 4 - subtest 'single' of 'check single' compare ok ok 5 - subtest 'single' of 'check single' compare name ok 6 - checking depth 1..6 ok 1 - check_single Use of uninitialized value $indent in concatenation (.) or string at /home/rando/perl5/perlbrew/perls/5.14.1-st/lib/5.14.1/Test/Builder.pm line 1754. not ok 1 - Test 'check all default plan()' completed # Failed test 'Test 'check all default plan()' completed' # at t/plan.t line 33. # Can't use an undefined value as a symbol reference at /home/rando/perl5/perlbrew/perls/5.14.1-st/lib/5.14.1/Test/Builder.pm line 1759. ok 2 - Test 'check all default plan()' no premature diagnostication not ok 3 - Test 'check all default plan()' result count # Failed test 'Test 'check all default plan()' result count' # at t/plan.t line 33. # got: 0 # expected: 1 not ok 4 - subtest '' of 'check all default plan()' compare ok # Failed test 'subtest '' of 'check all default plan()' compare ok' # at t/plan.t line 33. # got: undef # expected: '1' not ok 5 - subtest '' of 'check all default plan()' compare name # Failed test 'subtest '' of 'check all default plan()' compare name' # at t/plan.t line 33. # got: undef # expected: 'single' not ok 6 - checking depth # Failed test 'checking depth' # at t/plan.t line 33. # got: undef # expected: '2' # You need to change $Test::Builder::Level 1..6 # Looks like you failed 5 tests of 6. not ok 2 - check_all_default # Failed test 'check_all_default' # at t/plan.t line 36. ok 1 - Test 'check all dummy plan()' completed ok 2 - Test 'check all dummy plan()' no premature diagnostication ok 3 - Test 'check all dummy plan()' result count ok 4 - subtest 'single' of 'check all dummy plan()' compare ok ok 5 - subtest 'single' of 'check all dummy plan()' compare name ok 6 - checking depth 1..6 ok 3 - check_all_dummy 1..3 # Looks like you failed 1 test of 3.
Subject: tester-plan-test.pl
use strict; use warnings; use Test::Tester; use Test::More 0.88; { package Test::Tester::TestThingThatCallsPlan; use Exporter; our @ISA = qw(Exporter); our @EXPORT = qw(single_ok all_ok); my $Test = Test::Builder->new; sub single_ok { $Test->ok(1, 'single') } sub all_ok { $Test->plan(tests => 1); single_ok(); } } Test::Tester::TestThingThatCallsPlan->import(); subtest check_single => sub { check_test( sub { single_ok(); }, { ok => 1, name => 'single', depth => 1 }, 'check single' ); }; subtest check_all_default => sub { check_test( sub { all_ok(); }, { ok => 1, name => 'single', depth => 2 }, 'check all default plan()' ); }; subtest check_all_dummy => sub { check_test( sub { local *Test::Tester::Delegate::plan = sub {}; all_ok(); }, { ok => 1, name => 'single', depth => 2 }, 'check all dummy plan()' ); }; done_testing;
Subject: Re: [rt.cpan.org #70766] Tested tests that call plan() cause confusing problems
Date: Sat, 24 Sep 2011 15:00:55 +0100
To: bug-Test-Tester [...] rt.cpan.org
From: Fergal Daly <fergal [...] esatclear.ie>
Hi, sorry for not getting back sooner, I don't really do any Perl stuff any more. Why would your tests set the plan? I've never seen that. I guess if you had a test function that you expect to be the only thing called in a given .t file it would work but that still sounds odd. By the way, it looks like the new version of Test-Simple is going to have testing that's very similar to Test-Tester, you might want to raise this use case on the perl-qa list (or wherever mschwern is dealing with that), F
Show quoted text
> sorry for not getting back sooner, I don't really do any Perl stuff > any more. Why would your tests set the plan? I've never seen that. I > guess if you had a test function that you expect to be the only thing > called in a given .t file it would work but that still sounds odd.
That is exactly what I was testing. There are lots of modules out there, mostly xt (author or release) tests that are designed to work like that: you make a boilerplate test file and put that module's "all_tests_ok()" sort of function in the file. The synopsis for Test::Spelling (which is what I was testing) is a perfect example: Show quoted text
> use Test::More; > BEGIN { > plan skip_all => "Spelling tests only for authors" > unless -d 'inc/.author'; > } > > use Test::Spelling; > all_pod_files_spelling_ok();
I was actually testing changes to a Dist::Zilla plugin that generates a file very much like that and I wanted to confirm that the tests were in fact getting called (specifically that all my desired files were getting checked by that call). I would not be surprised to hear that I'm the first one who ever tried to use Test::Tester to do that. :-) Show quoted text
> By the way, it looks like the new version of Test-Simple is going to > have testing that's very similar to Test-Tester, you might want to > raise this use case on the perl-qa list (or wherever mschwern is > dealing with that), > > F
Ok, I'll keep that in mind. Thanks for the heads up! - R
You can see lots of examples of test modules that have a similar synopsis in Dist::Zilla::PluginBundle::TestingMania (which generates a bunch of these little test files that use the other test modules). https://metacpan.org/module/Dist::Zilla::PluginBundle::TestingMania Here's an example of the generated files: http://api.metacpan.org/source/DOHERTY/Dist-Zilla-PluginBundle-TestingMania-0.14/xt/release/ Typically each file is a very small boilerplate file that expects the real test module to run all the tests (and set the plan).
Subject: Re: [rt.cpan.org #70766] Tested tests that call plan() cause confusing problems
Date: Sun, 25 Sep 2011 11:02:11 +0100
To: bug-Test-Tester [...] rt.cpan.org
From: Fergal Daly <fergal [...] esatclear.ie>
The purpose of the plan is to make sure the expected number of tests are run. To make sure that the test file's _author_ does not have a bug in his test file such that some tests get skipped. So in the examples you give the plan should be for 1 test. The reason people have done otherwise is because there's no good way to do subplans (e.g. this test has N parts). In Test::Spelling for example, it could be refactored so that all_pod_files_spelling_ok calls $TEST->ok just once, passing if all files are OK. This would bring it into line with correct plan practice, it would make it possible to call other tests in the same file and it would eliminate the BEGIN block from the code example you gave which would then be use Test::More test => 1; use Test::Spelling SKIP: { skip "Spelling tests only for authors" unless -d 'inc/.author'; all_pod_files_spelling_ok(); } I think nothing is lost by doing it this way. If Test::Spelling dies half way through one of the files the overall test still fails and the plan is violated. Anyway, since this seems to be a common practice, I don't mind supporting testing planning but I have no time to do it. If you want to send a patch, I will make release and upload it, F
I've put patching this into my "queue", but I haven't had the time yet, and I haven't given any thought to the API yet. However I did just run into another issue with it, so I think I probably will do something, just need to figure out what, and find the time to implement. Originally I had simply defined plan() to an empty sub so that it would essentially be ignored if called. That worked fine for plans that declare the number of tests, but again I got very confused at the mass of angry output when the plan was for 'skip_all'. That's something else I need to keep in mind as I try to determine a useful API. Thanks for the help, and hopefully you'll hear from me again sometime soon with a patch ;-)
I've run into this too, when attempting to write tests for Test::Kwalitee before undertaking a big refactoring effort. Test::Kwalitee also calls plan() directly -- right in its import sub, even!!! In light of this open ticket, I think the best recourse is to change Test::Kwalitee to not call plan(), and instead, call done_testing in an END block (which will occur after Test::Tester has done its thing). I agree it's bad practice for Test modules to create their own plan -- unfortunately, many of them do it, and to alter this behaviour will break everyone who is using these tests (less of a big deal with autogenerated tests, as we can fix the generator, but there's *lots* of manual users of these tests too). These are the bad ones that I'm using in just one dist that I checked: Test::Spelling Test::CPAN::Meta Test::EOL Test::MinimumVersion Test::NoTabs Test::Pod The only option that I can see is to create a major version bump in the module, and keep the old behaviour if the explicit version is not specified, e.g.: use Test::Kwalitee; # creates a plan for itself, and also warns the user they should upgrade but use Test::Kwalitee 2; # no plan - you must call done_testing yourself