Тест с VCR без отката изменений базы данных

Я столкнулся с рядом сбоев, когда тест с поддержкой видеомагнитофона добавляет дополнительную запись в мою таблицу Projects, и эта запись сохраняется в ходе дополнительных тестов, вызывая сбои, а не откатывается в конце теста. В частности, у меня есть 4 проекта, созданных моими приборами Rails, а затем тест, который включает кассету видеомагнитофона для добавления дополнительного проекта. Этот тест всегда проходит, но после этого база данных не сбрасывается на 4 проекта.

Удобно, что проект с открытым исходным кодом, так что вы можете запустить его самостоятельно. Ошибку можно увидеть на мастере по адресу https://github.com/linuxfoundation/cii-best-practices-badge (оформить коммит 048776f, чтобы не получить временный обходной путь). Тест, вызывающий проблему, — это https://github.com/linuxfoundation/cii-best-practices-badge/blob/master/test/features/github_login_test.rb, который (с кассетой видеомагнитофона) входит в Github и получает список общедоступных проектов из теста. Пользователь. Он использует Capybara через https://github.com/blowmage/minitest-rails-capybara жемчужина.

При запуске с SEED=41779 rake test тест с использованием видеомагнитофона завершается успешно, но более поздний тест завершается неудачей, поскольку он подсчитывает 5, а не 4 проекта.

Вот журнал тестирования, где вы можете видеть, что ROLLBACK вызывается в конце, но SAVEPOINT никогда не указывалось в начале теста.

---------------------------------------------------
GithubLoginTest: test_0001_Has link to GitHub Login
---------------------------------------------------
Started GET "/" for 127.0.0.1 at 2016-05-30 22:02:03 -0400
Processing by StaticPagesController#home as HTML
  Rendered static_pages/home.html.erb within layouts/application (0.2ms)
  Rendered layouts/_header.html.erb (0.5ms)
  Rendered layouts/_footer.html.erb (1.3ms)
Completed 200 OK in 6ms (Views: 4.7ms | ActiveRecord: 0.0ms)
Started GET "/projects/new" for 127.0.0.1 at 2016-05-30 22:02:03 -0400
Processing by ProjectsController#new as HTML
  Rendered sessions/new.html.erb (3.2ms)
  Rendered projects/new.html.erb within layouts/application (8.6ms)
  Rendered layouts/_header.html.erb (1.5ms)
  Rendered layouts/_footer.html.erb (1.9ms)
Completed 200 OK in 28ms (Views: 25.0ms | ActiveRecord: 0.0ms)
Started POST "/auth/github" for 127.0.0.1 at 2016-05-30 22:02:03 -0400
Started GET "/auth/github/callback" for 127.0.0.1 at 2016-05-30 22:02:03 -0400
Processing by SessionsController#create as HTML
  Parameters: {"provider"=>"github"}
  [1m[36mUser Load (0.3ms)[0m  [1mSELECT  "users".* FROM "users" WHERE "users"."provider" = $1 AND "users"."uid" = $2 LIMIT 1[0m  [["provider", "github"], ["uid", "12345"]]
  [1m[35m (0.1ms)[0m  BEGIN
  [1m[36mSQL (0.5ms)[0m  [1mINSERT INTO "users" ("provider", "uid", "name", "email", "nickname", "activated", "created_at", "updated_at", "activation_digest") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9) RETURNING "id"[0m  [["provider", "github"], ["uid", "12345"], ["name", "CII Test"], ["email", "[email protected]"], ["nickname", "CIITheRobot"], ["activated", "t"], ["created_at", "2016-05-31 02:02:03.288717"], ["updated_at", "2016-05-31 02:02:03.288717"], ["activation_digest", "$2a$04$BhFbVTS54Yeeurh83VBmdOs.T30jvliDmEFIQ6/lMpnhpN7rGvVTW"]]
  [1m[35m (0.3ms)[0m  COMMIT
Redirected to http://127.0.0.1:31337/
  [1m[36mUser Load (0.3ms)[0m  [1mSELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1[0m  [["id", 764040364]]
Completed 302 Found in 11ms (ActiveRecord: 1.5ms)
Started GET "/" for 127.0.0.1 at 2016-05-30 22:02:03 -0400
Processing by StaticPagesController#home as HTML
  [1m[35mUser Load (0.2ms)[0m  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 764040364]]
  Rendered static_pages/home.html.erb within layouts/application (0.2ms)
  Rendered layouts/_header.html.erb (0.6ms)
  Rendered layouts/_footer.html.erb (1.2ms)
Completed 200 OK in 6ms (Views: 4.3ms | ActiveRecord: 0.2ms)
Started GET "/projects/new" for 127.0.0.1 at 2016-05-30 22:02:03 -0400
Processing by ProjectsController#new as HTML
  [1m[36mUser Load (0.2ms)[0m  [1mSELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1[0m  [["id", 764040364]]
  Rendered shared/_error_messages.html.erb (0.6ms)
  Rendered projects/new.html.erb within layouts/application (31.6ms)
  Rendered layouts/_header.html.erb (1.0ms)
  Rendered layouts/_footer.html.erb (1.8ms)
Completed 200 OK in 41ms (Views: 38.6ms | ActiveRecord: 0.2ms)
Started POST "/projects" for 127.0.0.1 at 2016-05-30 22:02:03 -0400
Processing by ProjectsController#create as HTML
  Parameters: {"utf8"=>"✓", "project"=>{"repo_url"=>"https://github.com/ciitest/cii-best-practices-badge"}, "commit"=>"Submit GitHub Repository"}
  [1m[35mUser Load (0.4ms)[0m  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 764040364]]
  [1m[36mProject Exists (0.6ms)[0m  [1mSELECT  1 AS one FROM "projects" WHERE "projects"."repo_url" = $1 LIMIT 1[0m  [["repo_url", "https://github.com/ciitest/cii-best-practices-badge"]]
  [1m[35m (0.2ms)[0m  BEGIN
  [1m[36mProject Exists (0.6ms)[0m  [1mSELECT  1 AS one FROM "projects" WHERE "projects"."repo_url" = 'https://github.com/ciitest/cii-best-practices-badge' LIMIT 1[0m
  [1m[35mSQL (1.0ms)[0m  INSERT INTO "projects" ("repo_url", "user_id", "homepage_url", "name", "sites_https_status", "sites_https_justification", "repo_public_status", "repo_public_justification", "repo_track_status", "repo_track_justification", "repo_distributed_status", "repo_distributed_justification", "contribution_status", "contribution_justification", "discussion_status", "discussion_justification", "license_location_status", "license_location_justification", "release_notes_status", "release_notes_justification", "build_status", "build_justification", "build_common_tools_status", "build_common_tools_justification", "badge_percentage", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27) RETURNING "id"  [["repo_url", "https://github.com/ciitest/cii-best-practices-badge"], ["user_id", 764040364], ["homepage_url", "https://bestpractices.coreinfrastructure.org"], ["name", "Core Infrastructure Initiative Best Practices Badge"], ["sites_https_status", "Met"], ["sites_https_justification", "Given only https: URLs."], ["repo_public_status", "Met"], ["repo_public_justification", "Repository on GitHub, which provides public git repositories with URLs."], ["repo_track_status", "Met"], ["repo_track_justification", "Repository on GitHub, which uses git. git can track the changes, who made them, and when they were made."], ["repo_distributed_status", "Met"], ["repo_distributed_justification", "Repository on GitHub, which uses git. git is distributed."], ["contribution_status", "Met"], ["contribution_justification", "Non-trivial contribution file in repository: <https://github.com/ciitest/cii-best-practices-badge/blob/master/CONTRIBUTING.md>."], ["discussion_status", "Met"], ["discussion_justification", "GitHub supports discussions on issues and pull requests."], ["license_location_status", "Met"], ["license_location_justification", "Non-trivial license location file in repository: <https://github.com/ciitest/cii-best-practices-badge/blob/master/LICENSE>."], ["release_notes_status", "Met"], ["release_notes_justification", "Non-trivial release notes file in repository: <https://github.com/ciitest/cii-best-practices-badge/blob/master/CHANGELOG.md>."], ["build_status", "Met"], ["build_justification", "Non-trivial build file in repository: <https://github.com/ciitest/cii-best-practices-badge/blob/master/Rakefile>."], ["build_common_tools_status", "Met"], ["build_common_tools_justification", "Non-trivial build file in repository: <https://github.com/ciitest/cii-best-practices-badge/blob/master/Rakefile>."], ["badge_percentage", 15], ["created_at", "2016-05-31 02:02:03.602250"], ["updated_at", "2016-05-31 02:02:03.602250"]]
  [1m[36mSQL (0.4ms)[0m  [1mINSERT INTO "versions" ("event", "whodunnit", "created_at", "item_id", "item_type") VALUES ($1, $2, $3, $4, $5) RETURNING "id"[0m  [["event", "create"], ["whodunnit", "764040364"], ["created_at", "2016-05-31 02:02:03.602250"], ["item_id", 980190963], ["item_type", "Project"]]
  [1m[35m (0.5ms)[0m  COMMIT
Redirected to http://127.0.0.1:31337/projects/980190963/edit
Completed 302 Found in 117ms (ActiveRecord: 4.3ms)
Started GET "/projects/980190963/edit" for 127.0.0.1 at 2016-05-30 22:02:03 -0400
Processing by ProjectsController#edit as HTML
  Parameters: {"id"=>"980190963"}
  [1m[36mUser Load (0.2ms)[0m  [1mSELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1[0m  [["id", 764040364]]
  [1m[35mProject Load (0.7ms)[0m  SELECT  "projects".* FROM "projects" WHERE "projects"."id" = $1  ORDER BY "projects"."created_at" ASC LIMIT 1  [["id", 980190963]]
  [1m[36mProject Exists (0.3ms)[0m  [1mSELECT  1 AS one FROM "projects" WHERE "projects"."user_id" = $1 AND "projects"."id" = $2 LIMIT 1[0m  [["user_id", 764040364], ["id", 980190963]]
  Rendered projects/_details.html.erb (0.0ms)
  Rendered shared/_error_messages.html.erb (0.0ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_details.html.erb (0.1ms)
  Rendered projects/_status_chooser.html.erb (3.3ms)
  Rendered projects/_status_chooser.html.erb (2.4ms)
  Rendered projects/_details.html.erb (0.1ms)
  Rendered projects/_status_chooser.html.erb (3.9ms)
  Rendered projects/_status_chooser.html.erb (3.3ms)
  Rendered projects/_details.html.erb (0.1ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (3.2ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.5ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.2ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.5ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.3ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.4ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.7ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.2ms)
  Rendered projects/_details.html.erb (0.1ms)
  Rendered projects/_status_chooser.html.erb (2.8ms)
  Rendered projects/_status_chooser.html.erb (2.9ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.3ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.0ms)
  Rendered projects/_status_chooser.html.erb (2.0ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.5ms)
  Rendered projects/_status_chooser.html.erb (1.9ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.6ms)
  Rendered projects/_status_chooser.html.erb (2.7ms)
  Rendered projects/_status_chooser.html.erb (1.9ms)
  Rendered projects/_status_chooser.html.erb (1.9ms)
  Rendered projects/_status_chooser.html.erb (2.1ms)
  Rendered projects/_status_chooser.html.erb (1.9ms)
  Rendered projects/_status_chooser.html.erb (1.9ms)
  Rendered projects/_details.html.erb (0.1ms)
  Rendered projects/_status_chooser.html.erb (2.0ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.5ms)
  Rendered projects/_status_chooser.html.erb (1.9ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.2ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.2ms)
  Rendered projects/_status_chooser.html.erb (2.0ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.0ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.1ms)
  Rendered projects/_status_chooser.html.erb (1.9ms)
  Rendered projects/_status_chooser.html.erb (1.9ms)
  Rendered projects/_status_chooser.html.erb (1.9ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.2ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.3ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.4ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.3ms)
  Rendered projects/_status_chooser.html.erb (2.3ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (3.1ms)
  Rendered projects/_details.html.erb (0.1ms)
  Rendered projects/_status_chooser.html.erb (4.6ms)
  Rendered projects/_status_chooser.html.erb (3.6ms)
  Rendered projects/_status_chooser.html.erb (3.1ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.6ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.3ms)
  Rendered projects/_status_chooser.html.erb (2.1ms)
  Rendered projects/_status_chooser.html.erb (3.6ms)
  Rendered projects/_status_chooser.html.erb (3.7ms)
  Rendered projects/_status_chooser.html.erb (3.6ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (3.3ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.7ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.5ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.2ms)
  Rendered projects/_status_chooser.html.erb (2.1ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.2ms)
  Rendered projects/_details.html.erb (0.1ms)
  Rendered projects/_status_chooser.html.erb (3.9ms)
  Rendered projects/_status_chooser.html.erb (2.7ms)
  Rendered projects/_details.html.erb (0.1ms)
  Rendered projects/_status_chooser.html.erb (4.0ms)
  Rendered projects/_status_chooser.html.erb (2.8ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.5ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.3ms)
  Rendered projects/_status_chooser.html.erb (2.0ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.2ms)
  Rendered projects/_details.html.erb (0.1ms)
  Rendered projects/_status_chooser.html.erb (2.3ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.6ms)
  Rendered projects/_status_chooser.html.erb (2.3ms)
  Rendered projects/_status_chooser.html.erb (2.3ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.4ms)
  Rendered projects/_status_chooser.html.erb (2.3ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.2ms)
  Rendered projects/_details.html.erb (0.0ms)
  Rendered projects/_status_chooser.html.erb (2.3ms)
  Rendered projects/_form.html.erb (202.1ms)
  Rendered projects/edit.html.erb within layouts/application (202.6ms)
  Rendered layouts/_header.html.erb (0.7ms)
  Rendered layouts/_footer.html.erb (1.3ms)
Completed 200 OK in 214ms (Views: 207.2ms | ActiveRecord: 1.1ms)
Started GET "/users/764040364" for 127.0.0.1 at 2016-05-30 22:02:04 -0400
Processing by UsersController#show as HTML
  Parameters: {"id"=>"764040364"}
  [1m[35mUser Load (0.2ms)[0m  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 764040364]]
  [1m[36mUser Load (0.7ms)[0m  [1mSELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1[0m  [["id", 764040364]]
  [1m[35mProject Load (3.6ms)[0m  SELECT "projects".* FROM "projects" WHERE "projects"."repo_url" IN ('https://github.com/ciitest/cii-best-practices-badge', 'https://github.com/ciitest/test-repo')  ORDER BY "projects"."created_at" ASC
  [1m[36mProject Load (1.1ms)[0m  [1mSELECT  "projects".* FROM "projects" WHERE "projects"."user_id" = $1  ORDER BY "projects"."created_at" ASC LIMIT 30 OFFSET 0[0m  [["user_id", 764040364]]
  [1m[35mProject Exists (0.3ms)[0m  SELECT  1 AS one FROM "projects" WHERE "projects"."user_id" = $1 LIMIT 1  [["user_id", 764040364]]
  Rendered projects/_table.html.erb (2.3ms)
  Rendered users/show.html.erb within layouts/application (6.9ms)
  Rendered layouts/_header.html.erb (1.1ms)
  Rendered layouts/_footer.html.erb (1.1ms)
Completed 200 OK in 48ms (Views: 13.5ms | ActiveRecord: 5.9ms)
Started GET "/projects/980190963/badge" for 127.0.0.1 at 2016-05-30 22:02:04 -0400
Processing by ProjectsController#badge as SVG
  Parameters: {"id"=>"980190963"}
  [1m[36mUser Load (0.2ms)[0m  [1mSELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1[0m  [["id", 764040364]]
  [1m[35mProject Load (0.8ms)[0m  SELECT  "projects".* FROM "projects" WHERE "projects"."id" = $1  ORDER BY "projects"."created_at" ASC LIMIT 1  [["id", 980190963]]
  Rendered text template (0.0ms)
Sent data  (0.7ms)
Completed 200 OK in 8ms (Views: 0.6ms | ActiveRecord: 1.0ms)
  [1m[36m (0.3ms)[0m  [1mROLLBACK[0m
  [1m[35m (0.1ms)[0m  BEGIN
----------------------------------------------

Сравните это с более поздним тестом, который устанавливает SAVEPOINT и ROLLBACK нормально:

--------------------------------------------------------
ProjectStatTest: test_project_stat_matches_expect_values
--------------------------------------------------------
  [1m[36m (0.0ms)[0m  [1mSAVEPOINT active_record_1[0m
  [1m[35m (0.0ms)[0m  SELECT COUNT(*) FROM "projects" WHERE ("projects"."badge_percentage" >= 0)
  [1m[36m (0.0ms)[0m  [1mSELECT COUNT(*) FROM "projects" WHERE ("projects"."badge_percentage" >= 25)[0m
  [1m[35m (0.0ms)[0m  SELECT COUNT(*) FROM "projects" WHERE ("projects"."badge_percentage" >= 50)
  [1m[36m (0.0ms)[0m  [1mSELECT COUNT(*) FROM "projects" WHERE ("projects"."badge_percentage" >= 75)[0m
  [1m[35m (0.0ms)[0m  SELECT COUNT(*) FROM "projects" WHERE ("projects"."badge_percentage" >= 90)
  [1m[36m (0.0ms)[0m  [1mSELECT COUNT(*) FROM "projects" WHERE ("projects"."badge_percentage" >= 100)[0m
  [1m[35m (0.0ms)[0m  SELECT COUNT(*) FROM "projects" WHERE ("projects"."created_at" >= '2015-02-28 12:00:00.000000')
  [1m[36m (0.0ms)[0m  [1mSELECT COUNT(*) FROM "projects" WHERE ("projects"."updated_at" >= '2015-02-28 12:00:00.000000')[0m
  [1m[35mSQL (0.0ms)[0m  INSERT INTO "project_stats" ("created_at", "updated_at", "percent_ge_0", "percent_ge_25", "percent_ge_50", "percent_ge_75", "percent_ge_90", "percent_ge_100", "created_since_yesterday", "updated_since_yesterday") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING "id"  [["created_at", "2015-03-01 12:00:00.000000"], ["updated_at", "2015-03-01 12:00:00.000000"], ["percent_ge_0", 5], ["percent_ge_25", 2], ["percent_ge_50", 2], ["percent_ge_75", 2], ["percent_ge_90", 1], ["percent_ge_100", 1], ["created_since_yesterday", 5], ["updated_since_yesterday", 0]]
  [1m[36m (0.0ms)[0m  [1mRELEASE SAVEPOINT active_record_1[0m
  [1m[35m (0.1ms)[0m  ROLLBACK
  [1m[36m (0.1ms)[0m  [1mBEGIN[0m
--------------------------------------------

Любые идеи, как заставить этот тест установить SAVEPOINT, чтобы ROLLBACK прошел успешно? Я подозреваю, что столкнулся с ошибкой с видеомагнитофоном (о которой я сообщил по адресу https://github.com/vcr/vcr/issues/586 ), но в этом трудно быть уверенным.


person Dan Kohn    schedule 31.05.2016    source источник


Ответы (1)


На первый взгляд кажется, что вы используете транзакционное тестирование с тестами, помеченными js: true — это не работает, потому что при использовании драйверов, поддерживающих JS Capybara, тестируемое приложение загружается в отдельный поток. Каждый поток (тесты и приложение) затем имеет собственное соединение с базой данных, и транзакция, начатая в одном потоке, не видна другому потоку до тех пор, пока она не будет зафиксирована (что может никогда не произойти из-за транзакционного тестирования). Это также означает, что записи, созданные в приложении, не очищаются, поскольку они фактически не были созданы в тестовой транзакции, которая откатывается. Вы, вероятно, захотите взглянуть на что-то вроде DatabaseCleaner для использования с вашими тестами с тегами js: true — смесь https://github.com/DatabaseCleaner/database_cleaner#minitest-example и https://github.com/DatabaseCleaner/database_cleaner#rspec-with-capybara-example — хорошая отправная точка

person Thomas Walpole    schedule 31.05.2016
comment
Спасибо за предложение! Я проверю это. - person Dan Kohn; 01.06.2016