Automate test setup

Goal: rake default task can do everything without manual setup

Also delete `spec/dummy_app/db/schema.rb`. People forget (understandably)
to update it. As long as we don't use the db:setup task first,
we don't need it.
This commit is contained in:
Jared Beck 2018-06-03 22:49:23 -04:00
parent 7d42a02c0c
commit f3bc5290ee
5 changed files with 52 additions and 420 deletions

View File

@ -30,118 +30,40 @@ Testing is a little awkward because the test suite:
1. Contains a "dummy" rails app with three databases (test, foo, and bar)
1. Supports three different RDBMS': sqlite, mysql, and postgres
### Test sqlite, AR 4.2
### Test sqlite, AR 4
```
rm spec/dummy_app/db/*.sqlite3
# Create the appropriate database config. file
rm spec/dummy_app/config/database.yml
DB=sqlite bundle exec rake prepare
# If this is the first test run ever, create databases.
# We can't use `appraisal` inside the dummy app, so we must set `BUNDLE_GEMFILE`.
# See spec/dummy_app/config/boot.rb for a complete explanation.
cd spec/dummy_app
export BUNDLE_GEMFILE=../../gemfiles/ar_4.2.gemfile
RAILS_ENV=test bundle exec rake db:setup
RAILS_ENV=foo bundle exec rake db:setup
RAILS_ENV=bar bundle exec rake db:setup
unset BUNDLE_GEMFILE
cd ../..
# Run tests
DB=sqlite bundle exec appraisal ar-4.2 rake
# Run a single test
DB=sqlite bundle exec appraisal ar-4.2 rspec spec/paper_trail/serializers/json_spec.rb
DB=sqlite bundle exec appraisal ar-4.2 rspec spec/paper_trail_spec.rb
```
### Test sqlite, AR 5
```
rm spec/dummy_app/db/*.sqlite3
# Create the appropriate database config. file
rm spec/dummy_app/config/database.yml
DB=sqlite bundle exec rake prepare
# If this is the first test run ever, create databases.
# We can't use `appraisal` inside the dummy app, so we must set `BUNDLE_GEMFILE`.
# See spec/dummy_app/config/boot.rb for a complete explanation.
cd spec/dummy_app
export BUNDLE_GEMFILE=../../gemfiles/ar_5.2.gemfile
RAILS_ENV=test bundle exec rake db:environment:set db:setup
RAILS_ENV=foo bundle exec rake db:environment:set db:setup
RAILS_ENV=bar bundle exec rake db:environment:set db:setup
unset BUNDLE_GEMFILE
cd ../..
# Run tests
DB=sqlite bundle exec appraisal ar-5.2 rake
```
### Test mysql, AR 5
```
# Create the appropriate database config. file
rm spec/dummy_app/config/database.yml
DB=mysql bundle exec rake prepare
# If this is the first test run ever, create databases.
# We can't use `appraisal` inside the dummy app, so we must set `BUNDLE_GEMFILE`.
# See spec/dummy_app/config/boot.rb for a complete explanation.
cd spec/dummy_app
export BUNDLE_GEMFILE=../../gemfiles/ar_5.2.gemfile
RAILS_ENV=test bundle exec rake db:setup db:environment:set
RAILS_ENV=foo bundle exec rake db:setup db:environment:set
RAILS_ENV=bar bundle exec rake db:setup db:environment:set
unset BUNDLE_GEMFILE
cd ../..
# Run tests
DB=mysql bundle exec appraisal ar-5.2 rake
```
### Test postgres, AR 5
```
# Create the appropriate database config. file
rm spec/dummy_app/config/database.yml
DB=postgres bundle exec rake prepare
# If this is the first test run ever, create databases.
# Unlike mysql, use create/migrate instead of setup.
# We can't use `appraisal` inside the dummy app, so we must set `BUNDLE_GEMFILE`.
# See spec/dummy_app/config/boot.rb for a complete explanation.
cd spec/dummy_app
export BUNDLE_GEMFILE=../../gemfiles/ar_5.2.gemfile
DB=postgres RAILS_ENV=test bundle exec rake db:environment:set db:drop db:create db:migrate
DB=postgres RAILS_ENV=foo bundle exec rake db:environment:set db:drop db:create db:migrate
DB=postgres RAILS_ENV=bar bundle exec rake db:environment:set db:drop db:create db:migrate
unset BUNDLE_GEMFILE
cd ../..
# Run tests
DB=postgres bundle exec rake
createuser --superuser postgres
DB=postgres bundle exec appraisal ar-5.2 rake
```
## Editing the migration
## Adding new schema
After editing `spec/dummy_app/db/migrate/20110208155312_set_up_test_tables.rb` ..
```
cd spec/dummy_app
export BUNDLE_GEMFILE=../../gemfiles/ar_5.1.gemfile
RAILS_ENV=test bundle exec rake db:environment:set db:drop db:create db:migrate
RAILS_ENV=foo bundle exec rake db:environment:set db:drop db:create db:migrate
RAILS_ENV=bar bundle exec rake db:environment:set db:drop db:create db:migrate
unset BUNDLE_GEMFILE
cd ../..
```
Don't forget to commit changes to `schema.rb`.
Edit `spec/dummy_app/db/migrate/20110208155312_set_up_test_tables.rb`. Migration
will be performed by `spec_helper.rb`, so you can just run rake as shown above.
Also, `spec/dummy_app/db/schema.rb` is deliberately `.gitignore`d, we don't use
it.
## Documentation

1
.gitignore vendored
View File

@ -18,6 +18,7 @@ gemfiles/*.lock
pkg/*
spec/dummy/
spec/dummy_app/config/database.yml
spec/dummy_app/db/schema.rb
spec/dummy_app/db/*.sqlite3
spec/dummy_app/log/*
spec/dummy_app/tmp/*

View File

@ -15,26 +15,12 @@ env:
- DB=mysql
- DB=postgres
- DB=sqlite
sudo: false
before_script:
- mysql --version
- sh -c "if [ \"$DB\" = 'mysql' ]; then mysql -e 'create database paper_trail_test;'; fi"
- sh -c "if [ \"$DB\" = 'mysql' ]; then mysql -e 'create database paper_trail_bar; '; fi"
- sh -c "if [ \"$DB\" = 'mysql' ]; then mysql -e 'create database paper_trail_foo; '; fi"
- psql --version
- sh -c "if [ \"$DB\" = 'postgres' ]; then psql -c 'create database paper_trail_test;' -U postgres; fi"
- sh -c "if [ \"$DB\" = 'postgres' ]; then psql -c 'create database paper_trail_bar;' -U postgres; fi"
- sh -c "if [ \"$DB\" = 'postgres' ]; then psql -c 'create database paper_trail_foo;' -U postgres; fi"
gemfile:
- gemfiles/ar_4.2.gemfile
- gemfiles/ar_5.1.gemfile
- gemfiles/ar_5.2.gemfile
matrix:
fast_finish: true
addons:
postgresql: "9.4"

View File

@ -1,15 +1,57 @@
# frozen_string_literal: true
require "fileutils"
require "bundler"
Bundler::GemHelper.install_tasks
desc "Delete generated files and databases"
task :clean do
# It's tempting to use `git clean` here, but this rake task will be run by
# people working on changes that haven't been committed yet, so we have to
# be more selective with what we delete.
::FileUtils.rm("spec/dummy_app/db/database.yml", force: true)
case ENV["DB"]
when "mysql"
%w[test foo bar].each do |db|
system("mysqladmin drop -f paper_trail_#{db} > /dev/null 2>&1")
end
when "postgres"
%w[test foo bar].each do |db|
system("dropdb --if-exists paper_trail_#{db} > /dev/null 2>&1")
end
when nil, "sqlite"
::FileUtils.rm(::Dir.glob("spec/dummy_app/db/*.sqlite3"))
else
raise "Don't know how to clean specified RDBMS: #{ENV['DB']}"
end
end
desc "Write a database.yml for the specified RDBMS"
task :prepare do
task prepare: [:clean] do
ENV["DB"] ||= "sqlite"
FileUtils.cp(
"spec/dummy_app/config/database.#{ENV['DB']}.yml",
"spec/dummy_app/config/database.yml"
)
case ENV["DB"]
when "mysql"
%w[test foo bar].each do |db|
system("mysqladmin create paper_trail_#{db}")
# Migration happens later in spec_helper.
end
when "postgres"
%w[test foo bar].each do |db|
system("createdb paper_trail_#{db}")
# Migration happens later in spec_helper.
end
when nil, "sqlite"
# noop. test.sqlite3 will be created when migration happens in spec_helper.
# Shortly thereafter, foo and bar.sqlite3 are created when
# spec/support/alt_db_init.rb is `require`d.
nil
else
raise "Don't know how to create specified DB: #{ENV['DB']}"
end
end
require "rspec/core/rake_task"

View File

@ -1,319 +0,0 @@
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# Note that this schema.rb definition is the authoritative source for your
# database schema. If you need to create the application database on another
# system, you should be using db:schema:load, not running all the migrations
# from scratch. The latter is a flawed and unsustainable approach (the more migrations
# you'll amass, the slower it'll run and the greater likelihood for issues).
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20110208155312) do
create_table "animals", force: :cascade do |t|
t.string "name"
t.string "species"
end
create_table "articles", force: :cascade do |t|
t.string "title"
t.string "content"
t.string "abstract"
t.string "file_upload"
end
create_table "authorships", force: :cascade do |t|
t.integer "book_id"
t.integer "author_id"
end
create_table "banana_versions", force: :cascade do |t|
t.string "item_type", null: false
t.integer "item_id", null: false
t.string "event", null: false
t.string "whodunnit"
t.text "object"
t.datetime "created_at", limit: 6
t.index ["item_type", "item_id"], name: "index_banana_versions_on_item_type_and_item_id"
end
create_table "bananas", force: :cascade do |t|
t.datetime "created_at", limit: 6
t.datetime "updated_at", limit: 6
end
create_table "bar_habtms", force: :cascade do |t|
t.string "name"
end
create_table "bar_habtms_foo_habtms", id: false, force: :cascade do |t|
t.integer "foo_habtm_id"
t.integer "bar_habtm_id"
t.index ["bar_habtm_id"], name: "index_bar_habtms_foo_habtms_on_bar_habtm_id"
t.index ["foo_habtm_id"], name: "index_bar_habtms_foo_habtms_on_foo_habtm_id"
end
create_table "books", force: :cascade do |t|
t.string "title"
end
create_table "boolits", force: :cascade do |t|
t.string "name"
t.boolean "scoped", default: true
end
create_table "callback_modifiers", force: :cascade do |t|
t.string "some_content"
t.boolean "deleted", default: false
end
create_table "chapters", force: :cascade do |t|
t.string "name"
end
create_table "citations", force: :cascade do |t|
t.integer "quotation_id"
end
create_table "custom_primary_key_record_versions", force: :cascade do |t|
t.string "item_type", null: false
t.string "item_id", null: false
t.string "event", null: false
t.string "whodunnit"
t.text "object"
t.datetime "created_at", limit: 6
t.index ["item_type", "item_id"], name: "idx_cust_pk_item"
end
create_table "custom_primary_key_records", primary_key: "uuid", id: :string, force: :cascade do |t|
t.string "name"
t.index ["uuid"], unique: true
t.datetime "created_at", limit: 6
t.datetime "updated_at", limit: 6
end
create_table "customers", force: :cascade do |t|
t.string "name"
end
create_table "documents", force: :cascade do |t|
t.string "name"
end
create_table "editors", force: :cascade do |t|
t.string "name"
end
create_table "editorships", force: :cascade do |t|
t.integer "book_id"
t.integer "editor_id"
end
create_table "families", force: :cascade do |t|
t.string "name"
t.integer "parent_id"
t.integer "partner_id"
end
create_table "family_lines", force: :cascade do |t|
t.integer "parent_id"
t.integer "grandson_id"
end
create_table "fluxors", force: :cascade do |t|
t.integer "widget_id"
t.string "name"
end
create_table "foo_habtms", force: :cascade do |t|
t.string "name"
end
create_table "fruits", force: :cascade do |t|
t.string "name"
t.string "color"
end
create_table "gadgets", force: :cascade do |t|
t.string "name"
t.string "brand"
t.datetime "created_at", limit: 6
t.datetime "updated_at", limit: 6
end
create_table "legacy_widgets", force: :cascade do |t|
t.string "name"
t.integer "version"
end
create_table "line_items", force: :cascade do |t|
t.integer "order_id"
t.string "product"
end
create_table "not_on_updates", force: :cascade do |t|
t.datetime "created_at", limit: 6
t.datetime "updated_at", limit: 6
end
create_table "on_create", force: :cascade do |t|
t.string "name", null: false
end
create_table "on_destroy", force: :cascade do |t|
t.string "name", null: false
end
create_table "on_empty_array", force: :cascade do |t|
t.string "name", null: false
end
create_table "on_touch", force: :cascade do |t|
t.string "name", null: false
end
create_table "on_update", force: :cascade do |t|
t.string "name", null: false
end
create_table "orders", force: :cascade do |t|
t.integer "customer_id"
t.string "order_date"
end
create_table "paragraphs", force: :cascade do |t|
t.integer "section_id"
t.string "name"
end
create_table "people", force: :cascade do |t|
t.string "name"
t.string "time_zone"
t.integer "mentor_id"
end
create_table "pets", force: :cascade do |t|
t.integer "owner_id"
t.integer "animal_id"
end
create_table "post_versions", force: :cascade do |t|
t.string "item_type", null: false
t.integer "item_id", null: false
t.string "event", null: false
t.string "whodunnit"
t.text "object"
t.datetime "created_at", limit: 6
t.string "ip"
t.string "user_agent"
t.index ["item_type", "item_id"], name: "index_post_versions_on_item_type_and_item_id"
end
create_table "post_with_statuses", force: :cascade do |t|
t.integer "status"
t.datetime "created_at", null: false, limit: 6
t.datetime "updated_at", null: false, limit: 6
end
create_table "posts", force: :cascade do |t|
t.string "title"
t.string "content"
end
create_table "quotations", force: :cascade do |t|
t.integer "chapter_id"
end
create_table "sections", force: :cascade do |t|
t.integer "chapter_id"
t.string "name"
end
create_table "skippers", force: :cascade do |t|
t.string "name"
t.datetime "another_timestamp", limit: 6
t.datetime "created_at", limit: 6
t.datetime "updated_at", limit: 6
end
create_table "songs", force: :cascade do |t|
t.integer "length"
end
create_table "things", force: :cascade do |t|
t.string "name"
end
create_table "translations", force: :cascade do |t|
t.string "headline"
t.string "content"
t.string "language_code"
t.string "type"
end
create_table "vehicles", force: :cascade do |t|
t.string "name", null: false
t.string "type", null: false
t.integer "owner_id"
t.datetime "created_at", null: false, limit: 6
t.datetime "updated_at", null: false, limit: 6
end
create_table "version_associations", force: :cascade do |t|
t.integer "version_id"
t.string "foreign_key_name", null: false
t.integer "foreign_key_id"
t.index ["foreign_key_name", "foreign_key_id"], name: "index_version_associations_on_foreign_key"
t.index ["version_id"], name: "index_version_associations_on_version_id"
end
create_table "versions", force: :cascade do |t|
t.string "item_type", null: false
t.integer "item_id", null: false
t.string "event", null: false
t.string "whodunnit"
t.text "object", limit: 1073741823
t.text "object_changes", limit: 1073741823
t.integer "transaction_id"
t.datetime "created_at", limit: 6
t.integer "answer"
t.string "action"
t.string "question"
t.integer "article_id"
t.string "title"
t.string "ip"
t.string "user_agent"
t.index ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id"
end
create_table "whatchamajiggers", force: :cascade do |t|
t.string "owner_type"
t.integer "owner_id"
t.string "name"
end
create_table "widgets", force: :cascade do |t|
t.string "name"
t.text "a_text"
t.integer "an_integer"
t.float "a_float"
t.decimal "a_decimal", precision: 6, scale: 4
t.datetime "a_datetime", limit: 6
t.time "a_time"
t.date "a_date"
t.boolean "a_boolean"
t.string "type"
t.datetime "created_at", limit: 6
t.datetime "updated_at", limit: 6
end
create_table "wotsits", force: :cascade do |t|
t.integer "widget_id"
t.string "name"
t.datetime "created_at", limit: 6
t.datetime "updated_at", limit: 6
end
end