1 package t
::lib
::TestBuilder
;
10 smallint
=> \
&_gen_int
,
11 mediumint
=> \
&_gen_int
,
12 integer
=> \
&_gen_int
,
16 decimal
=> \
&_gen_real
,
17 double_precision
=> \
&_gen_real
,
19 timestamp
=> \
&_gen_date
,
20 datetime
=> \
&_gen_date
,
24 varchar
=> \
&_gen_text
,
25 tinytext
=> \
&_gen_text
,
27 mediumtext
=> \
&_gen_text
,
28 longtext
=> \
&_gen_text
,
30 set
=> \
&_gen_set_enum
,
31 enum
=> \
&_gen_set_enum
,
33 tinyblob
=> \
&_gen_blob
,
34 mediumblob
=> \
&_gen_blob
,
36 longblob
=> \
&_gen_blob
,
39 our $default_value = {
42 surname
=> 'my surname',
43 address
=> 'my adress',
47 branchname
=> 'my branchname',
53 default_privacy
=> 'default',
66 $default_value->{UserPermission
}->{code
} = $default_value->{UserPermission
}->{module_bit
};
72 bless( $self, $class );
74 $self->schema( Koha
::Database
->new()->schema );
75 $self->schema->txn_begin();
76 $self->schema->storage->sql_maker->quote_char('`');
81 my ($self, $schema) = @_;
83 if( defined( $schema ) ) {
84 $self->{schema
} = $schema;
86 return $self->{schema
};
90 my ($self, $params) = @_;
91 my $source = $self->schema->resultset( $params->{source
} );
92 return $source->delete_all();
96 my ($self, $params) = @_;
97 my $source = $params->{source
} || return;
98 my $value = $params->{value
};
99 my $only_fk = $params->{only_fk
} || 0;
101 my $col_values = $self->_buildColumnValues({
107 my $foreign_keys = $self->_getForeignKeys( { source
=> $source } );
108 for my $fk ( @
$foreign_keys ) {
110 my $col_name = $fk->{keys}->[0]->{col_name
};
111 if( ref( $col_values->{$col_name} ) eq 'HASH' ) {
112 $fk_value = $col_values->{$col_name};
114 elsif( defined( $col_values->{$col_name} ) ) {
118 my $fk_row = $self->build({
119 source
=> $fk->{source
},
123 my $keys = $fk->{keys};
124 for my $key( @
$keys ) {
125 $col_values->{ $key->{col_name
} } = $fk_row->{ $key->{col_fk_name
} };
126 $data->{ $key->{col_name
} } = $fk_row;
132 $new_row = $col_values;
135 $new_row = $self->_storeColumnValues({
137 values => $col_values,
140 $new_row->{_fk
} = $data if( defined( $data ) );
146 my $source = $params->{source
};
147 $source =~ s
|(\w
+)$|$1|;
151 sub _buildColumnValues
{
152 my ($self, $params) = @_;
153 my $source = _formatSource
( { source
=> $params->{source
} } );
154 my $original_value = $params->{value
};
157 my @columns = $self->schema->source($source)->columns;
158 my %unique_constraints = $self->schema->source($source)->unique_constraints();
161 BUILD_VALUE
: while ( $build_value ) {
162 # generate random values for all columns
163 for my $col_name( @columns ) {
164 my $col_value = $self->_buildColumnValue({
166 column_name
=> $col_name,
167 value
=> $original_value,
169 $col_values->{$col_name} = $col_value if( defined( $col_value ) );
173 # If default values are set, maybe the data exist in the DB
174 # But no need to wait for another value
175 # FIXME this can be wrong if a default value is defined for a field
176 # which is not a constraint and that the generated value for the
177 # constraint already exists.
178 last BUILD_VALUE
if exists( $default_value->{$source} );
180 # If there is no original value given and unique constraints exist,
181 # check if the generated values do not exist yet.
182 if ( not defined $original_value and scalar keys %unique_constraints > 0 ) {
184 # verify the data would respect each unique constraint
185 CONSTRAINTS
: foreach my $constraint (keys %unique_constraints) {
188 my $constraint_columns = $unique_constraints{$constraint};
189 # loop through all constraint columns and build the condition
190 foreach my $constraint_column ( @
$constraint_columns ) {
192 $condition->{ $constraint_column } =
193 $col_values->{ $constraint_column };
196 my $count = $self->schema
197 ->resultset( $source )
198 ->search( $condition )
201 # no point checking more stuff, exit the loop
212 # rel_name => $rel_name,
213 # source => $table_name,
215 # col_name => $col_name,
216 # col_fk_name => $col_fk_name,
219 sub _getForeignKeys
{
220 my ($self, $params) = @_;
221 my $source = $self->schema->source( $params->{source
} );
223 my @foreign_keys = ();
224 my @relationships = $source->relationships;
225 for my $rel_name( @relationships ) {
226 my $rel_info = $source->relationship_info($rel_name);
227 if( $rel_info->{attrs
}->{is_foreign_key_constraint
} ) {
229 rel_name
=> $rel_name,
230 source
=> $rel_info->{source
},
234 while( my ($col_fk_name, $col_name) = each(%{$rel_info->{cond
}}) ) {
235 $col_name =~ s
|self
.(\w
+)|$1|;
236 $col_fk_name =~ s
|foreign
.(\w
+)|$1|;
238 col_name
=> $col_name,
239 col_fk_name
=> $col_fk_name,
242 $rel->{keys} = \
@keys;
244 push @foreign_keys, $rel;
247 return \
@foreign_keys;
250 sub _storeColumnValues
{
251 my ($self, $params) = @_;
252 my $source = $params->{source
};
253 my $col_values = $params->{values};
257 $new_row = $self->schema->resultset($source)->update_or_create($col_values);
259 die "$source - $@\n" if ($@
);
262 $new_row = { $new_row->get_columns };
264 warn "$source - $@\n" if ($@
);
268 sub _buildColumnValue
{
269 my ($self, $params) = @_;
270 my $source = $params->{source
};
271 my $value = $params->{value
};
272 my $col_name = $params->{column_name
};
273 my $col_info = $self->schema->source($source)->column_info($col_name);
276 if( exists( $value->{$col_name} ) ) {
277 $col_value = $value->{$col_name};
279 elsif( exists $default_value->{$source} and exists $default_value->{$source}->{$col_name} ) {
280 $col_value = $default_value->{$source}->{$col_name};
282 elsif( not $col_info->{default_value
} and not $col_info->{is_auto_increment
} and not $col_info->{is_foreign_key
} ) {
284 my $data_type = $col_info->{data_type
};
285 $data_type =~ s
| |_
|;
286 $col_value = $gen_type->{$data_type}->( $self, { info
=> $col_info } );
288 die "The type $col_info->{data_type} is not defined\n" if ($@
);
295 my ($self, $params) = @_;
296 my $data_type = $params->{info
}->{data_type
};
299 if( $data_type eq 'tinyint' ) {
302 elsif( $data_type eq 'smallint' ) {
305 elsif( $data_type eq 'mediumint' ) {
308 elsif( $data_type eq 'integer' ) {
311 elsif( $data_type eq 'bigint' ) {
312 $max = 9223372036854775807;
314 return int( rand($max+1) );
318 my ($self, $params) = @_;
320 if( defined( $params->{info
}->{size
} ) ) {
321 $max = 10 ** ($params->{info
}->{size
}->[0] - $params->{info
}->{size
}->[1]);
323 return rand($max) + 1;
327 my ($self, $params) = @_;
328 return $self->schema->storage->datetime_parser->format_datetime(DateTime
->now());
332 my ($self, $params) = @_;
333 # From perldoc String::Random
334 # max: specify the maximum number of characters to return for * and other
335 # regular expression patters that don't return a fixed number of characters
336 my $regex = '[A-Za-z][A-Za-z0-9_]*';
337 my $size = $params->{info
}{size
};
338 if ( defined $size and $size > 1 ) {
340 } elsif ( defined $size and $size == 1 ) {
343 my $random = String
::Random
->new( max
=> $size );
344 return $random->randregex($regex);
348 my ($self, $params) = @_;
349 return $params->{info
}->{extra
}->{list
}->[0];
353 my ($self, $params) = @_;;
360 $self->schema->txn_rollback();
366 t::lib::TestBuilder.pm - Koha module to simplify the writing of tests
370 use t::lib::TestBuilder;
372 Koha module to insert the foreign keys automatically for the tests
376 This module allows to insert automatically an entry in the database. All the database changes are wrapped in a transaction.
377 The foreign keys are created according to the DBIx::Class schema.
378 The taken values are the values by default if it is possible or randomly generated.
384 $builder = t::lib::TestBuilder->new()
386 Constructor - Begins a transaction and returns the object TestBuilder
390 $schema = $builder->schema
392 Getter - Returns the schema of DBIx::Class
396 $builder->clear({ source => $source_name })
400 =item C<$source_name> is the name of the source in the DBIx::Class schema (required)
404 Clears all the data of this source (database table)
409 source => $source_name,
416 =item C<$source_name> is the name of the source in the DBIx::Class schema (required)
418 =item C<$value> is the values for the entry (optional)
420 =item C<$only_fk> is a boolean to indicate if only the foreign keys are created (optional)
424 Inserts an entry in the database by instanciating all the foreign keys.
425 The values can be specified, the values which are not given are default values if they exists or generated randomly.
426 Returns the values of the entry as a hashref with an extra key : _fk which contains all the values of the generated foreign keys.
430 Yohann Dufour <yohann.dufour@biblibre.com>
434 Copyright 2014 - Biblibre SARL
438 This file is part of Koha.
440 Koha is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by
441 the Free Software Foundation; either version 3 of the License, or (at your option) any later version.
443 Koha is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
445 You should have received a copy of the GNU General Public License along with Koha; if not, see <http://www.gnu.org/licenses>.