Rspec + Postgresql9.1 Нарушает ненулевое ограничение? - PullRequest
2 голосов
/ 10 декабря 2011

Я использую rails 3.1.3 с postgresql 9.1 и тестирую с помощью Rspec.Это действительно тестовое приложение, основанное на Railstutorial, как часть моего квеста по изучению рельсов.

Моя проблема с тестами spec / models / employee_spec.rb.Пока есть 34 примера, и все они проходят, кроме трех, и они терпят неудачу из-за ненулевого ограничения.Ниже приведены неудачные тесты:

it "should create a new instance given valid attributes" do
    Employee.create!(@attr)   
  end (------ the Employee.create!(@attr) seems to be the problem)

it "should reject duplicate email addresses" do
    # Put an employee with a given email address into the database.
    Employee.create!(@attr) 

    employee_with_duplicate_email = Employee.new(@attr)

    employee_with_duplicate_email.should_not be_valid
  end

it "should reject email addresses identical up to case" do
    upcased_email = @attr[:email].upcase

    Employee.create!(@attr.merge(:email => upcased_email))

    employee_with_upcase_email = Employee.new(@attr)

    employee_with_upcase_email.should_not be_valid
  end

Надеюсь, один из вас, кто прочитает это, если он не слишком длинный, может дать мне несколько советов относительно того, как мне обойти эту проблему.и измените атрибут так, чтобы он принимал нулевые значения, но я хотел бы думать, что rspec должен быть в состоянии справиться с не нулевыми ограничениями)

Ну, спасибо всем и каждому за любую помощь, указатели и рекомендацииВы можете дать.

Том.

Схема таблицы:

# == Schema Information
#
# Table name: employees
#
#  id                        :integer         not null, primary key
#  first_name                :string(255)     not null
#  last_name                 :string(255)     not null
#  mi                        :text
#  marital_status            :string(255)     not null
#  gender                    :string(255)     not null
#  birth_date                :date            default(Sat, 20 Aug 1949), not null
#  hire_date                 :date            not null
#  term_date                 :date
#  primary_position          :string(255)     not null
#  trained_position          :string(255)
#  email                     :string(255)     not null
#  active                    :boolean         default(TRUE), not null
#  address1                  :string(255)     not null
#  address2                  :string(255)
#  city                      :string(255)     not null
#  zip_code                  :string(255)     not null
#  state                     :string(255)     not null
#  emp_home_ph               :string(255)
#  emp_mobile_ph             :string(255)
#  emer_contact_first_name   :string(255)
#  emer_contact_last_name    :string(255)
#  emer_contact_relationship :string(255)
#  emer_contact_ph           :string(255)
#  created_at                :datetime
#  updated_at                :datetime
#

Файл спецификации (~/spec/models/employee_spec.rb):

require 'spec_helper'

describe Employee do

  before(:each) do
     @attr = { :first_name => "Teress", :last_name => "Pottle", :mi => "null",  
    :marital_status => "Single", :gender => "Female", :birth_date => '1987-04-20',  
    :hire_date => '2002-01-01', :term_date => "null", :active => "true",  
    :primary_position => "Job Coach", :trained_position => "null", :email =>   
    "tpottle@example.com", :address1 => "1 First Ave", :address2 => "null", :city =>  
    "Frave", :zip_code => "54806", :state => "WI", :emp_home_ph => "null",  
    :emp_mobile_ph => "null", :emer_contact_first_name => "null",  
    :emer_contact_last_name => "null", :emer_contact_relationship => "null",  
    :emer_contact_ph => "null" }
   end

 it "should create a new instance given valid attributes" do
     Employee.create!(@attr)
 end

 it "should require a first_name" do
    no_first_name = Employee.new(@attr.merge(:first_name => ""))
    no_first_name.should_not be_valid
 end

 it "should reject first_name that is too long" do
   long_name = "a" * 26
   long_first_name = Employee.new(@attr.merge(:first_name => long_name))
   long_first_name.should_not be_valid
 end

 it "should require a last_name" do
   no_last_name = Employee.new(@attr.merge(:last_name => ""))
   no_last_name.should_not be_valid
 end

 it "should reject a last_name that is too long" do
   long_name = "a" * 26
   long_last_name = Employee.new(@attr.merge(:last_name => long_name))
   long_last_name.should_not be_valid
 end

 it "should require a marital_status" do
   no_marital_status = Employee.new(@attr.merge(:marital_status => ""))
   no_marital_status.should_not be_valid
 end

 it "should require a gender" do
   no_gender = Employee.new(@attr.merge(:gender => ""))
   no_gender.should_not be_valid
 end

 it "should require a birth_date" do
   no_birth_date = Employee.new(@attr.merge(:birth_date => ""))
   no_birth_date.should_not be_valid
 end

 it "should require a hire_date" do
   no_hire_date = Employee.new(@attr.merge(:hire_date => ""))
   no_hire_date.should_not be_valid
 end

 it "should require a primary_position" do
    no_primary_position = Employee.new(@attr.merge(:primary_position => ""))
    no_primary_position.should_not be_valid
 end

 it "should require a email" do
    no_email = Employee.new(@attr.merge(:email => ""))
    no_email.should_not be_valid
 end

 it "should require an 'active' setting" do
    no_active_setting = Employee.new(@attr.merge(:active => ""))
    no_active_setting.should_not be_valid
 end

it "should require an address1" do
    no_address1 = Employee.new(@attr.merge(:address1 => ""))
    no_address1.should_not be_valid
end

it "should require a city" do
   no_city = Employee.new(@attr.merge(:city => ""))
   no_city.should_not be_valid
end

it "should require a zip_code" do
   no_zip_code = Employee.new(@attr.merge(:zip_code => ""))
   no_zip_code.should_not be_valid
end

it "should require a state" do
   no_state = Employee.new(@attr.merge(:state => ""))
   no_state.should_not be_valid
end

it "should accept valid email addresses" do
   addresses = %w[user@foo.com THE_USER@foo.bar.org first.last@foo.jp]
     addresses.each do |address|
       valid_email_employee = Employee.new(@attr.merge(:email => address))
       valid_email_employee.should be_valid
    end
end

it "should reject invalid email addresses" do
   addresses = %w[user@foo,com user_at_foo.org example.user@foo.]
      addresses.each do |address|
         invalid_email_employee = Employee.new(@attr.merge(:email => address))
         invalid_email_employee.should_not be_valid
      end
end

it "should reject duplicate email addresses" do
   # Put an employee with a given email address into the database.
   Employee.create!(@attr)
   employee_with_duplicate_email = Employee.new(@attr)
   employee_with_duplicate_email.should_not be_valid
end

it "should reject email addresses identical up to case" do
  upcased_email = @attr[:email].upcase
  Employee.create!(@attr.merge(:email => upcased_email))
  employee_with_upcase_email = Employee.new(@attr)
  employee_with_upcase_email.should_not be_valid
end
end

Класс сотрудника (~/app/models/employee.rb):

 class Employee < ActiveRecord::Base

  attr_accessor :first_name, :last_name, :mi, :marital_status, :gender, :birth_date,  
 :hire_date, :term_date, :primary_position, :trained_position, :email, :active,  
 :address1, :address2, :city, :zip_code, :state, :emp_home_ph, :emp_mobile_ph,  
 :emer_contact_first_name, :emer_contact_last_name, :emer_contact_relationship, 
 :emer_contact_ph

 email_regex = /([\w+.]+)@[a-z0-9\-.]+\.[a-z]+/i
 date_regex = /^[0-9]{4}[-][0-9]{2}[-][0-9]{2}$/

 validates(:marital_status, :gender, :primary_position, :active, :address1, :city, 
 :zip_code, :state, :presence => true)
 validates(:first_name, :last_name, :presence => true, 
        :length => { :maximum => 25 })
 validates(:birth_date, :hire_date, :presence => true,
        :format => { :with => date_regex })
 validates(:email, :presence => true,
        :format => { :with => email_regex },
        :uniqueness => { :case_sensitive => false})
end

Что происходит, когда я запускаю rspec:

loading autotest/rails_rspec2
/home/tom/.rvm/rubies/ruby-1.9.3-p0/bin/ruby -rrubygems -S /home/tom/.rvm/gems  
/ruby-1.9.3-p0@latest/gems/rspec-core-2.7.1/exe/rspec --tty  
'/home/tom/rails_projects/tracking /spec/controllers/employees_controller_spec.rb'   
'/home/tom/rails_projects/tracking/spec/controllers/pages_controller_spec.rb' '/home  
/tom/rails_projects/tracking/spec/models/employee_spec.rb' '/home/tom/rails_projects  
/tracking/spec/requests/layout_links_spec.rb'
........F.................FF......

Failures:

1) Employee should create a new instance given valid attributes
 Failure/Error: Employee.create!(@attr)
 ActiveRecord::StatementInvalid:
   PGError: ERROR:  null value in column "first_name" violates not-null constraint
   : INSERT INTO "employees" ("active", "address1", "address2", "birth_date", 
   "city", "created_at", "email", "emer_contact_first_name", 
   "emer_contact_last_name",  "emer_contact_ph", "emer_contact_relationship",
   "emp_home_ph", "emp_mobile_ph", "first_name", "gender", "hire_date", "last_name",
   "marital_status", "mi", "primary_position", "state", "term_date", 
   "trained_position", "updated_at", "zip_code")
    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) RETURNING "id"
    # ./spec/models/employee_spec.rb:42:in `block (2 levels) in <top (required)>'

2) Employee should reject duplicate email addresses
 Failure/Error: Employee.create!(@attr)
 ActiveRecord::StatementInvalid:
   PGError: ERROR:  null value in column "first_name" violates not-null constraint
   : INSERT INTO "employees" ("active", "address1", "address2", "birth_date", "city",
   "created_at", "email", "emer_contact_first_name", "emer_contact_last_name",
  "emer_contact_ph", "emer_contact_relationship", "emp_home_ph", "emp_mobile_ph",
  "first_name", "gender", "hire_date", "last_name", "marital_status", "mi",
  "primary_position", "state", "term_date", "trained_position", "updated_at", 
  "zip_code") 
   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) RETURNING "id"
   # ./spec/models/employee_spec.rb:140:in `block (2 levels) in <top (required)>'

3) Employee should reject email addresses identical up to case
 Failure/Error: Employee.create!(@attr.merge(:email => upcased_email))
 ActiveRecord::StatementInvalid:
   PGError: ERROR:  null value in column "first_name" violates not-null constraint
   : INSERT INTO "employees" ("active", "address1", "address2", "birth_date", "city",  
   "created_at", "email", "emer_contact_first_name", "emer_contact_last_name",
   "emer_contact_ph", "emer_contact_relationship", "emp_home_ph", "emp_mobile_ph",
   "first_name", "gender", "hire_date", "last_name", "marital_status", "mi",
   "primary_position", "state", "term_date", "trained_position", "updated_at",
   "zip_code") 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) RETURNING "id"
   # ./spec/models/employee_spec.rb:147:in `block (2 levels) in <top (required)>'

 Finished in 19.24 seconds
 34 examples, 3 failures

 Failed examples:

rspec ./spec/models/employee_spec.rb:41 # Employee should create a new instance given
valid attributes
rspec ./spec/models/employee_spec.rb:138 # Employee should reject duplicate email
addresses
rspec ./spec/models/employee_spec.rb:145 # Employee should reject email addresses
identical up to case

1 Ответ

2 голосов
/ 11 декабря 2011

Ваша проблема не в ваших тестах, ваша проблема в вашем классе Employee. Ваш класс начинается с этого:

class Employee < ActiveRecord::Base

  attr_accessor :first_name, :last_name, :mi, :marital_status, :gender, :birth_date,  
   :hire_date, :term_date, :primary_position, :trained_position, :email, :active,  
   :address1, :address2, :city, :zip_code, :state, :emp_home_ph, :emp_mobile_ph,  
   :emer_contact_first_name, :emer_contact_last_name, :emer_contact_relationship, 
   :emer_contact_ph

но вам не нужно или не хотите использовать attr_accessor здесь. Обычные атрибуты объекта (которые создает attr_accessor) не совпадают с атрибутами ActiveRecord. ActiveRecord проверит структуру таблицы и создаст собственное внутреннее хранилище для поддерживаемых базой данных атрибутов и набор методов доступа и мутатора для этих атрибутов; внутренне ActiveRecord будет использовать эти методы доступа, чтобы увидеть, что находится в объекте. Затем вы используете attr_accessor для объявления столбцов как атрибутов объекта, а attr_accessor создает свои собственные методы доступа и мутатора, которые заменяют ActiveRecord. В результате object.first_name будет искать переменную экземпляра @first_name в object, но такого не будет, Employee.create установит first_name в атрибутах ActiveRecord, не @first_name значение экземпляра.

Решение состоит в том, чтобы избавиться от оператора attr_accessor в вашем классе. Затем прочитайте Rails Guides параллельно с вашим уроком.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...