Re: Inverting test conditions in Test::More ?
by hippo (Archbishop) on Jul 24, 2020 at 09:59 UTC
|
There doesn't seem to be a simple, generic way to negate an arbitrary test in Test::More AFAICT. But, if you are happy enough to dip your toe in the Test2::Suite waters:
use strict;
use warnings;
use Test2::V0;
use Test2::Tools::Compare qw/is isnt/;
my $w = { z => [ 0 .. 5 ] };
my $x = { z => [ 0 .. 5 ] };
my $y = { z => [ 1 .. 5 ] };
is ($w, $x, 'Match is good');
isnt ($x, $y, 'Not matching - also good');
done_testing;
| [reply] [d/l] |
|
|
Thanks, finally someone accepting my question! :)
> There doesn't seem to be a simple, generic way to negate an arbitrary test in Test::More AFAICT.
I just realized that all tests return a boolean result.
So here a workaround:
use strict;
use warnings;
use Test::More;
sub fail_ok (&;@) {
my ($code,$description) = @_;
my $result;
TODO:
{
local $TODO= "should be silent";
my $result = $code->();
}
$result
? fail($description)
: pass($description);
}
fail_ok { is(1,2,"") }
"Bingo! Test failed";
done_testing;
The TODO block ensures that there is no failed test in the final result.
But I still need to understand how to make the output of the failed inner test silent ... °
... I probably need to redirect the STDERR output of Test::Builder or fiddle with TAP altogether
-*- mode: compilation; default-directory: "d:/exp/" -*-
Compilation started at Fri Jul 24 13:02:20
C:/Perl_524/bin\perl.exe -w d:/exp/pm_negate_test.pl
not ok 1 - # TODO should be silent
# Failed (TODO) test ''
# at d:/exp/pm_negate_test.pl line 21.
# got: '1'
# expected: '2'
ok 2 - Bingo! Test failed
1..2
Compilation finished at Fri Jul 24 13:02:21
°) Hmm... probably with subtests... | [reply] [d/l] [select] |
|
|
my $cond = 1 == 2;
ok( $cond ); # fails
ok( ! $cond ); # passes
... or whatever boolean condition.
If the latter, Test::Builder::Tester seems designed to test other tests.
To be fair, I could be misunderstanding - this is not a use case I've come across before.
| [reply] [d/l] |
|
|
|
|
use strict;
use warnings;
use Test::More;
my $Test = Test::Builder->new;
sub fail_ok (&;@) {
my ($code,$description) = @_;
# --- silence output
my $ignore;
$Test->output(\$ignore);
$Test->failure_output(\$ignore);
$Test->todo_output(\$ignore);
my $result;
TODO:
{
local $TODO= "should be silent";
#my $result = subtest "Negation of $description", $code;
my $result = $code->();
}
# --- undo silence
$Test->reset_outputs;
# --- output result
$result
? fail($description)
: pass($description);
}
fail_ok { is(1,2,"") }
"Bingo! Test failed";
fail_ok { is(1,3,"") }
"Bingo! Test failed again";
done_testing;
C:/Perl_524/bin\perl.exe -w d:/exp/pm_negate_test.pl
ok 2 - Bingo! Test failed
ok 4 - Bingo! Test failed again
1..4
| [reply] [d/l] [select] |
Re: Inverting test conditions in Test::More ?
by Corion (Patriarch) on Jul 24, 2020 at 09:05 UTC
|
Why don't you test directly for where you know the difference is? You won't need is_deeply since you don't need to check all elements. You only need to check that there is at least one difference, and if you know your input data, you know where to find the difference.
| [reply] [d/l] |
|
|
| [reply] |
|
|
| [reply] [d/l] |
|
|
|
|
|
|
|
Sounds like you're just trying to illicit specific responses. Better to just come out and say what you want to say rather than attempt to be coy about it.
| [reply] |
Re: Inverting test conditions in Test::More ?
by perlfan (Parson) on Jul 24, 2020 at 09:15 UTC
|
Looks like you could easily use Test::More::_deep_check to create is_not_deeply and submit a PR. Of course, either you're the first person ever to need this or there's something fundamentally wrong with whatever it is that you're doing. Is there a reason you must do "is_not_deeply" when a test to make sure "is_deeply" would suffice? I'm still not quite sure what it is you're testing.
>I could just serialize a nested structure
If you can ensure consistent/ordered serialization in the case of your structures being hash refs (or use Tie::IxHash somehow, I suppose. But this doesn't seem to be the right approach if you're reaching for deeply comparing two structures. Consider that you'd probably need to write unit tests to test that your serialization is coming out as expected. | [reply] [d/l] [select] |
|
|
Supposing I just wanted to test deeply nested structures ...
> Looks like you could easily use Test::More::_deep_check
that's an internal function, Test::More provides explain() for serialization within the regular API
see also eq_array() and eq_hash() but "they may be deprecated in future versions."
> If you can ensure consistent/ordered serialization in the case of your structures being hash refs
Please note that the order of hash-keys within the same Perl run is guarantied to be stable.
Furthermore is explain() ordering hash-keys alphabetically AFAICT.
( Data::Dump too IIRC )
| [reply] |
|
|
| [reply] |
|
|
| [reply] |
|
|