[SearchBuilder-devel] [PATCH] t/01searches.t
Ruslan U. Zakirov
Ruslan.Zakirov at miet.ru
Thu May 26 07:12:37 EDT 2005
Hello.
Three patches attached:
1) init_data: new function in t/utils.pl
2) search_builder_pm: small changes, description is in patch
3) searches_tests: tests for SearchBuilder.pm
All this covers basic searches.
You can skip search_builder_pm.patch and see what tests fails and how
I've fixed it.
PS: We had power crisis in the Moscow, that's why I wasn't available.
--
Best regards, Ruslan.
-------------- next part --------------
----------------------------------------------------------------------
r1680: cubic | 2005-05-25 23:08:25 +0000
new function init_data in test framework
----------------------------------------------------------------------
=== DBIx-SearchBuilder/local/t/utils.pl
==================================================================
--- DBIx-SearchBuilder/local/t/utils.pl (revision 1679)
+++ DBIx-SearchBuilder/local/t/utils.pl (revision 1680)
@@ -177,7 +177,7 @@
=head2 cleanup_schema
-Takes C<$class> and C<$handle> and inits schema by calling
+Takes C<$class> and C<$handle> and cleanup schema by calling
C<cleanup_schema_$driver> method of the C<$class> if method exists.
Always returns undef.
@@ -195,4 +195,27 @@
}
}
+=head2 init_data
+
+=cut
+
+sub init_data
+{
+ my ($class, $handle) = @_;
+ my @data = $class->init_data();
+ my @columns = @{ shift @data };
+ my $count = 0;
+ foreach my $values ( @data ) {
+ my %args;
+ for( my $i = 0; $i < @columns; $i++ ) {
+ $args{ $columns[$i] } = $values->[$i];
+ }
+ my $rec = $class->new( $handle );
+ my $id = $rec->Create( %args );
+ die "Couldn't create record" unless $id;
+ $count++;
+ }
+ return $count;
+}
+
1;
-------------- next part --------------
----------------------------------------------------------------------
r1679: cubic | 2005-05-25 23:06:40 +0000
SearchBuilder.pm fixes&cleanups:
CleanSlate doesnt init show_rows
CleanSlate doesnt clean _{open|close}_parens
get rid of stupid ifs in CleanSlate
get rid of evals in _DoSearch and _DoCount, use Handle methods to control DBI error handling
----------------------------------------------------------------------
=== DBIx-SearchBuilder/local/SearchBuilder.pm
==================================================================
--- DBIx-SearchBuilder/local/SearchBuilder.pm (revision 1678)
+++ DBIx-SearchBuilder/local/SearchBuilder.pm (revision 1679)
@@ -109,7 +109,7 @@
my $self = shift;
my %args = ( Handle => undef,
@_ );
- $self->{'DBIxHandle'} = $args{'Handle'};
+ $self->_Handle( $args{'Handle'} );
$self->CleanSlate();
}
@@ -139,14 +139,19 @@
$self->{'alias_count'} = 0;
$self->{'first_row'} = 0;
$self->{'must_redo_search'} = 1;
+ $self->{'show_rows'} = 0;
@{ $self->{'aliases'} } = ();
- delete $self->{'items'} if ( defined $self->{'items'} );
- delete $self->{'left_joins'} if ( defined $self->{'left_joins'} );
- delete $self->{'raw_rows'} if ( defined $self->{'raw_rows'} );
- delete $self->{'count_all'} if ( defined $self->{'count_all'} );
- delete $self->{'subclauses'} if ( defined $self->{'subclauses'} );
- delete $self->{'restrictions'} if ( defined $self->{'restrictions'} );
+ delete $self->{$_} for qw(
+ items
+ left_joins
+ raw_rows
+ count_all
+ subclauses
+ restrictions
+ _open_parens
+ _close_parens
+ );
#we have no limit statements. DoSearch won't work.
$self->_isLimited(0);
@@ -191,18 +196,17 @@
# If we're about to redo the search, we need an empty set of items
delete $self->{'items'};
- eval {
- # TODO: finer-grained eval and checking.
- my $records = $self->_Handle->SimpleQuery($QueryString);
+ my $records = $self->_Handle->SimpleQuery($QueryString);
+ return 0 unless $records;
- while ( my $row = $records->fetchrow_hashref() ) {
- my $item = $self->NewItem();
- $item->LoadFromHash($row);
- $self->AddRecord($item);
- }
+ while ( my $row = $records->fetchrow_hashref() ) {
+ my $item = $self->NewItem();
+ $item->LoadFromHash($row);
+ $self->AddRecord($item);
+ }
+ return $self->_RecordCount if $records->err;
- $self->{'must_redo_search'} = 0;
- };
+ $self->{'must_redo_search'} = 0;
return $self->_RecordCount;
}
@@ -250,15 +254,15 @@
my $all = shift || 0;
my $QueryString = $self->BuildSelectCountQuery();
- eval {
- # TODO: finer-grained Eval
- my $records = $self->_Handle->SimpleQuery($QueryString);
+ my $records = $self->_Handle->SimpleQuery($QueryString);
+ return 0 unless $records;
- my @row = $records->fetchrow_array();
- $self->{ $all ? 'count_all' : 'raw_rows' } = $row[0];
+ my @row = $records->fetchrow_array();
+ return 0 if $records->err;
- return ( $row[0] );
- };
+ $self->{ $all ? 'count_all' : 'raw_rows' } = $row[0];
+
+ return ( $row[0] );
}
# }}}
@@ -485,7 +489,7 @@
return (undef) unless ( $self->_isLimited );
- $self->_DoSearch() if ( $self->{'must_redo_search'} != 0 );
+ $self->_DoSearch() if $self->{'must_redo_search'};
if ( $self->{'itemscount'} < $self->_RecordCount ) { #return the next item
my $item = ( $self->{'items'}[ $self->{'itemscount'} ] );
@@ -1121,9 +1125,7 @@
sub _OrderClause {
my $self = shift;
- unless ( defined $self->{'order_clause'} ) {
- return "";
- }
+ return '' unless $self->{'order_clause'};
return ($self->{'order_clause'});
}
@@ -1141,7 +1143,7 @@
=cut
-sub GroupBy { (shift)->GroupByCols( @_) }
+sub GroupBy { (shift)->GroupByCols( @_ ) }
# }}}
@@ -1199,9 +1201,7 @@
sub _GroupClause {
my $self = shift;
- unless ( defined $self->{'group_clause'} ) {
- return "";
- }
+ return '' unless $self->{'group_clause'};
return ($self->{'group_clause'});
}
@@ -1520,11 +1520,13 @@
sub IsLast {
my $self = shift;
+ return undef unless $self->Count;
+
if ( $self->_ItemsCounter == $self->Count ) {
return (1);
}
else {
- return (undef);
+ return (0);
}
}
-------------- next part --------------
----------------------------------------------------------------------
r1681: cubic | 2005-05-25 23:09:37 +0000
basic tests for SearchBuilder.pm
----------------------------------------------------------------------
=== DBIx-SearchBuilder/local/t/01searches.t
==================================================================
--- DBIx-SearchBuilder/local/t/01searches.t (revision 1680)
+++ DBIx-SearchBuilder/local/t/01searches.t (revision 1681)
@@ -0,0 +1,248 @@
+#!/usr/bin/perl -w
+
+
+use strict;
+use warnings;
+use File::Spec;
+use Test::More;
+BEGIN { require "t/utils.pl" }
+our (@AvailableDrivers);
+
+use constant TESTS_PER_DRIVER => 55;
+
+my $total = scalar(@AvailableDrivers) * TESTS_PER_DRIVER;
+plan tests => $total;
+
+foreach my $d ( @AvailableDrivers ) {
+SKIP: {
+ unless( has_schema( 'TestApp', $d ) ) {
+ skip "No schema for '$d' driver", TESTS_PER_DRIVER;
+ }
+ unless( should_test( $d ) ) {
+ skip "ENV is not defined for driver '$d'", TESTS_PER_DRIVER;
+ }
+
+ my $handle = get_handle( $d );
+ connect_handle( $handle );
+ isa_ok($handle->dbh, 'DBI::db');
+
+ my $ret = init_schema( 'TestApp', $handle );
+ isa_ok($ret,'DBI::st', "Inserted the schema. got a statement handle back");
+
+ my $count_all = init_data( 'TestApp::User', $handle );
+ ok( $count_all, "init users data" );
+
+ my $users_obj = TestApp::Users->new( $handle );
+ isa_ok( $users_obj, 'DBIx::SearchBuilder' );
+ is( $users_obj->_Handle, $handle, "same handle as we used in constructor");
+
+# check that new object returns 0 records in any case
+ is( $users_obj->_RecordCount, 0, '_RecordCount returns 0 on not limited obj' );
+ is( $users_obj->Count, 0, 'Count returns 0 on not limited obj' );
+ is( $users_obj->IsLast, undef, 'IsLast returns undef on not limited obj after Count' );
+ is( $users_obj->First, undef, 'First returns undef on not limited obj' );
+ is( $users_obj->IsLast, undef, 'IsLast returns undef on not limited obj after First' );
+ is( $users_obj->Last, undef, 'Last returns undef on not limited obj' );
+ is( $users_obj->IsLast, undef, 'IsLast returns undef on not limited obj after Last' );
+ $users_obj->GotoFirstItem;
+ is( $users_obj->Next, undef, 'Next returns undef on not limited obj' );
+ is( $users_obj->IsLast, undef, 'IsLast returns undef on not limited obj after Next' );
+ # XXX TODO FIXME: may be this methods should be implemented
+ # $users_obj->GotoLastItem;
+ # is( $users_obj->Prev, undef, 'Prev returns undef on not limited obj' );
+ my $items_ref = $users_obj->ItemsArrayRef;
+ isa_ok( $items_ref, 'ARRAY', 'ItemsArrayRef always returns array reference' );
+ is_deeply( $items_ref, [], 'ItemsArrayRef returns [] on not limited obj' );
+
+# unlimit new object and check
+ $users_obj->UnLimit;
+ is( $users_obj->Count, $count_all, 'Count returns same number of records as was inserted' );
+ isa_ok( $users_obj->First, 'DBIx::SearchBuilder::Record', 'First returns record object' );
+ isa_ok( $users_obj->Last, 'DBIx::SearchBuilder::Record', 'Last returns record object' );
+ $users_obj->GotoFirstItem;
+ isa_ok( $users_obj->Next, 'DBIx::SearchBuilder::Record', 'Next returns record object' );
+ $items_ref = $users_obj->ItemsArrayRef;
+ isa_ok( $items_ref, 'ARRAY', 'ItemsArrayRef always returns array reference' );
+ is( scalar @{$items_ref}, $count_all, 'ItemsArrayRef returns same number of records as was inserted' );
+ $users_obj->RedoSearch;
+ $items_ref = $users_obj->ItemsArrayRef;
+ isa_ok( $items_ref, 'ARRAY', 'ItemsArrayRef always returns array reference' );
+ is( scalar @{$items_ref}, $count_all, 'ItemsArrayRef returns same number of records as was inserted' );
+
+# try to use $users_obj for all tests, after each call to CleanSlate it should look like new obj.
+# and test $obj->new syntax
+ my $clean_obj = $users_obj->new( $handle );
+ isa_ok( $clean_obj, 'DBIx::SearchBuilder' );
+
+# basic limits
+ $users_obj->CleanSlate;
+ is_deeply( $users_obj, $clean_obj, 'after CleanSlate looks like new object');
+ $users_obj->Limit( FIELD => 'Login', VALUE => 'obra' );
+ is( $users_obj->Count, 1, 'found one user with login obra' );
+ TODO: {
+ local $TODO = 'require discussion';
+ is( $users_obj->IsLast, undef, 'IsLast returns undef before we fetch any record' );
+ }
+ my $first_rec = $users_obj->First;
+ isa_ok( $first_rec, 'DBIx::SearchBuilder::Record', 'First returns record object' );
+ is( $users_obj->IsLast, 1, '1 record in the collection then first rec is last');
+ is( $first_rec->Login, 'obra', 'login is correct' );
+ my $last_rec = $users_obj->Last;
+ is( $last_rec, $first_rec, 'Last returns same object as First' );
+ is( $users_obj->IsLast, 1, 'IsLast always returns 1 after Last call');
+ $users_obj->GotoFirstItem;
+ my $next_rec = $users_obj->Next;
+ is( $next_rec, $first_rec, 'Next returns same object as First' );
+ is( $users_obj->IsLast, 1, 'IsLast returns 1 after fetch first record with Next method');
+ is( $users_obj->Next, undef, 'only one record in the collection' );
+ TODO: {
+ local $TODO = 'require discussion';
+ is( $users_obj->IsLast, undef, 'Next returns undef, IsLast returns undef too');
+ }
+ $items_ref = $users_obj->ItemsArrayRef;
+ isa_ok( $items_ref, 'ARRAY', 'ItemsArrayRef always returns array reference' );
+ is( scalar @{$items_ref}, 1, 'ItemsArrayRef has only 1 record' );
+
+# similar basic limit, but with different OPERATORS and less Firs/Next/Last tests
+ # LIKE
+ $users_obj->CleanSlate;
+ is_deeply( $users_obj, $clean_obj, 'after CleanSlate looks like new object');
+ $users_obj->Limit( FIELD => 'Name', OPERATOR => 'LIKE', VALUE => 'Glass' );
+ is( $users_obj->Count, 1, "found one user with 'Glass' in the name" );
+ $first_rec = $users_obj->First;
+ isa_ok( $first_rec, 'DBIx::SearchBuilder::Record', 'First returns record object' );
+ is( $first_rec->Login, 'glasser', 'login is correct' );
+
+ # STARTSWITH
+ $users_obj->CleanSlate;
+ is_deeply( $users_obj, $clean_obj, 'after CleanSlate looks like new object');
+ $users_obj->Limit( FIELD => 'Name', OPERATOR => 'STARTSWITH', VALUE => 'Ruslan' );
+ is( $users_obj->Count, 1, "found one user who name starts with 'Ruslan'" );
+ $first_rec = $users_obj->First;
+ isa_ok( $first_rec, 'DBIx::SearchBuilder::Record', 'First returns record object' );
+ is( $first_rec->Login, 'cubic', 'login is correct' );
+
+ # ENDSWITH
+ $users_obj->CleanSlate;
+ is_deeply( $users_obj, $clean_obj, 'after CleanSlate looks like new object');
+ $users_obj->Limit( FIELD => 'Name', OPERATOR => 'ENDSWITH', VALUE => 'Tang' );
+ is( $users_obj->Count, 1, "found one user who name ends with 'Tang'" );
+ $first_rec = $users_obj->First;
+ isa_ok( $first_rec, 'DBIx::SearchBuilder::Record', 'First returns record object' );
+ is( $first_rec->Login, 'autrijus', 'login is correct' );
+
+ # IS NULL
+ # XXX TODO FIXME: FIELD => undef should be handled as NULL
+ $users_obj->CleanSlate;
+ is_deeply( $users_obj, $clean_obj, 'after CleanSlate looks like new object');
+ $users_obj->Limit( FIELD => 'Phone', OPERATOR => 'IS', VALUE => 'NULL' );
+ is( $users_obj->Count, 2, "found 2 users who has unknown phone number" );
+
+ # IS NOT NULL
+ $users_obj->CleanSlate;
+ is_deeply( $users_obj, $clean_obj, 'after CleanSlate looks like new object');
+ $users_obj->Limit( FIELD => 'Phone', OPERATOR => 'IS NOT', VALUE => 'NULL', QOUTEVALUE => 0 );
+ is( $users_obj->Count, $count_all - 2, "found users who has phone number filled" );
+
+
+ cleanup_schema( 'TestApp', $handle );
+}} # SKIP, foreach blocks
+
+1;
+
+package TestApp;
+
+sub schema_mysql {
+<<EOF;
+CREATE TEMPORARY TABLE Users (
+ id integer AUTO_INCREMENT,
+ Login varchar(18) NOT NULL,
+ Name varchar(36),
+ Phone varchar(18),
+ PRIMARY KEY (id))
+EOF
+
+}
+
+sub schema_pg {
+<<EOF;
+CREATE TEMPORARY TABLE Users (
+ id serial PRIMARY KEY,
+ Login varchar(18) NOT NULL,
+ Name varchar(36),
+ Phone varchar(18)
+)
+EOF
+
+}
+
+sub schema_sqlite {
+
+<<EOF;
+CREATE TABLE Users (
+ id integer primary key,
+ Login varchar(18) NOT NULL,
+ Name varchar(36),
+ Phone varchar(18))
+EOF
+
+}
+
+
+1;
+
+package TestApp::User;
+
+use base qw/DBIx::SearchBuilder::Record/;
+
+sub _Init {
+ my $self = shift;
+ my $handle = shift;
+ $self->Table('Users');
+ $self->_Handle($handle);
+}
+
+sub _ClassAccessible {
+ {
+ id =>
+ {read => 1, type => 'int(11)' },
+ Login =>
+ {read => 1, write => 1, type => 'varchar(18)' },
+ Name =>
+ {read => 1, write => 1, type => 'varchar(36)' },
+ Phone =>
+ {read => 1, write => 1, type => 'varchar(18)', default => ''},
+ }
+}
+
+sub init_data {
+ return (
+ [ 'Login', 'Name', 'Phone' ],
+ [ 'cubic', 'Ruslan U. Zakirov', '+7-903-264-XX-XX' ],
+ [ 'obra', 'Jesse Vincent', undef ],
+ [ 'glasser', 'David Glasser', undef ],
+ [ 'autrijus', 'Autrijus Tang', '+X-XXX-XXX-XX-XX' ],
+ );
+}
+
+1;
+
+package TestApp::Users;
+
+# use TestApp::User;
+use base qw/DBIx::SearchBuilder/;
+
+sub _Init {
+ my $self = shift;
+ $self->SUPER::_Init( Handle => shift );
+ $self->Table('Users');
+}
+
+sub NewItem
+{
+ my $self = shift;
+ return TestApp::User->new( $self->_Handle );
+}
+
+1;
+
More information about the SearchBuilder-devel
mailing list