gitlab-org--gitlab-foss/spec/migrations
Grzegorz Bizon 5331a49d0b Merge branch 'master' into fix/gb/improve-updating-column-in-batches-helper
* master: (56 commits)
  File view buttons
  Don't reset the session when the example failed, because we need capybara-screenshot to have access to it
  Resolve "MR comment + system note highlight don't have the same width"
  Add feature spec for dashboard state filter tabs
  Wording of Mysql support.
  a new feature checklist and more elaborate documentation requirements
  Filter archived project in API v3 only if param present
  Revert to using links instead of buttons in Issuable Index tabs.
  Do not run the codeclimate job on docs-only changes
  Only show gray footer space if environment actions exist
  Migrate Gitlab::Git::Blob.find to Gitaly
  Backport filtered search lazy token consistent state fix
  Add a comment explaining how the branch clean up happens
  Fix Github::Representation::PullRequest#source_branch_exists?
  Add CHANGELOG
  Fix GitHub importer performance on branch existence check
  Rebuild the dynamic path before validating it
  Rename stage ref migration specs to match a class name
  Enable Style/DotPosition Rubocop 👮
  Revert "Merge branch 'winh-merge-request-related-issues' into 'master'"
  ...

Conflicts:
	db/post_migrate/20170526185921_migrate_build_stage_reference.rb
2017-06-22 12:37:38 +02:00
..
active_record
add_head_pipeline_for_each_merge_request_spec.rb Fix migration specs that can not run within transaction 2017-06-21 16:21:12 +02:00
clean_upload_symlinks_spec.rb Bring in security changes from the 9.2.5 release 2017-06-08 16:17:13 +02:00
cleanup_namespaceless_pending_delete_projects_spec.rb
convert_custom_notification_settings_to_columns_spec.rb Deserialise existing custom notification settings 2017-06-15 15:15:13 +01:00
fix_wrongly_renamed_routes_spec.rb
migrate_build_stage_reference_again_spec.rb Rename stage ref migration specs to match a class name 2017-06-21 15:51:00 +02:00
migrate_old_artifacts_spec.rb Add missing specs 2017-06-01 16:34:48 +02:00
migrate_pipeline_stages_spec.rb Migrate stages only with correct foreign references 2017-06-06 14:32:24 +02:00
migrate_process_commit_worker_jobs_spec.rb Enable Style/DotPosition Rubocop 👮 2017-06-21 13:48:12 +00:00
migrate_user_activities_to_users_last_activity_on_spec.rb Fix migration specs that can not run within transaction 2017-06-21 16:21:12 +02:00
migrate_user_project_view_spec.rb Disable transaction in specs for some migrations 2017-06-22 12:35:47 +02:00
move_uploads_to_system_dir_spec.rb Bring in security changes from the 9.2.5 release 2017-06-08 16:17:13 +02:00
README.md Document a new migrations testing technique 2017-06-15 13:05:56 +02:00
remove_dot_git_from_usernames_spec.rb
rename_more_reserved_project_names_spec.rb Correct RSpec/SingleLineHook cop offenses 2017-06-14 13:18:56 -05:00
rename_reserved_project_names_spec.rb Correct RSpec/SingleLineHook cop offenses 2017-06-14 13:18:56 -05:00
rename_system_namespaces_spec.rb Update rename_system_namespace_spec to new validations. 2017-06-08 16:17:13 +02:00
rename_users_with_renamed_namespace_spec.rb Simpler way of renaming users 2017-05-19 17:27:18 +02:00
turn_nested_groups_into_regular_groups_for_mysql_spec.rb Enable Style/DotPosition Rubocop 👮 2017-06-21 13:48:12 +00:00
update_retried_for_ci_build_spec.rb Disable Migration/UpdateColumnInBatches for old migrations 2017-05-29 11:28:23 +02:00
update_upload_paths_to_system_spec.rb Bring in security changes from the 9.2.5 release 2017-06-08 16:17:13 +02:00

Testing migrations

In order to reliably test a migration, we need to test it against a database schema that this migration has been written for. In order to achieve that we have some migration helpers and RSpec test tag, called :migration.

If you want to write a test for a migration consider adding :migration tag to the test signature, like describe SomeMigrationClass, :migration.

How does it work?

Adding a :migration tag to a test signature injects a few before / after hooks to the test.

The most important change is that adding a :migration tag adds a before hook that will revert all migrations to the point that a migration under test is not yet migrated.

In other words, our custom RSpec hooks will find a previous migration, and migrate the database down to the previous migration version.

With this approach you can test a migration against a database schema that this migration has been written for.

Use migrate! helper to run the migration that is under test.

The after hook will migrate the database up and reinstitutes the latest schema version, so that the process does not affect subsequent specs and ensures proper isolation.

Available helpers

Use table helper to create a temporary ActiveRecord::Base derived model for a table.

Use migrate! helper to run the migration that is under test. It will not only run migration, but will also bump the schema version in the schema_migrations table. It is necessary because in the after hook we trigger the rest of the migrations, and we need to know where to start.

See spec/support/migrations_helpers.rb for all the available helpers.

An example

require 'spec_helper'

# Load a migration class.

require Rails.root.join('db', 'post_migrate', '20170526185842_migrate_pipeline_stages.rb')

describe MigratePipelineStages, :migration do

  # Create test data - pipeline and CI/CD jobs.

  let(:jobs) { table(:ci_builds) }
  let(:stages) { table(:ci_stages) }
  let(:pipelines) { table(:ci_pipelines) }
  let(:projects) { table(:projects) }

  before do
    projects.create!(id: 123, name: 'gitlab1', path: 'gitlab1')
    pipelines.create!(id: 1, project_id: 123, ref: 'master', sha: 'adf43c3a')
    jobs.create!(id: 1, commit_id: 1, project_id: 123, stage_idx: 2, stage: 'build')
    jobs.create!(id: 2, commit_id: 1, project_id: 123, stage_idx: 1, stage: 'test')
  end

  # Test the migration.

  it 'correctly migrates pipeline stages' do
    expect(stages.count).to be_zero

    migrate!

    expect(stages.count).to eq 2
    expect(stages.all.pluck(:name)).to match_array %w[test build]
  end
end

Best practices

  1. Use only one test example per migration unless there is a good reason to use more.
  2. Note that this type of tests do not run within the transaction, we use a truncation database cleanup strategy. Do not depend on transaction being present.