Нокогири соскоб не прошел?

У меня есть следующий код:

  url       = "http://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Dpets&field-keywords="
  data      = Nokogiri::HTML(open(url))

  department   = data.css('#ref_2619534011')

  @department_hash = {}
  department.css('li').drop(1).each do | department |
    department_title = department.css('.refinementLink').text
    department_count = department.css('.narrowValue').text[/[\d,]+/].delete(",").to_i
    @department_hash[:department] ||= {}
    @department_hash[:department]["Pet Supplies"] ||= {}
    @department_hash[:department]["Pet Supplies"][department_title] = department_count
  end 

Итак, когда я делаю это <%= @department_hash %> в шаблоне, я получаю следующее:

{:department=>{"Pet Supplies"=>{"Birds"=>15918, "Cats"=>245418, "Dogs"=>513869, "Fish & Aquatic Pets"=>47182, "Horses"=>14774, "Insects"=>358, "Reptiles & Amphibians"=>5834, "Small Animals"=>19806}}} 

Я создал спецификацию для app.rb (я использую Sinatra):

app_spec.rb:

require File.dirname(__FILE__) + '/app.rb'

describe "Department" do
  it "should scrap correct string" do
    expect(@department_hash).to eq '{:department=>{"Pet Supplies"=>{"Birds"=>15918, "Cats"=>245418, "Dogs"=>513869, "Fish & Aquatic Pets"=>47182, "Horses"=>14774, "Insects"=>358, "Reptiles & Amphibians"=>5834, "Small Animals"=>19806}}}' 
  end
end

Но тест не проходит:

  1) Department should scrap correct string
     Failure/Error: expect(@department_hash).to eq '{:department=>{"Pet Supplies"=>{"Birds"=>15918, "Cats"=>245418, "Dogs"=>513869, "Fish & Aquatic Pets"=>47182, "Horses"=>14774, "Insects"=>358, "Reptiles & Amphibians"=>5834, "Small Animals"=>19806}}}'

       expected: "{:department=>{\"Pet Supplies\"=>{\"Birds\"=>15918, \"Cats\"=>245418, \"Dogs\"=>513869, \"Fish & Aquatic Pets\"=>47182, \"Horses\"=>14774, \"Insects\"=>358, \"Reptiles & Amphibians\"=>5834, \"Small Animals\"=>19806}}}"
            got: nil

       (compared using ==)
     # ./app_spec.rb:5:in `block (2 levels) in <top (required)>'

ИЗМЕНИТЬ:

Я пробовал это:

expect(@department_hash[:department]["Товары для животных"].keys).to eq '["Птицы", "Кошки", "Собаки", "Рыбы и водные животные", "Лошади", "Насекомые", " Рептилии и амфибии», «Мелкие животные»]

Но тест также не проходит:

2) Департаменту следует удалить правильные ключи. Ошибка/ошибка: expect(@department_hash[:department]["Pet Supplies"].keys).to eq '["Птицы", "Кошки", "Собаки", "Рыбы и водные животные". ", "Лошади", "Насекомые", "Рептилии и амфибии", "Мелкие животные"]' NoMethodError: неопределенный метод []' for nil:NilClass # ./app_spec.rb:9:inblock (2 уровня) в '

Что может быть причиной?


person alexchenco    schedule 15.08.2013    source источник


Ответы (1)


@department_hash не определено в рамках теста.

Если взять простой пример:

require 'rspec/autorun'

@department_hash = 2
puts defined?(@department_hash)
#=> "instance-variable"

describe "Department" do
  it "should scrap correct string" do
        puts defined?(@department_hash)
        #=> "" (ie not defined)
    end
end

Вы можете видеть, что @department_hash определено в файле main, но не определено в тесте.

Вам нужно запустить код приложения в рамках теста. Например, переместив код в тест, @department_hash больше не будет нулевым.

require 'rspec/autorun'
require 'nokogiri'
require 'open-uri'

describe "Department" do
  it "should scrap correct string" do
    url       = "http://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Dpets&field-keywords="
    data      = Nokogiri::HTML(open(url))

    department   = data.css('#ref_2619534011')

    @department_hash = {}
    department.css('li').drop(1).each do | department |
      department_title = department.css('.refinementLink').text
      department_count = department.css('.narrowValue').text[/[\d,]+/].delete(",").to_i
      @department_hash[:department] ||= {}
      @department_hash[:department]["Pet Supplies"] ||= {}
      @department_hash[:department]["Pet Supplies"][department_title] = department_count
    end       

    expect(@department_hash).to eq({:department=>{"Pet Supplies"=>{"Birds"=>17556, "Cats"=>245692, "Dogs"=>516246, "Fish & Aquatic Pets"=>47424, "Horses"=>15062, "Insects"=>358, "Reptiles & Amphibians"=>5835, "Small Animals"=>19836}}})
  end
end

Обратите внимание, что ваш тест должен быть eq(hash), а не eq 'hash' (т. е. вы хотите сравнивать хэши, а не строку с хешем.

Обновление — код извлечен в класс:

Перенос кода приложения в тест не идеален, если он предназначен для повторного использования в другом месте. Вместо этого может быть лучше создать метод или класс для кода вашего приложения, а затем вызвать этот код из теста.

require 'rspec/autorun'
require 'nokogiri'
require 'open-uri'

# This class could be placed in your app.rb  
class DepartmentScraper
  def scrape_page()
    url       = "http://www.amazon.com/s/ref=nb_sb_noss?url=search-alias%3Dpets&field-keywords="
    data      = Nokogiri::HTML(open(url))

    department   = data.css('#ref_2619534011')

    @department_hash = {}
    department.css('li').drop(1).each do | department |
      department_title = department.css('.refinementLink').text
      department_count = department.css('.narrowValue').text[/[\d,]+/].delete(",").to_i
      @department_hash[:department] ||= {}
      @department_hash[:department]["Pet Supplies"] ||= {}
      @department_hash[:department]["Pet Supplies"][department_title] = department_count        
    end

    return @department_hash
  end
end

describe "Department" do
  it "should scrap correct string" do
    department_hash = DepartmentScraper.new.scrape_page()

    expect(department_hash).to eq({:department=>{"Pet Supplies"=>{"Birds"=>17556, "Cats"=>245692, "Dogs"=>516246, "Fish & Aquatic Pets"=>47424, "Horses"=>15062, "Insects"=>358, "Reptiles & Amphibians"=>5835, "Small Animals"=>19836}}})
  end
end
person Justin Ko    schedule 15.08.2013
comment
Есть ли способ сделать это, не перемещая весь мой файл в тесте? Вот почему я включил его вверху. - person alexchenco; 15.08.2013
comment
Вы можете извлечь код приложения в методы и/или классы (они могут лежать в вашем файле app.rb). Затем из теста вы вызовете эти методы/классы. К ответу добавлен краткий пример. - person Justin Ko; 15.08.2013
comment
Большое спасибо! Я попробую и скажу вам результаты. - person alexchenco; 15.08.2013
comment
Спасибо, это сработало. Кстати, о чем rspec/autorun часть? Автоматически включать app.rb? - person alexchenco; 16.08.2013
comment
Обычно вы запускаете свои спецификации с помощью такой команды, как rspec your_spec.rb. Требуя rspec/autorun, ваши тесты всегда будут запускаться, когда файл включен, т.е. запускается, когда вы выполняете только ruby your_spec.rb. Вероятно, вам следует сделать это без autorun. Однако для одноразовых сценариев или при использовании чего-то вроде SciTE в качестве редактора я считаю использование autorun более удобным. - person Justin Ko; 16.08.2013