Грешки при валидиране на имейл на RSpec с вложени контексти

Защо получавам тези грешки при проверката? :( Някакви идеи?

Това са моите грешки при проверката -- всичките имейли вече са заети... Моите грешки:

20:33:25 guard.1     | 
20:33:25 guard.1     | Failures:
20:33:25 guard.1     | 
20:33:25 guard.1     |   1) BookmarkImporter should extract all links
20:33:25 guard.1     |      Failure/Error: let(:user) { create(:user) }
20:33:25 guard.1     |      ActiveRecord::RecordInvalid:
20:33:25 guard.1     |        Validation failed: Email has already been taken, Email has already been taken
20:33:25 guard.1     |      # ./spec/lib/bookmark_importer_spec.rb:2:in `block (2 levels) in <top (required)>'
20:33:25 guard.1     |      # ./spec/lib/bookmark_importer_spec.rb:11:in `block (2 levels) in <top (required)>'
20:33:25 guard.1     |      # ./spec/lib/bookmark_importer_spec.rb:14:in `block (2 levels) in <top (required)>'
20:33:25 guard.1     | 
20:33:25 guard.1     |   2) BookmarkImporter should assign bookmarks to the unsorted board of the user
20:33:25 guard.1     |      Failure/Error: let(:user) { create(:user) }
20:33:25 guard.1     |      ActiveRecord::RecordInvalid:
20:33:25 guard.1     |        Validation failed: Email has already been taken, Email has already been taken
20:33:25 guard.1     |      # ./spec/lib/bookmark_importer_spec.rb:2:in `block (2 levels) in <top (required)>'
20:33:25 guard.1     |      # ./spec/lib/bookmark_importer_spec.rb:11:in `block (2 levels) in <top (required)>'
20:33:25 guard.1     |      # ./spec/lib/bookmark_importer_spec.rb:21:in `block (2 levels) in <top (required)>'
20:33:25 guard.1     | 
20:33:25 guard.1     |   3) Board must have a name
20:33:25 guard.1     |      Failure/Error: board = build(:board, :name => "")
20:33:25 guard.1     |      ActiveRecord::RecordInvalid:
20:33:25 guard.1     |        Validation failed: Email has already been taken, Email has already been taken
20:33:25 guard.1     |      # ./spec/models/board_spec.rb:5:in `block (2 levels) in <top (required)>'
20:33:25 guard.1     | 
20:33:25 guard.1     |   4) Board is destroyable by default
20:33:25 guard.1     |      Failure/Error: board = create(:board)
20:33:25 guard.1     |      ActiveRecord::RecordInvalid:
20:33:25 guard.1     |        Validation failed: Email has already been taken, Email has already been taken
20:33:25 guard.1     |      # ./spec/models/board_spec.rb:10:in `block (2 levels) in <top (required)>'
20:33:25 guard.1     | 
20:33:25 guard.1     |   5) Bookmark must have a title
20:33:25 guard.1     |      Failure/Error: bookmark = build(:bookmark, :title => "")
20:33:25 guard.1     |      ActiveRecord::RecordInvalid:
20:33:25 guard.1     |        Validation failed: Email has already been taken, Email has already been taken
20:33:25 guard.1     |      # ./spec/models/bookmark_spec.rb:10:in `block (2 levels) in <top (required)>'
20:33:25 guard.1     | 
20:33:25 guard.1     |   6) Bookmark must have a url
20:33:25 guard.1     |      Failure/Error: bookmark = build(:bookmark, :url => "")
20:33:25 guard.1     |      ActiveRecord::RecordInvalid:
20:33:25 guard.1     |        Validation failed: Email has already been taken, Email has already been taken
20:33:25 guard.1     |      # ./spec/models/bookmark_spec.rb:15:in `block (2 levels) in <top (required)>'
20:33:25 guard.1     | 
20:33:25 guard.1     |   7) User should have a unsorted board
20:33:25 guard.1     |      Failure/Error: let(:user) { create(:user) }
20:33:25 guard.1     |      ActiveRecord::RecordInvalid:
20:33:25 guard.1     |        Validation failed: Email has already been taken, Email has already been taken
20:33:25 guard.1     |      # ./spec/models/user_spec.rb:4:in `block (2 levels) in <top (required)>'
20:33:25 guard.1     |      # ./spec/models/user_spec.rb:7:in `block (2 levels) in <top (required)>'
20:33:25 guard.1     | 
20:33:25 guard.1     |   8) User should not be able to destroy the unsorted board
20:33:25 guard.1     |      Failure/Error: let(:user) { create(:user) }
20:33:25 guard.1     |      ActiveRecord::RecordInvalid:
20:33:25 guard.1     |        Validation failed: Email has already been taken, Email has already been taken
20:33:25 guard.1     |      # ./spec/models/user_spec.rb:4:in `block (2 levels) in <top (required)>'
20:33:25 guard.1     |      # ./spec/models/user_spec.rb:22:in `block (2 levels) in <top (required)>'
20:33:25 guard.1     | 
20:33:25 guard.1     |   9) Bookmarks GET /bookmarks when user is logged in and has no bookmarks, should display a getting started help if the user has no bookmarks
20:33:25 guard.1     |      Failure/Error: page.should have_content("Get started:")
20:33:25 guard.1     |      Capybara::ElementNotFound:
20:33:25 guard.1     |        Unable to find xpath "/html"
20:33:25 guard.1     |      # (eval):2:in `text'
20:33:25 guard.1     |      # ./spec/requests/bookmarks_spec.rb:23:in `block (5 levels) in <top (required)>'
20:33:25 guard.1     | 
20:33:25 guard.1     |   10) Bookmarks GET /bookmarks when user is logged in and has bookmarks, main page should display the unsorted bookmarks board
20:33:25 guard.1     |      Failure/Error: user = create(:user)
20:33:25 guard.1     |      ActiveRecord::RecordInvalid:
20:33:25 guard.1     |        Validation failed: Email has already been taken, Email has already been taken
20:33:25 guard.1     |      # ./spec/requests/bookmarks_spec.rb:14:in `block (4 levels) in <top (required)>'
20:33:25 guard.1     |      # ./spec/requests/bookmarks_spec.rb:35:in `block (5 levels) in <top (required)>'
20:33:25 guard.1     | 
20:33:25 guard.1     |   11) Bookmarks GET /bookmarks when user is logged in and has bookmarks, main page should display all boards
20:33:25 guard.1     |      Failure/Error: user = create(:user)
20:33:25 guard.1     |      ActiveRecord::RecordInvalid:
20:33:25 guard.1     |        Validation failed: Email has already been taken, Email has already been taken
20:33:25 guard.1     |      # ./spec/requests/bookmarks_spec.rb:14:in `block (4 levels) in <top (required)>'
20:33:25 guard.1     |      # ./spec/requests/bookmarks_spec.rb:35:in `block (5 levels) in <top (required)>'
20:33:25 guard.1     | 
20:33:25 guard.1     |   12) Bookmarks GET /bookmarks when user is logged in and has bookmarks, main page should have a way to access account settings
20:33:25 guard.1     |      Failure/Error: user = create(:user)
20:33:25 guard.1     |      ActiveRecord::RecordInvalid:
20:33:25 guard.1     |        Validation failed: Email has already been taken, Email has already been taken
20:33:25 guard.1     |      # ./spec/requests/bookmarks_spec.rb:14:in `block (4 levels) in <top (required)>'
20:33:25 guard.1     |      # ./spec/requests/bookmarks_spec.rb:35:in `block (5 levels) in <top (required)>'
20:33:25 guard.1     | 
20:33:25 guard.1     |   13) Bookmarks GET /bookmarks when user is logged in and has bookmarks, board should display bookmarks inside
20:33:25 guard.1     |      Failure/Error: user = create(:user)
20:33:25 guard.1     |      ActiveRecord::RecordInvalid:
20:33:25 guard.1     |        Validation failed: Email has already been taken, Email has already been taken
20:33:25 guard.1     |      # ./spec/requests/bookmarks_spec.rb:14:in `block (4 levels) in <top (required)>'
20:33:25 guard.1     |      # ./spec/requests/bookmarks_spec.rb:35:in `block (5 levels) in <top (required)>'
20:33:25 guard.1     | 
20:33:25 guard.1     |   14) Bookmarks GET /bookmarks when user is logged in and has bookmarks, board should allow deletion
20:33:25 guard.1     |      Failure/Error: user = create(:user)
20:33:25 guard.1     |      ActiveRecord::RecordInvalid:
20:33:25 guard.1     |        Validation failed: Email has already been taken, Email has already been taken
20:33:25 guard.1     |      # ./spec/requests/bookmarks_spec.rb:14:in `block (4 levels) in <top (required)>'
20:33:25 guard.1     |      # ./spec/requests/bookmarks_spec.rb:35:in `block (5 levels) in <top (required)>'
20:33:25 guard.1     | 
20:33:25 guard.1     |   15) Bookmarks GET /bookmarks when user is logged in and has bookmarks, bookmarks should allow deletion
20:33:25 guard.1     |      Failure/Error: user = create(:user)
20:33:25 guard.1     |      ActiveRecord::RecordInvalid:
20:33:25 guard.1     |        Validation failed: Email has already been taken, Email has already been taken
20:33:25 guard.1     |      # ./spec/requests/bookmarks_spec.rb:14:in `block (4 levels) in <top (required)>'
20:33:25 guard.1     |      # ./spec/requests/bookmarks_spec.rb:35:in `block (5 levels) in <top (required)>'
20:33:25 guard.1     | 
20:33:25 guard.1     |   16) Bookmarks GET /bookmarks when user is logged in and has bookmarks, bookmarks should allow dragging and dropping between boards
20:33:25 guard.1     |      Failure/Error: user = create(:user)
20:33:25 guard.1     |      ActiveRecord::RecordInvalid:
20:33:25 guard.1     |        Validation failed: Email has already been taken, Email has already been taken
20:33:25 guard.1     |      # ./spec/requests/bookmarks_spec.rb:14:in `block (4 levels) in <top (required)>'
20:33:25 guard.1     |      # ./spec/requests/bookmarks_spec.rb:35:in `block (5 levels) in <top (required)>'
20:33:25 guard.1     | 
20:33:25 guard.1     |   17) Bookmarks GET /bookmarks when user is logged in and has bookmarks, archiving should  be able to show archive buttons
20:33:25 guard.1     |      Failure/Error: user = create(:user)
20:33:25 guard.1     |      ActiveRecord::RecordInvalid:
20:33:25 guard.1     |        Validation failed: Email has already been taken, Email has already been taken
20:33:25 guard.1     |      # ./spec/requests/bookmarks_spec.rb:14:in `block (4 levels) in <top (required)>'
20:33:25 guard.1     |      # ./spec/requests/bookmarks_spec.rb:35:in `block (5 levels) in <top (required)>'
20:33:25 guard.1     | 
20:33:26 guard.1     |   18) Bookmarks GET /bookmarks when user is logged in and has bookmarks, archiving should be able to show archived bookmarks
20:33:26 guard.1     |      Failure/Error: user = create(:user)
20:33:26 guard.1     |      ActiveRecord::RecordInvalid:
20:33:26 guard.1     |        Validation failed: Email has already been taken, Email has already been taken
20:33:26 guard.1     |      # ./spec/requests/bookmarks_spec.rb:14:in `block (4 levels) in <top (required)>'
20:33:26 guard.1     |      # ./spec/requests/bookmarks_spec.rb:35:in `block (5 levels) in <top (required)>'
20:33:26 guard.1     | 
20:33:26 guard.1     |   19) Bookmarks GET /bookmarks when user is logged in and has bookmarks, archiving should hide the bookmark when archived
20:33:26 guard.1     |      Failure/Error: user = create(:user)
20:33:26 guard.1     |      ActiveRecord::RecordInvalid:
20:33:26 guard.1     |        Validation failed: Email has already been taken, Email has already been taken
20:33:26 guard.1     |      # ./spec/requests/bookmarks_spec.rb:14:in `block (4 levels) in <top (required)>'
20:33:26 guard.1     |      # ./spec/requests/bookmarks_spec.rb:35:in `block (5 levels) in <top (required)>'
20:33:26 guard.1     | 
20:33:26 guard.1     |   20) Bookmarks GET /bookmarks when user is logged in and has bookmarks, archiving should display the bookmark when unarchived
20:33:26 guard.1     |      Failure/Error: user = create(:user)
20:33:26 guard.1     |      ActiveRecord::RecordInvalid:
20:33:26 guard.1     |        Validation failed: Email has already been taken, Email has already been taken
20:33:26 guard.1     |      # ./spec/requests/bookmarks_spec.rb:14:in `block (4 levels) in <top (required)>'
20:33:26 guard.1     |      # ./spec/requests/bookmarks_spec.rb:35:in `block (5 levels) in <top (required)>'
20:33:26 guard.1     | 
20:33:26 guard.1     |   21) Landing GET / should redirect to bookmarks if user is logged in
20:33:26 guard.1     |      Failure/Error: user = create(:user)
20:33:26 guard.1     |      ActiveRecord::RecordInvalid:
20:33:26 guard.1     |        Validation failed: Email has already been taken, Email has already been taken
20:33:26 guard.1     |      # ./spec/requests/home_spec.rb:9:in `block (3 levels) in <top (required)>'
20:33:26 guard.1     | 

Моята спецификация има редица тестове, като трябва да се отбележи, е let (Което изглежда се изпълнява повече от веднъж) Моята спецификация:

require 'spec_helper'

describe "Bookmarks" do
  describe "GET /bookmarks" do
    context "when user is not logged in" do
      it "should redirect a to home" do
        get bookmarks_path
        response.should redirect_to(root_url)
      end
    end

    context "when user is logged in" do
      let(:user) {
        user = create(:user)
        user.confirm!
        login_as(user, :scope => :user)
        user
      }

      context "and has no bookmarks," do
        it "should display a getting started help if the user has no bookmarks" do
          get bookmarks_path
          page.should have_content("Get started:")
          page.should have_content("Import bookmarks:")
          page.should have_content("Drag the bookmarklet:")
        end
      end

      context "and has bookmarks," do

        before(:all) do
          bookmark_file = File.open( Rails.root.join("spec", "support", "bookmarks.html") )

          # the let you defined above for "user" is available here, but it needs to be in an RSpec block
          BookmarkImporter.new(bookmark_file, user)
        end

        describe "main page" do
          it "should display the unsorted bookmarks board" do
            visit bookmarks_path
            page.should have_content("Unsorted")
          end

          it "should display all boards" do
            pending
          end

          it "should have a way to access account settings" do
            pending
          end

        end

        describe "board" do
          it "should display bookmarks inside" do
            pending
          end

          it "should allow deletion" do
            pending
          end
        end


        describe "bookmarks" do
          it "should allow deletion" do
            pending
          end

          it "should allow dragging and dropping between boards" do
            pending
          end
        end

        describe "archiving" do
          it "should  be able to show archive buttons" do
            pending
          end

          it "should be able to show archived bookmarks" do
            pending
            # archived bookmarks should be hidden 
            # archived bookmarks should be hidden and shown after clicking the link
          end

          it "should hide the bookmark when archived" do
            pending
          end

          it "should display the bookmark when unarchived" do
            pending
          end
        end
      end # end user has bookmarks context
    end #end user logged in context
  end
end

Зададох имейла на потребителя да бъде последователност... така че не трябва да получава грешка при проверка... Моите фабрики:

# Read about factories at http://github.com/thoughtbot/factory_girl

FactoryGirl.define do
  factory :board do
    name "MyString"
    user
  end

  factory :bookmark do
    title "bookmark title"
    url "http://www.google.com"
    type ""
    board
  end

  factory :user do
    sequence(:email) {|n| "person#{n}@example.com" }
    password "password"
    #encrypted_password "$2a$10$qntR5INbkjtRZ.wDEpsNVemyO6oGknq9VyGt.8El4Tg1roHqs7mK2"
  end
end

За всеки случай... Моят помощник по спецификациите:

if(ENV["RUN_COVERAGE"])
  require 'simplecov'
  SimpleCov.start 'rails' do
    add_filter "/spec/"
  end
  puts "Running coverage tool\n"
end
require 'rubygems'
require 'spork'
#uncomment the following line to use spork with the debugger
#require 'spork/ext/ruby-debug'

Spork.prefork do
  # Loading more in this block will cause your tests to run faster. However,
  # if you change any configuration or code from libraries loaded here, you'll
  # need to restart spork for it take effect.

  # This file is copied to spec/ when you run 'rails generate rspec:install'
  ENV["RAILS_ENV"] ||= 'test'
  require File.expand_path("../../config/environment", __FILE__)
  require 'rspec/rails'
  require 'rspec/autorun'
  require 'capybara/rspec'
  require 'capybara/rails'


  RSpec.configure do |config|
    # ## Mock Framework
    config.mock_with :rr

    # If you're not using ActiveRecord, or you'd prefer not to run each of your
    # examples within a transaction, remove the following line or assign false
    # instead of true.
    config.use_transactional_fixtures = true

    # If true, the base class of anonymous controllers will be inferred
    # automatically. This will be the default behavior in future versions of
    # rspec-rails.
    config.infer_base_class_for_anonymous_controllers = false

    config.include Factory::Syntax::Methods

    config.include Warden::Test::Helpers, :type => :request
    Warden.test_mode!
    config.after(:each) { Warden.test_reset! }
  end

end

Spork.each_run do
  # This code will be run each time you run your specs.

  # Reload models on each run
  require 'factory_girl_rails'
  # reload all the models
  Dir["#{Rails.root}/app/models/**/*.rb"].each do |model|
    load model
  end 

  # Reload Factories on each run
  FactoryGirl.factories.clear
  FactoryGirl.find_definitions

  # Requires supporting ruby files with custom matchers and macros, etc,
  # in spec/support/ and its subdirectories.
  Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
end

person ibash    schedule 04.03.2012    source източник


Отговори (2)


before(:all) блокове в RSpec не се изпълняват в рамките на транзакция, затова вашият потребител остава в тестовата база данни след обработката на целия тестов пакет.

Помислете дали да използвате after(:all) блок, където трябва ръчно да почистите подходящи таблици, или да използвате database_cleaner, който можете да конфигурирате да съкращаване на таблици преди тестово изпълнение.

person Nash Bridges    schedule 04.03.2012
comment
Веднъж стартирах database_cleaner и получих много предупреждения за транзакции, които вече се изпълняват... След като го коментирах (и промених before(:all) на before(:each)) всичко работи според очакванията! - person ibash; 04.03.2012

Синтаксисът на FactoryGirl за create е или:

Factory(:user)

or

FactoryGirl.create(:user)

Подозирам, че извикването на create(:user) не прави това, което мислите, че прави. Актуализирайте своя let до:

let(:user) {
    user = Factory(:user)
    user.confirm!
    login_as(user, :scope => :user)
    user
  }

Имайте предвид, че let ще бъде извикан всеки път, когато е необходим за тест.

person nmott    schedule 04.03.2012
comment
Забележете config.include Factory::Syntax::Methods в блока RSpec.configure. - person Nash Bridges; 04.03.2012