I am having some problems with tests failing, and it seems to be related
to
the foreign key constraints I have in the database.
Listing A shows what appears in development.log, when I run “rake
test”,
before any output appears in test.log (which I find strange because I
would
have thought that all output would go to test.log when running in test
mode).
Lising B shows the corresponding output of the “rake test --trace”
command.
IIf I remove the foreign key constraints from the database, the test
runs
fine, and Listing C appears in the development log instead. The
corresponding “rake test --trace” output is shown in Listing D.
So it seems that as part of the testing process, rails is attempting
to drop
and recreate all of the tables in the database, but it is doing it in
the
wrong order so that the foreign key constraints get in they way. In
fact the
ordering is based on the order that the tables are created in schema.rb
(LISTING E) (which is different to the order that I programmatically
create
the tables in the migration file (LISTING F)). So has anyone else had
this
problem? Is the solution a matter of controlling which order schema.rb
creates the table? Or is there something more fundamental wrong with my
setup?
Thanks.
============= LISTING A ========================
SQL (0.000450) SELECT * FROM schema_info
SQL (0.000502) SHOW TABLES
SQL (0.001142) SHOW FIELDS FROM functional_rights
SQL (0.001021) SHOW KEYS FROM functional_rights
SQL (0.001017) SHOW FIELDS FROM functional_rights_functional_roles
SQL (0.000922) SHOW KEYS FROM functional_rights_functional_roles
SQL (0.001036) SHOW FIELDS FROM functional_roles
SQL (0.000856) SHOW KEYS FROM functional_roles
SQL (0.000990) SHOW FIELDS FROM functional_roles_users
SQL (0.000903) SHOW KEYS FROM functional_roles_users
SQL (0.001211) SHOW FIELDS FROM users
SQL (0.001118) SHOW KEYS FROM users
SQL (0.000000) Mysql::Error: Cannot delete or update a parent row: a
foreign key constraint fails: DROP TABLE functional_rights
SQL (0.000000) Mysql::Error: Table ‘functional_rights’ already
exists:
CREATE TABLEfunctional_rights (id
int(11) DEFAULT NULL auto_increment
PRIMARY KEY, name
varchar(255) DEFAULT ‘’ NOT NULL, controller
varchar(255) DEFAULT ‘’ NOT NULL, action
varchar(255) DEFAULT ‘’ NOT
NULL)
ENGINE=InnoDB
============= LISTING B ========================
(in /home/michael/code/rails/work/railsproject)
** Invoke test (first_time)
** Execute test
** Invoke test:units (first_time)
** Invoke db:test:prepare (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute db:test:prepare
** Invoke db:test:clone (first_time)
** Invoke db:schema:dump (first_time)
** Invoke environment
** Execute db:schema:dump
** Execute db:test:clone
** Invoke db:schema:load (first_time)
** Invoke environment
** Execute db:schema:load
** Invoke test:functionals (first_time)
** Invoke db:test:prepare
** Execute test:functionals
/usr/bin/ruby18 -Ilib:test
“/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake/rake_test_loader.rb”
“test/functional/functional_role_controller_test.rb”
“test/functional/user_controller_test.rb”
“test/functional/functional_right_controller_test.rb”
“test/functional/session_controller_test.rb”
Loaded suite
/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake/rake_test_loader
Started
…
Finished in 0.181921 seconds.
14 tests, 80 assertions, 0 failures, 0 errors
** Invoke test:integration (first_time)
** Invoke db:test:prepare
** Execute test:integration
/usr/bin/ruby18 -Ilib:test
“/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake/rake_test_loader.rb”
rake aborted!
Test failures
/usr/lib/ruby/gems/1.8/gems/rails-1.1.6/lib/tasks/testing.rake:35
/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake.rb:387:in execute' /usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake.rb:387:in
execute’
/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake.rb:357:in invoke' /usr/lib/ruby/1.8/thread.rb:135:in
synchronize’
/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake.rb:350:in invoke' /usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake.rb:1906:in
run’
/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake.rb:1906:in `run’
/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/bin/rake:7
/usr/bin/rake:18
============= LISTING C ========================
SQL (0.000450) SELECT * FROM schema_info
SQL (0.000485) SHOW TABLES
SQL (0.001146) SHOW FIELDS FROM functional_rights
SQL (0.001023) SHOW KEYS FROM functional_rights
SQL (0.001011) SHOW FIELDS FROM functional_rights_functional_roles
SQL (0.000823) SHOW KEYS FROM functional_rights_functional_roles
SQL (0.001001) SHOW FIELDS FROM functional_roles
SQL (0.000853) SHOW KEYS FROM functional_roles
SQL (0.000991) SHOW FIELDS FROM functional_roles_users
SQL (0.000838) SHOW KEYS FROM functional_roles_users
SQL (0.001170) SHOW FIELDS FROM users
SQL (0.001298) SHOW KEYS FROM users
SQL (0.001402) DROP TABLE functional_rights
SQL (0.006160) CREATE TABLE functional_rights (id
int(11) DEFAULT
NULL
auto_increment PRIMARY KEY, name
varchar(255) DEFAULT ‘’ NOT NULL,
controller
varchar(255) DEFAULT ‘’ NOT NULL, action
varchar(255)
DEFAULT
‘’ NOT NULL) ENGINE=InnoDB
SQL (0.001514) DROP TABLE functional_rights_functional_roles
SQL (0.010817) CREATE TABLE functional_rights_functional_roles
(functional_right_id
int(11), functional_role_id
int(11))
ENGINE=InnoDB
SQL (0.001557) DROP TABLE functional_roles
SQL (0.004841) CREATE TABLE functional_roles (id
int(11) DEFAULT
NULL
auto_increment PRIMARY KEY, name
varchar(255) DEFAULT ‘’ NOT NULL)
ENGINE=InnoDB
SQL (0.001718) DROP TABLE functional_roles_users
SQL (0.005080) CREATE TABLE functional_roles_users
(functional_role_id
int(11), user_id
int(11)) ENGINE=InnoDB
SQL (0.001777) DROP TABLE users
SQL (0.005176) CREATE TABLE users (id
int(11) DEFAULT NULL
auto_increment PRIMARY KEY, username
varchar(255) DEFAULT ‘’ NOT NULL,
password_salt
varchar(255) DEFAULT ‘’ NOT NULL, password_hash
varchar(255) DEFAULT ‘’ NOT NULL, email_address
varchar(255) DEFAULT
‘’ NOT
NULL, created_at
datetime NOT NULL) ENGINE=InnoDB
SQL (0.000000) Mysql::Error: Table ‘schema_info’ already exists:
CREATE
TABLE schema_info (version int(11))
SQL (0.000974) SHOW FIELDS FROM schema_info
SQL (0.000680) UPDATE schema_info SET version = 2
============= LISTING D ========================
(in /home/michael/code/rails/work/railsproject)
** Invoke test (first_time)
** Execute test
** Invoke test:units (first_time)
** Invoke db:test:prepare (first_time)
** Invoke environment (first_time)
** Execute environment
** Execute db:test:prepare
** Invoke db:test:clone (first_time)
** Invoke db:schema:dump (first_time)
** Invoke environment
** Execute db:schema:dump
** Execute db:test:clone
** Invoke db:schema:load (first_time)
** Invoke environment
** Execute db:schema:load
** Execute test:units
/usr/bin/ruby18 -Ilib:test
“/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake/rake_test_loader.rb”
“test/unit/functional_role_test.rb” “test/unit/overlay_test.rb”
“test/unit/password_test.rb” “test/unit/user_test.rb”
“test/unit/functional_right_test.rb”
Loaded suite
/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake/rake_test_loader
Started
…
Finished in 1.309497 seconds.
47 tests, 262 assertions, 0 failures, 0 errors
** Invoke test:functionals (first_time)
** Invoke db:test:prepare
** Execute test:functionals
/usr/bin/ruby18 -Ilib:test
“/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake/rake_test_loader.rb”
“test/functional/functional_role_controller_test.rb”
“test/functional/user_controller_test.rb”
“test/functional/functional_right_controller_test.rb”
“test/functional/session_controller_test.rb”
Loaded suite
/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake/rake_test_loader
Started
…
Finished in 0.15657 seconds.
14 tests, 80 assertions, 0 failures, 0 errors
** Invoke test:integration (first_time)
** Invoke db:test:prepare
** Execute test:integration
/usr/bin/ruby18 -Ilib:test
“/usr/lib/ruby/gems/1.8/gems/rake-0.7.1/lib/rake/rake_test_loader.rb”
===========================LISTING E ==========================
ActiveRecord::Schema.define(:version => 2) do
create_table “functional_rights”, :force => true do |t|
t.column “name”, :string, :default => “”, :null => false
t.column “controller”, :string, :default => “”, :null => false
t.column “action”, :string, :default => “”, :null => false
end
create_table “functional_rights_functional_roles”, :id => false,
:force =>
true do |t|
t.column “functional_right_id”, :integer
t.column “functional_role_id”, :integer
end
add_index “functional_rights_functional_roles”,
[“functional_right_id”], :name => “fk_frfr_functional_right”
add_index “functional_rights_functional_roles”,
[“functional_role_id”], :name => “fk_frfr_functional_role”
create_table “functional_roles”, :force => true do |t|
t.column “name”, :string, :default => “”, :null => false
end
create_table “functional_roles_users”, :id => false, :force => true do
|t|
t.column “functional_role_id”, :integer
t.column “user_id”, :integer
end
add_index “functional_roles_users”, [“functional_role_id”], :name =>
“fk_fru_functional_role”
add_index “functional_roles_users”, [“user_id”], :name =>
“fk_fru_user”
create_table “users”, :force => true do |t|
t.column “username”, :string, :default => “”, :null => false
t.column “password_salt”, :string, :default => “”, :null => false
t.column “password_hash”, :string, :default => “”, :null => false
t.column “email_address”, :string, :default => “”, :null => false
t.column “created_at”, :datetime, :null => false
end
end
========================== LISTING F ===========================
class AddFunctionalRightsAndFunctionalRolesTables <
ActiveRecord::Migration
def self.up
create_table(:functional_rights, :force => true) { |t| # A table
storing
the actions on a given controller that a given right allows a user to
perform.
t.column :name, :string, :null => false
t.column :controller, :string, :null => false
t.column :action, :string, :null => false
}
create_table(:functional_roles, :force => true) { |t| # *functional*
roles,
referring to the fact that we are talking about actions that a user may
perform, rather than data they can access.
t.column :name, :string, :null => false
}
# Join
create_table(:functional_rights_functional_roles, :id => false, :force
=>
true) { |t|
t.column :functional_right_id, :integer
t.column :functional_role_id, :integer
}
# Join
create_table(:functional_roles_users, :id => false, :force => true) {
|t|
t.column :functional_role_id, :integer
t.column :user_id, :integer
}
# Add foreign key constraints.
execute 'ALTER TABLE functional_rights_functional_roles ADD CONSTRAINT
fk_frfr_functional_right FOREIGN KEY ( functional_right_id ) REFERENCES
functional_rights( id ) ’
execute 'ALTER TABLE functional_rights_functional_roles ADD CONSTRAINT
fk_frfr_functional_role FOREIGN KEY ( functional_role_id ) REFERENCES
functional_roles( id ) ’
execute 'ALTER TABLE functional_roles_users ADD CONSTRAINT
fk_fru_functional_role FOREIGN KEY ( functional_role_id ) REFERENCES
functional_roles( id ) ’
execute 'ALTER TABLE functional_roles_users ADD CONSTRAINT fk_fru_user
FOREIGN KEY ( user_id ) REFERENCES users( id ) ’
end
def self.down
drop_table :functional_rights_functional_roles
drop_table :functional_roles_users
drop_table :functional_rights
drop_table :functional_roles
end
end