use strict; use warnings; package FixMyStreet::TestAppProve; use App::Prove; use sigtrap qw(handler signal_handler normal-signals); use YAML (); use Path::Tiny 'path'; use Test::PostgreSQL; use Data::Dumper; use Getopt::Long ':config' => qw(bundling pass_through no_ignore_case); =head1 NAME FixMyStreet::TestAppProve - spin up a clean database and configuration for tests =head1 USAGE see bin/run-tests for usage =cut sub cleanup { unlink "conf/general-test-autogenerated.$$.yml"; } sub signal_handler { cleanup(); exit(0); } END { cleanup(); } my $pg; sub spin_up_database { warn "Spinning up a Pg cluster/database...\n"; $pg = Test::PostgreSQL->new( run_psql_args => '-1Xq -v ON_ERROR_STOP=1', # No -b on 9.1 ); # On 9.1, must run each file separately $pg->run_psql_scripts('db/schema.sql'); $pg->run_psql_scripts('db/fixture.sql'); $pg->run_psql_scripts('db/generate_secret.sql'); warn sprintf "# Connected to %s\n", $pg->dsn; return { FMS_DB_PORT => $pg->port, FMS_DB_NAME => 'test', FMS_DB_USER => 'postgres', FMS_DB_HOST => 'localhost', FMS_DB_PASS => '', }; } sub get_config { my $cls = shift; my $extra_config = shift; my $config_file = delete $extra_config->{config_file}; my $db_config_file = delete $extra_config->{db_config_file}; my $config = YAML::Load( path($config_file)->slurp ); if ($db_config_file) { my $db_config = YAML::Load( path($db_config_file)->slurp ); $config->{FMS_DB_PORT} = $db_config->{FMS_DB_PORT}; $config->{FMS_DB_NAME} = $db_config->{FMS_DB_NAME}; $config->{FMS_DB_USER} = $db_config->{FMS_DB_USER}; $config->{FMS_DB_HOST} = $db_config->{FMS_DB_HOST}; $config->{FMS_DB_PASS} = $db_config->{FMS_DB_PASS}; } else { my $new_db_config = $cls->spin_up_database(); $config = { %$config, %$new_db_config }; } $config = { %$config, %$extra_config }; my $config_out = "general-test-autogenerated.$$.yml"; path("conf/$config_out")->spew( YAML::Dump($config) ); return $config_out; } sub run { my ($class, @args) = @_; local @ARGV = @args; my $config_file = 'conf/general.yml-example'; my $db_config_file; my $recurse; my @state; GetOptions ( # our own config variables 'config=s' => \$config_file, 'db-config=s' => \$db_config_file, # App::Prove variables we want to munge 'r|recurse' => \$recurse, 'state=s@' => \@state, ); my $config_out = $class->get_config({ config_file => $config_file, db_config_file => $db_config_file }); local $ENV{FMS_OVERRIDE_CONFIG} = $config_out; # Don't warn over use of Regex dispatch type local $ENV{CATALYST_NOWARN_DEPRECATE} = 1; my $prove = App::Prove->new; $prove->process_args(@ARGV); # If no arguments, test everything $prove->argv(['t']) unless @{$prove->argv} || @state; # verbose if we have a single file $prove->verbose(1) if @{$prove->argv} and -f $prove->argv->[-1] && !$ENV{CI}; # we always want to recurse $prove->recurse(1); # we always want to save state $prove->state([ @state, 'save' ]); $prove->run; } 1;