Как проверить область в Rails 3 - PullRequest
24 голосов
/ 11 июня 2010

Каков наилучший способ тестирования областей в Rails 3. В rails 2 я бы сделал что-то вроде:

Rspec:

it 'should have a top_level scope' do
  Category.top_level.proxy_options.should == {:conditions => {:parent_id => nil}}
end

В rails 3 произойдет сбой с "undefinedметод `proxy_options 'для []: ActiveRecord :: Relation" ошибка.

Как люди проверяют, что область задана с правильными параметрами?Я вижу, что вы могли бы исследовать объект arel и, возможно, могли бы рассчитывать на это, но я не уверен, что будет лучшим способом сделать это.

Ответы [ 6 ]

37 голосов
/ 29 марта 2011

Оставляя в стороне вопрос о том, как тестировать ... вот как добиться подобных вещей в Rails3 ...

В Rails3 именованные области отличаются тем, что они просто генерируют реляционные операторы Arel. Но, исследуйте!

Если вы идете в консоль и набираете:

# All the guts of arel!
Category.top_level.arel.inspect

Вы увидите внутренние части Арела. Он используется для построения отношения, но также может быть проанализирован для текущего состояния. Вы заметите публичные методы, такие как #where_clauses и тому подобное.

Тем не менее, сама область имеет много полезных открытых методов для самоанализа, которые упрощают доступ к @arel:

.
# Basic stuff:
=> [:table, :primary_key, :to_sql]

# and these to check-out all parts of your relation:
=> [:includes_values, :eager_load_values, :preload_values,
    :select_values, :group_values, :order_values, :reorder_flag,
    :joins_values, :where_values, :having_values, :limit_value,
    :offset_value, :readonly_value, :create_with_value, :from_value]

# With 'where_values' you can see the whole tree of conditions:
Category.top_level.where_values.first.methods - Object.new.methods
=> [:operator, :operand1, :operand2, :left, :left=, 
    :right, :right=, :not, :or, :and, :to_sql, :each]

# You can see each condition to_sql
Category.top_level.where_values.map(&:to_sql)
=> ["`categories`.`parent_id` IS NULL"]

# More to the point, use #where_values_hash to see rails2-like :conditions hash:
Category.top_level.where_values_hash
=> {"parent_id"=>nil}

Используйте это последнее: #where_values_hash для тестирования областей аналогично #proxy_options в Rails2 ....

27 голосов
/ 30 июня 2010

В идеале ваши юнит-тесты должны рассматривать модели (классы) и их экземпляры как черные ящики. В конце концов, вам важна не реализация, а поведение интерфейса.

Таким образом, вместо того, чтобы проверять, что область реализована особым образом (то есть с определенным набором условий), попробуйте проверить, что он ведет себя правильно - что он возвращает экземпляры, которые он должен, и не возвращает экземпляры, которые он не должен.

describe Category do
  describe ".top_level" do
    it "should return root categories" do
      frameworks = Category.create(:name => "Frameworks")

      Category.top_level.should include(frameworks)
    end

    it "should not return child categories" do
      frameworks = Category.create(:name => "Frameworks")
      rails = Category.create(:name => "Ruby on Rails", :parent => frameworks)

      Category.top_level.should_not include(rails)
    end
  end
end

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

5 голосов
/ 29 марта 2011

Вот как я их проверяю. Подумайте об этом:

  scope :item_type, lambda { |item_type|
    where("game_items.item_type = ?", item_type )
  } 

, который получает все элементы game_items, где item_type равен значению (например, «Оружие»):

    it "should get a list of all possible game weapons if called like GameItem.item_type('Weapon'), with no arguments" do
        Factory(:game_item, :item_type => 'Weapon')
        Factory(:game_item, :item_type => 'Gloves')
        weapons = GameItem.item_type('Weapon')
        weapons.each { |weapon| weapon.item_type.should == 'Weapon' }
    end

Я проверяю, что в массиве оружия хранятся только типы предметов оружия, а не что-то еще, например, перчатки, указанные в спецификации.

3 голосов
/ 05 ноября 2010

Не знаю, помогает ли это или нет, но я ищу решение и наткнулся на этот вопрос.

Я только что сделал это, и оно работает для меня

it { User.nickname('hello').should == User.where(:nickname => 'hello') }
1 голос
/ 19 декабря 2014

Быстро проверяйте пункты объема

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

Вы можете использовать where_values_hash длятест where условия.Вот пример использования Rspec:

it 'should have a top_level scope' do
  Category.top_level.where_values_hash.should eq {"parent_id" => nil}
end

Несмотря на то, что документация очень небольшая и иногда отсутствует, существуют другие методы для других типов условий, например:

order_values ​​

Category.order(:id).order_values
# => [:id]

select_values ​​

Category.select(:id).select_values
# => [:id]

group_values ​​

Category.group(:id).group_values
# => [:id]

Имея_значения

Category.having(:id).having_values
# => [:id]

и т. Д.

Область по умолчанию

Для областей по умолчанию вы должны обрабатывать их немного по-другому.Проверьте этот ответ для лучшего объяснения.

1 голос
/ 25 сентября 2010

FWIW, я согласен с вашим оригинальным методом (Rails 2).Создание моделей только для их тестирования делает ваши тесты way слишком медленными для запуска в непрерывном тестировании, поэтому необходим другой подход.Люблю Rails 3, но определенно упускаю удобство proxy_options!

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