Skip Menu |
 

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

Report information
The Basics
Id: 102380
Status: open
Priority: 0/
Queue: Test-DatabaseRow

People
Owner: Nobody in particular
Requestors: pickardj79 [...] gmail.com
Cc:
AdminCc:

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



Subject: numeric comparisons against string database values
Date: Thu, 26 Feb 2015 12:43:07 -0500
To: bug-Test-DatabaseRow [...] rt.cpan.org
From: John Pickard <pickardj79 [...] gmail.com>
Download (untitled) / with headers
text/plain 3.3k
Test-DatabaseRow-2.04 First, thanks! Thanks for reading this email, thanks for creating and maintaining Test::DatabaseRow. I've run into an issue with row_ok when tests is an arrayref. The comparison operation is evaluating to '==' when the expected looks like a number but the database value is a string. I think this is only an issue for '==' vs. 'eq' (not > vs. 'gt') because equality is assumed when tests is an arrayref. Of course this is easiest to explain with an example. For this example I have a test database as 'testing' and have run the following sql: create table testing.test_databaserow ( strcol varchar(20) default null ); insert into testing.test_databaserow (strcol) values ( '11,22' ); For the following perl code, I would expect the first two tests to fail, the third to pass. Using Test::DatabaseRow v2.04 the first test passes: #!/usr/bin/perl use strict; use warnings FATAL => 'all'; use Test::DatabaseRow; use Test::More tests => 3; my $dbh = <YOUR DATABASE HANDLE>; row_ok( sql => "select strcol from testing.test_databaserow", results => 1, tests => [ strcol => '11' ], dbh => $dbh, ); row_ok( sql => "select strcol from testing.test_databaserow", results => 1, tests => [ strcol => '11,' ], dbh => $dbh, ); row_ok( sql => "select strcol from testing.test_databaserow", results => 1, tests => [ strcol => '11,22' ], dbh => $dbh, ); This issue may be what is referred to as an "annoying case" in the comment on line 263 of Test::DatabaseRow::Object, however I think it is more than annoying since it erroneously allows tests to pass. I think the problem (if you agree it's a problem) stems from the override of the warning signal handler on line 399, this is a bit severe for avoiding undef comparisons. What if this was just a "no warnings 'uninitialized';"? I realize that that doesn't really solve the issue (just produces warnings). Ignoring that, here are my thoughts as "fixes": 1) Look at attached Object1.pm. Change $oper to "eq" if either $expect or $got =~ /\A $RE{num}{real} \z/x on ~line 396 (really only need to do check with $got, since we already looked at $expect when coercing tests): my $adj_oper = $oper eq '==' && $got !~ /\A $RE{num}{real} \z/x ? 'eq' : $oper; Then change other uses of $oper to $adj_oper, lines 401, 406, 407, and 413-415 This feels a little bit like a hack to me but it does solve the problem. 2) Look at attached Object2.pm. Use the sig warn to set the test to failed if a warning other than uninitialized is raised. I implemented this with a new local variable called $got_warnings which if set will set $passed to 0. Remove line 399 and add my $got_warning; no warnings 'uninitialized'; local $SIG{__WARN__} = sub { $got_warning = 1; }; # $^W not work Then add "$passed = 0 if $got_warning;" after the eval. Unfortunately, the diagnostics for this don't work because $oper is still '==' so _is_diag will print the got as a number and the got/expected look the same in the printout: not ok 1 - simple db test # Failed test 'simple db test' # at ../Tickets/Testing/Packages/Test_DatabaseRow.pl line 21. # While checking column 'strcol' on 1st row # got: 11 # expected: 11 I do not have a solution to this diag problem :(. Maybe pass a way to force printing as strings to_is_diag (ugh... not in Object2.pm)? Best, John
Download Object1.pm
text/x-perl 24k

Message body is not shown because sender requested not to inline it.

Download Object2.pm
text/x-perl 23.9k

Message body is not shown because sender requested not to inline it.

Subject: Re: [rt.cpan.org #102380] AutoReply: numeric comparisons against string database values
Date: Fri, 27 Feb 2015 15:22:46 -0500
To: bug-Test-DatabaseRow [...] rt.cpan.org
From: John Pickard <jep5m [...] virginia.edu>
Download (untitled) / with headers
text/plain 4.8k
Sorry, I now see in the documentation where it quite clearly states that "Any expected value that looks like a number will be compared numerically". However, the documentation also states that "The function will try and Do The Right Thing" and I'd argue that using a string comparison when the "got" value is a string is closer to the right thing :). Thanks again! John On Thu, Feb 26, 2015 at 12:43 PM, Bugs in Test-DatabaseRow via RT < bug-Test-DatabaseRow@rt.cpan.org> wrote: Show quoted text
> > Greetings, > > This message has been automatically generated in response to the > creation of a trouble ticket regarding: > "numeric comparisons against string database values", > a summary of which appears below. > > There is no need to reply to this message right now. Your ticket has been > assigned an ID of [rt.cpan.org #102380]. Your ticket is accessible > on the web at: > > https://rt.cpan.org/Ticket/Display.html?id=102380 > > Please include the string: > > [rt.cpan.org #102380] > > in the subject line of all future correspondence about this issue. To do > so, > you may reply to this message. > > Thank you, > bug-Test-DatabaseRow@rt.cpan.org > > ------------------------------------------------------------------------- > Test-DatabaseRow-2.04 > > First, thanks! Thanks for reading this email, thanks for creating and > maintaining Test::DatabaseRow. > > I've run into an issue with row_ok when tests is an arrayref. The > comparison operation is evaluating to '==' when the expected looks like a > number but the database value is a string. I think this is only an issue > for '==' vs. 'eq' (not > vs. 'gt') because equality is assumed when tests > is an arrayref. > > Of course this is easiest to explain with an example. For this example I > have a test database as 'testing' and have run the following sql: > > create table testing.test_databaserow ( > strcol varchar(20) default null > ); > > insert into testing.test_databaserow (strcol) values ( '11,22' ); > > > For the following perl code, I would expect the first two tests to fail, > the third to pass. Using Test::DatabaseRow v2.04 the first test passes: > > #!/usr/bin/perl > > use strict; > use warnings FATAL => 'all'; > > use Test::DatabaseRow; > use Test::More tests => 3; > > my $dbh = <YOUR DATABASE HANDLE>; > > row_ok( > sql => "select strcol from testing.test_databaserow", > results => 1, > tests => [ strcol => '11' ], > dbh => $dbh, > ); > > row_ok( > sql => "select strcol from testing.test_databaserow", > results => 1, > tests => [ strcol => '11,' ], > dbh => $dbh, > ); > > row_ok( > sql => "select strcol from testing.test_databaserow", > results => 1, > tests => [ strcol => '11,22' ], > dbh => $dbh, > ); > > > This issue may be what is referred to as an "annoying case" in the comment > on line 263 of Test::DatabaseRow::Object, however I think it is more than > annoying since it erroneously allows tests to pass. I think the problem (if > you agree it's a problem) stems from the override of the warning signal > handler on line 399, this is a bit severe for avoiding undef comparisons. > What if this was just a "no warnings 'uninitialized';"? I realize that that > doesn't really solve the issue (just produces warnings). Ignoring that, > here are my thoughts as "fixes": > > 1) Look at attached Object1.pm. Change $oper to "eq" if either $expect or > $got =~ /\A $RE{num}{real} \z/x on ~line 396 (really only need to do check > with $got, since we already looked at $expect when coercing tests): > my $adj_oper = $oper eq '==' && $got !~ /\A $RE{num}{real} \z/x > ? 'eq' > : $oper; > Then change other uses of $oper to $adj_oper, lines 401, 406, 407, and > 413-415 > This feels a little bit like a hack to me but it does solve the > problem. > > 2) Look at attached Object2.pm. Use the sig warn to set the test to failed > if a warning other than uninitialized is raised. I implemented this with a > new local variable called $got_warnings which if set will set $passed to 0. > Remove line 399 and add > my $got_warning; > no warnings 'uninitialized'; > local $SIG{__WARN__} = sub { $got_warning = 1; }; # $^W not work > > Then add "$passed = 0 if $got_warning;" after the eval. Unfortunately, > the diagnostics for this don't work because $oper is still '==' so _is_diag > will print the got as a number and the got/expected look the same in the > printout: > not ok 1 - simple db test > # Failed test 'simple db test' > # at ../Tickets/Testing/Packages/Test_DatabaseRow.pl line 21. > # While checking column 'strcol' on 1st row > # got: 11 > # expected: 11 > > I do not have a solution to this diag problem :(. Maybe pass a way to > force printing as strings to_is_diag (ugh... not in Object2.pm)? > > > Best, > John >
Subject: Re: [rt.cpan.org #102380] AutoReply: numeric comparisons against string database values
Date: Sun, 1 Mar 2015 09:24:34 -0500
To: bug-Test-DatabaseRow [...] rt.cpan.org
From: Mark Fowler <mark [...] twoshortplanks.com>
Download (untitled) / with headers
text/plain 6.3k
Hi John, So I've been thinking about this a lot over the last few days. Here's the thing: I don't want the behaviour to change based on what the database returned. I expect the "mode" we're in to be deterministic just from the Perl side. Having the mode change based on what the return data is seems to lead us down the smart-match-is-too-clever problem. OTOH, I see your point. While 11 and 11.0 should probably match, 11 and 11,12 should probably not. What we could do is add smarts to _also_ check that the database return value looks like a number when in numeric mode. This leads us onto another problem. We'd need to work out an API that allowed explicitly turning on this mode as well. Which in turn leads us onto the problem of reworking the API so we could have arbitrary comparisons. This is a long standing issue that I wanted to look into because Test::DatabaseRow currently assumes each column value is a plain old scalar, but with databases like postgres they can be entire arrayrefs or more complex data structures and that obviously lend itself to more complex comparisons in turn. I'm going to think about this some more. Mark. On Fri, Feb 27, 2015 at 3:23 PM, John Pickard via RT <bug-Test-DatabaseRow@rt.cpan.org> wrote: Show quoted text
> Queue: Test-DatabaseRow > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=102380 > > > Sorry, I now see in the documentation where it quite clearly states that > "Any expected value that looks like a number will be compared numerically". > However, the documentation also states that "The function will try and Do > The Right Thing" and I'd argue that using a string comparison when the > "got" value is a string is closer to the right thing :). > > Thanks again! > John > > > On Thu, Feb 26, 2015 at 12:43 PM, Bugs in Test-DatabaseRow via RT < > bug-Test-DatabaseRow@rt.cpan.org> wrote: >
>> >> Greetings, >> >> This message has been automatically generated in response to the >> creation of a trouble ticket regarding: >> "numeric comparisons against string database values", >> a summary of which appears below. >> >> There is no need to reply to this message right now. Your ticket has been >> assigned an ID of [rt.cpan.org #102380]. Your ticket is accessible >> on the web at: >> >> https://rt.cpan.org/Ticket/Display.html?id=102380 >> >> Please include the string: >> >> [rt.cpan.org #102380] >> >> in the subject line of all future correspondence about this issue. To do >> so, >> you may reply to this message. >> >> Thank you, >> bug-Test-DatabaseRow@rt.cpan.org >> >> ------------------------------------------------------------------------- >> Test-DatabaseRow-2.04 >> >> First, thanks! Thanks for reading this email, thanks for creating and >> maintaining Test::DatabaseRow. >> >> I've run into an issue with row_ok when tests is an arrayref. The >> comparison operation is evaluating to '==' when the expected looks like a >> number but the database value is a string. I think this is only an issue >> for '==' vs. 'eq' (not > vs. 'gt') because equality is assumed when tests >> is an arrayref. >> >> Of course this is easiest to explain with an example. For this example I >> have a test database as 'testing' and have run the following sql: >> >> create table testing.test_databaserow ( >> strcol varchar(20) default null >> ); >> >> insert into testing.test_databaserow (strcol) values ( '11,22' ); >> >> >> For the following perl code, I would expect the first two tests to fail, >> the third to pass. Using Test::DatabaseRow v2.04 the first test passes: >> >> #!/usr/bin/perl >> >> use strict; >> use warnings FATAL => 'all'; >> >> use Test::DatabaseRow; >> use Test::More tests => 3; >> >> my $dbh = <YOUR DATABASE HANDLE>; >> >> row_ok( >> sql => "select strcol from testing.test_databaserow", >> results => 1, >> tests => [ strcol => '11' ], >> dbh => $dbh, >> ); >> >> row_ok( >> sql => "select strcol from testing.test_databaserow", >> results => 1, >> tests => [ strcol => '11,' ], >> dbh => $dbh, >> ); >> >> row_ok( >> sql => "select strcol from testing.test_databaserow", >> results => 1, >> tests => [ strcol => '11,22' ], >> dbh => $dbh, >> ); >> >> >> This issue may be what is referred to as an "annoying case" in the comment >> on line 263 of Test::DatabaseRow::Object, however I think it is more than >> annoying since it erroneously allows tests to pass. I think the problem (if >> you agree it's a problem) stems from the override of the warning signal >> handler on line 399, this is a bit severe for avoiding undef comparisons. >> What if this was just a "no warnings 'uninitialized';"? I realize that that >> doesn't really solve the issue (just produces warnings). Ignoring that, >> here are my thoughts as "fixes": >> >> 1) Look at attached Object1.pm. Change $oper to "eq" if either $expect or >> $got =~ /\A $RE{num}{real} \z/x on ~line 396 (really only need to do check >> with $got, since we already looked at $expect when coercing tests): >> my $adj_oper = $oper eq '==' && $got !~ /\A $RE{num}{real} \z/x >> ? 'eq' >> : $oper; >> Then change other uses of $oper to $adj_oper, lines 401, 406, 407, and >> 413-415 >> This feels a little bit like a hack to me but it does solve the >> problem. >> >> 2) Look at attached Object2.pm. Use the sig warn to set the test to failed >> if a warning other than uninitialized is raised. I implemented this with a >> new local variable called $got_warnings which if set will set $passed to 0. >> Remove line 399 and add >> my $got_warning; >> no warnings 'uninitialized'; >> local $SIG{__WARN__} = sub { $got_warning = 1; }; # $^W not work >> >> Then add "$passed = 0 if $got_warning;" after the eval. Unfortunately, >> the diagnostics for this don't work because $oper is still '==' so _is_diag >> will print the got as a number and the got/expected look the same in the >> printout: >> not ok 1 - simple db test >> # Failed test 'simple db test' >> # at ../Tickets/Testing/Packages/Test_DatabaseRow.pl line 21. >> # While checking column 'strcol' on 1st row >> # got: 11 >> # expected: 11 >> >> I do not have a solution to this diag problem :(. Maybe pass a way to >> force printing as strings to_is_diag (ugh... not in Object2.pm)? >> >> >> Best, >> John >>
>
Subject: Re: [rt.cpan.org #102380] AutoReply: numeric comparisons against string database values
Date: Tue, 3 Mar 2015 09:47:26 -0500
To: bug-Test-DatabaseRow [...] rt.cpan.org
From: John Pickard <jep5m [...] virginia.edu>
Download (untitled) / with headers
text/plain 7.3k
Hi Mark, I also don't like changing the mode and I think your "_also_" check is great solution. Why must the interface change to explicitly turn on the numbers-compare-as-numbers-and-don't-equate-to-strings mode? Seems like this would be the expected behavior. Previously passing tests would fail, but they would fail correctly, right? Of course, this is from my naive and narrow-minded view point, I have no experience designing/maintaining modules used by thousands of people! - John On Sun, Mar 1, 2015 at 9:25 AM, mark@twoshortplanks.com via RT < bug-Test-DatabaseRow@rt.cpan.org> wrote: Show quoted text
> <URL: https://rt.cpan.org/Ticket/Display.html?id=102380 > > > Hi John, > > So I've been thinking about this a lot over the last few days. > > Here's the thing: I don't want the behaviour to change based on what > the database returned. I expect the "mode" we're in to be > deterministic just from the Perl side. Having the mode change based > on what the return data is seems to lead us down the > smart-match-is-too-clever problem. > > OTOH, I see your point. While 11 and 11.0 should probably match, 11 > and 11,12 should probably not. What we could do is add smarts to > _also_ check that the database return value looks like a number when > in numeric mode. > > This leads us onto another problem. We'd need to work out an API that > allowed explicitly turning on this mode as well. Which in turn leads > us onto the problem of reworking the API so we could have arbitrary > comparisons. This is a long standing issue that I wanted to look into > because Test::DatabaseRow currently assumes each column value is a > plain old scalar, but with databases like postgres they can be entire > arrayrefs or more complex data structures and that obviously lend > itself to more complex comparisons in turn. > > I'm going to think about this some more. > > Mark. > > > On Fri, Feb 27, 2015 at 3:23 PM, John Pickard via RT > <bug-Test-DatabaseRow@rt.cpan.org> wrote:
> > Queue: Test-DatabaseRow > > Ticket <URL: https://rt.cpan.org/Ticket/Display.html?id=102380 > > > > > Sorry, I now see in the documentation where it quite clearly states that > > "Any expected value that looks like a number will be compared
> numerically".
> > However, the documentation also states that "The function will try and Do > > The Right Thing" and I'd argue that using a string comparison when the > > "got" value is a string is closer to the right thing :). > > > > Thanks again! > > John > > > > > > On Thu, Feb 26, 2015 at 12:43 PM, Bugs in Test-DatabaseRow via RT < > > bug-Test-DatabaseRow@rt.cpan.org> wrote: > >
> >> > >> Greetings, > >> > >> This message has been automatically generated in response to the > >> creation of a trouble ticket regarding: > >> "numeric comparisons against string database values", > >> a summary of which appears below. > >> > >> There is no need to reply to this message right now. Your ticket has
> been
> >> assigned an ID of [rt.cpan.org #102380]. Your ticket is accessible > >> on the web at: > >> > >> https://rt.cpan.org/Ticket/Display.html?id=102380 > >> > >> Please include the string: > >> > >> [rt.cpan.org #102380] > >> > >> in the subject line of all future correspondence about this issue. To do > >> so, > >> you may reply to this message. > >> > >> Thank you, > >> bug-Test-DatabaseRow@rt.cpan.org > >> > >>
> -------------------------------------------------------------------------
> >> Test-DatabaseRow-2.04 > >> > >> First, thanks! Thanks for reading this email, thanks for creating and > >> maintaining Test::DatabaseRow. > >> > >> I've run into an issue with row_ok when tests is an arrayref. The > >> comparison operation is evaluating to '==' when the expected looks like
> a
> >> number but the database value is a string. I think this is only an issue > >> for '==' vs. 'eq' (not > vs. 'gt') because equality is assumed when
> tests
> >> is an arrayref. > >> > >> Of course this is easiest to explain with an example. For this example I > >> have a test database as 'testing' and have run the following sql: > >> > >> create table testing.test_databaserow ( > >> strcol varchar(20) default null > >> ); > >> > >> insert into testing.test_databaserow (strcol) values ( '11,22' ); > >> > >> > >> For the following perl code, I would expect the first two tests to fail, > >> the third to pass. Using Test::DatabaseRow v2.04 the first test passes: > >> > >> #!/usr/bin/perl > >> > >> use strict; > >> use warnings FATAL => 'all'; > >> > >> use Test::DatabaseRow; > >> use Test::More tests => 3; > >> > >> my $dbh = <YOUR DATABASE HANDLE>; > >> > >> row_ok( > >> sql => "select strcol from testing.test_databaserow", > >> results => 1, > >> tests => [ strcol => '11' ], > >> dbh => $dbh, > >> ); > >> > >> row_ok( > >> sql => "select strcol from testing.test_databaserow", > >> results => 1, > >> tests => [ strcol => '11,' ], > >> dbh => $dbh, > >> ); > >> > >> row_ok( > >> sql => "select strcol from testing.test_databaserow", > >> results => 1, > >> tests => [ strcol => '11,22' ], > >> dbh => $dbh, > >> ); > >> > >> > >> This issue may be what is referred to as an "annoying case" in the
> comment
> >> on line 263 of Test::DatabaseRow::Object, however I think it is more
> than
> >> annoying since it erroneously allows tests to pass. I think the problem
> (if
> >> you agree it's a problem) stems from the override of the warning signal > >> handler on line 399, this is a bit severe for avoiding undef
> comparisons.
> >> What if this was just a "no warnings 'uninitialized';"? I realize that
> that
> >> doesn't really solve the issue (just produces warnings). Ignoring that, > >> here are my thoughts as "fixes": > >> > >> 1) Look at attached Object1.pm. Change $oper to "eq" if either $expect
> or
> >> $got =~ /\A $RE{num}{real} \z/x on ~line 396 (really only need to do
> check
> >> with $got, since we already looked at $expect when coercing tests): > >> my $adj_oper = $oper eq '==' && $got !~ /\A $RE{num}{real} \z/x > >> ? 'eq' > >> : $oper; > >> Then change other uses of $oper to $adj_oper, lines 401, 406, 407,
> and
> >> 413-415 > >> This feels a little bit like a hack to me but it does solve the > >> problem. > >> > >> 2) Look at attached Object2.pm. Use the sig warn to set the test to
> failed
> >> if a warning other than uninitialized is raised. I implemented this
> with a
> >> new local variable called $got_warnings which if set will set $passed
> to 0.
> >> Remove line 399 and add > >> my $got_warning; > >> no warnings 'uninitialized'; > >> local $SIG{__WARN__} = sub { $got_warning = 1; }; # $^W not work > >> > >> Then add "$passed = 0 if $got_warning;" after the eval.
> Unfortunately,
> >> the diagnostics for this don't work because $oper is still '==' so
> _is_diag
> >> will print the got as a number and the got/expected look the same in the > >> printout: > >> not ok 1 - simple db test > >> # Failed test 'simple db test' > >> # at ../Tickets/Testing/Packages/Test_DatabaseRow.pl line 21. > >> # While checking column 'strcol' on 1st row > >> # got: 11 > >> # expected: 11 > >> > >> I do not have a solution to this diag problem :(. Maybe pass a way
> to
> >> force printing as strings to_is_diag (ugh... not in Object2.pm)? > >> > >> > >> Best, > >> John > >>
> >
> >


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

Please report any issues with rt.cpan.org to rt-cpan-admin@bestpractical.com.