rails strange unit test fails - ruby-on-rails

I try to run this simplest unit test:
test "the truth" do
assert true
end
like this:
ruby -Itest test/unit/my_model_test.rb
(there is the only one test in the file, and actually in the whole site)
it fails with this message:
ActiveRecord::RecordNotUnique: SQLite3::ConstraintException: column email is not unique: INSERT INTO "users"... [some values to insert here]
now I do have a table named "users" but other than that I have never asked to do any tests on it nor do I even have such tests. Where does this error come from? How do I run just my test?
EDIT: the "users" table comes from the devise gem if that helps

Quote from http://guides.rubyonrails.org/testing.html
Rails by default automatically loads all fixtures from the
test/fixtures folder for your unit and functional test. Loading
involves three steps:
Remove any existing data from the table corresponding to the fixture
Load the fixture data into the table
Dump the fixture data into a
variable in case you want to access it directly
So I think you need to check those fixtures. Also I suggest you to read that tutorial. It is very well written.

Related

Ruby on Rails - Understanding Database Dependencies in Test

I've got some model code that calls to the database with a simple find():
#thing = Thing.find(id)
I have data seeded in the database for the test environment. If I open the console in test (rails c -e test), I can run Thing.find(1) and get a result fine, however when I run a test that calls the method shown above, it reports that it cannot find a record with the id of 1.
I assume I am misunderstanding the relationship between test seed data and the tests being run against that database. Why do I see seed sin the test DB but the test doesn't?
A more conventional way of doing this would be to create fixtures (or factories if using FactoryBot) and call these factories in your test setup. As previous answers have said, hardcoding test ID's will likely return RecordNotFound due to auto-incrementing.

Ruby on Rails 4 fixtures require table

Fixtures when using Rails (My environment Rails 4.2)
Why when running a test, why does it error when a fixture exists but there isn't a table with the same name? And why does the fixture require to have a matching column in the table?
Example 1: (table does not exist)
create a fixture joes.yml (Joes table does not exist)
Run the rake test:integration
The error you'll get is:
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such table: joes: DELETE FROM "joes"
Example 2: (table exists, but column does not)
create a fixture products.yml. This case the table Products does exist
add a yml block with a name of a column you don't have in the products table. example add an entry other: bla in the products.yml file
Run the rake test:integration
ActiveRecord::Fixture::FixtureError: table "products" has no column named "other".
I thought I could use fixtures as common place to reference in my tests, but doesn't need to match my DB.
Fixtures are your data, they still require a place to go!
"Fixtures allow you to populate your testing database with predefined data before your tests run. Fixtures are database independent written in YAML. There is one file per model."
http://guides.rubyonrails.org/testing.html#the-low-down-on-fixtures
They are not some sort of in memory replacement for a testing database, they just allow you to pre-populate your test database with values, so that you can test more conveniently without having to put lots of data in, when setting up a test run. That's all.

How to create mysql function in rails test database?

I wrote a Mysql function for my rails app and i added it to my database by manual.
When i want to test the function using Rails UNIT test, it through the errors like below
ActiveRecord::StatementInvalid: Mysql::Error: FUNCTION mydatabase.fn_Sample_Function does not exist:
How to add the function, out of the test suite or beginning of test run ?
Thanks in Advance,
Aaa.
I can't see the error. But I assume the problem is your schema format.
config.active_record.schema_format = :sql
in application.rb should be what you need to do.
The reason behind that is by default your test database is not made from a schema only dump of your development database, but, instead from db/schema.rb - which knows nothing about mysql functions.
an sql schema format will do a mysqldump (or pg_dump) with the schema only flag set to true and create a development_structure.sql file.

How to use ruby-on-rails fixtures for setting up (external) data that does not belong to the rails app DB?

Per my requirements, I have created models for querying external database (different from the one that the rails app uses) for some of the data.
I am trying to write tests around these models and want to separate the "sample test data" from the actual tests.
I thought I could put the data in a yml file and load it into a hash, but it did work out :(
Added sample test data to a fixture file name 'external_database.yml'
Put the below code in setup, in the test file
ext_data = YAML.load_file(Rails.root.to_s + "/test/fixtures/ext_data.yml")
But I am stuck with the below error
1) Error:
test_should_errorout_for_invalid_market_zip(ExtDBTest):
ActiveRecord::StatementInvalid: Mysql::Error: Table 'rails_app_db.ext_data' doesn't exist: DELETE FROM ext_data
What is the best way to do what I want done?
I guess your problem is that the schema of that external database is not contained in your schema.rb-file and/or migrations. These are used to setup your test-database before you run the tests.
So the attempt is made to write those fixtures into non-existing tables - with the result you see above.
Multiple database-connections in unit tests are generally a pain. Consider creating an sqlite-file for the data of the external dependencies and configure your test-environment to use this file - or a copy of it, in case you need to mutate data.

Populate a constant values table

In a Rails application, I need a table in my database to contain constant data.
This table content is not intended to change for the moment but I do not want to put the content in the code, to be able to change it whenever needed.
I tried filling this table in the migration that created it, but this does not seem to work with the test environment and breaks my unit tests. In test environment, my model is never able to return any value while it is ok in my development environment.
Is there a way to fill that database correctly even in test environment ? Is there another way of handling these kind of data that should not be in code ?
edit
Thanks all for your answers and especially Vlad R for explaining the problem.
I now understand why my data are not loaded in test. This is because the test environment uses the db:load rake command which directly loads the schema instead of running the migrations. Having put my values in the migration only and not in the schema, these values are not loaded for test.
What you are probably observing is that the test framework is not running the migrations (db:migrate), but loading db/schema.rb directly (db:load) instead.
You have two options:
continue to use the migration for production and development; for the test environment, add your constant data to the corresponding yml files in db/fixtures
leave the existing db/fixtures files untouched, and create another set of yml files (containing the constant data) in the same vein as db/fixtures, but usable by both test and production/development environments when doing a rake db:load schema initialization
To cover those scenarios that use db:load (instead of db:migrate - e.g. test, bringing up a new database on a new development machine using the faster db:load instead of db:migrate, etc.) is create a drop-in rakefile in RAILS_APP/lib/tasks to augment the db:load task by loading your constant intialization data from "seed" yml files (one for each model) into the database.
Use the db:seed rake task as an example. Put your seed data in db/seeds/.yml
#the command is: rake:db:load
namespace :db do
desc 'Initialize data from YAML.'
task :load => :environment do
require 'active_record/fixtures'
Dir.glob(RAILS_ROOT + '/db/seeds/*.yml').each do |file|
Fixtures.create_fixtures('db/seeds', File.basename(file, '.*'))
end
end
end
To cover the incremental scenarios (db:migrate), define one migration that does the same thing as the task defined above.
If your seed data ever changes, you will need to add another migration to remove the old seed data and load the new one instead, which may be non-trivial in case of foreign-key dependencies etc.
Take a look at my article on loading seed data.
There's a number of ways to do this. I like a rake task called db:populate which lets you specify your fixed data in normal ActiveRecord create statements. For getting the data into tests, I've just be loading this populate file in my test_helper. However, I think I am going to switch to a test database that already has the seed data populated.
There's also plugin called SeedFu that helps with this problem.
Whatever you do, I recommend against using fixtures for this, because they don't validate your data, so it's very easy to create invalid records.

Resources