ruby 2.1 rails 4 sunspot solr 测试在套件中失败但单独通过 [英] ruby 2.1 rails 4 sunspot solr tests fail in suite but pass individually
问题描述
我的团队已经被这个问题难住了一段时间,并且不知道下一步该去哪里尝试.下面的规范在单独运行时可以正常工作,但是,当我们通过 bundle exec ./bin/rspec spec
在我们的套件中运行它时,这两个测试每次都会失败:
My team has been stumped on this issue for some time now and are at a loss as to where to try next. The spec below works correctly when run individually, however, when we run this in our suite via bundle exec ./bin/rspec spec
these two tests fail every single time:
- GET/external-products/:id/deals
- GET/external-products/search/deals
我们尝试了多种不同的方法来解决这个问题,我开始怀疑上述规范之外的其他内容.所以我必须求助于堆栈之神,并恳求那里有人有更好的方法甚至更好的问题来提出这个问题.
We have tried numerous different ways to approach this issue and I am starting to suspect something else outside of the said spec. SO I have to turn to the Stack gods, and plea that someone out there has a better approach or even a better question to ask this problem.
Rspec 错误:
8) Retailigence Products and Locations GET /external-products/search/deals Search a given region for related deals by query string
Failure/Error: expect(response_body).to have_json_type(Integer).at_path('deals/0/id')
JsonSpec::MissingPath:
Missing JSON path "deals/0/id"
# ./spec/features/external_products_spec.rb:151:in `block (3 levels) in <top (required)>'
# -e:1:in `<main>'
9) Retailigence Products and Locations GET /external-products/:id/deals Search a given region for deals related to a particular product
Failure/Error: expect(response_body).to have_json_type(Integer).at_path('deals/0/id')
JsonSpec::MissingPath:
Missing JSON path "deals/0/id"
# ./spec/features/external_products_spec.rb:105:in `block (3 levels) in <top (required)>'
# -e:1:in `<main>'
这是我们的 spec_helper.rb:
Here is our spec_helper.rb:
require 'rubygems'
ENV['RAILS_ENV'] ||= 'test'
require File.expand_path('../../config/environment', __FILE__)
require 'rspec/rails'
require 'email_spec'
require 'pry'
require 'rspec_api_documentation/dsl'
require 'sunspot/rails/spec_helper'
require 'sunspot_test/rspec'
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join('spec/concerns/**/*.rb')].each { |f| require f }
Dir[Rails.root.join('spec/support/**/*.rb')].each { |f| require f }
# Checks for pending migrations before tests are run.
# If you are not using ActiveRecord, you can remove this line.
ActiveRecord::Migration.maintain_test_schema!
# Model specs: type: :model
# Controller specs: type: :controller
# Request specs: type: :request
# Feature specs: type: :feature
# View specs: type: :view
# Helper specs: type: :helper
# Mailer specs: type: :mailer
# Routing specs: type: :routing
RSpec.configure do |config|
config.order = 'random'
config.seed = srand % 0xFFFF
config.infer_spec_type_from_file_location!
config.use_transactional_fixtures = false
config.infer_base_class_for_anonymous_controllers = false
config.before(:each) { GC.disable }
config.after(:each) { GC.enable }
config.include FactoryGirl::Syntax::Methods
config.include JsonSpec::Helpers
config.include Stubs
config.include LoginHelper
config.include SolrSpecHelper
config.include SunspotMatchers
config.include Devise::TestHelpers, type: :controller
config.before do
Sunspot.session = SunspotMatchers::SunspotSessionSpy.new(Sunspot.session)
end
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
end
RspecApiDocumentation.configure do |config|
config.format = :json
end
功能/external_product_service_spec.rb
The features/external_product_service_spec.rb
resource 'Retailigence Products and Locations', type: :feature, api: true, slow: true, sunspot: true do
before(:all) do
log_in_as_client!
end
let(:id) { '7c381d47-d251-457a-a2d2-930c8993a5fa' }
let(:lat) { 39.74585 }
let(:long) { -104.998929 }
let(:q) { 'whiteboard cleaner' }
get '/external-products/:id' do
parameter :id, 'The external id to search', required: true
parameter :lat, 'The latitude to search', required: true
parameter :long, 'The longitude to search', required: true
parameter :radius, 'The radius, in miles, to search'
example 'Search a given region for products matching a given external product id' do
do_request user_email: @user.email, user_token: @token, timestamp: @timestamp
expect(response_body).to have_json_type(Array).at_path('external_products')
expect(response_body).to have_json_type(String).at_path('external_products/0/id')
expect(response_body).to have_json_type(String).at_path('external_products/0/name')
expect(response_body).to have_json_type(String).at_path('external_products/0/seo_slug')
expect(response_body).to have_json_type(String).at_path('external_products/0/description')
expect(response_body).to have_json_type(Array).at_path('external_products/0/images')
expect(response_body).to have_json_type(String).at_path('external_products/0/price')
end
end
get '/external-products/:id/external-stores' do
parameter :id, 'The external id to search', required: true
parameter :lat, 'The latitude to search', required: true
parameter :long, 'The longitude to search', required: true
parameter :radius, 'The radius, in miles, to search'
example 'Search a given region for stores which have the product matching a given external product id' do
do_request user_email: @user.email, user_token: @token, timestamp: @timestamp
expect(response_body).to have_json_type(Array).at_path('external_stores')
expect(response_body).to have_json_type(String).at_path('external_stores/0/id')
expect(response_body).to have_json_type(String).at_path('external_stores/0/name')
expect(response_body).to have_json_type(String).at_path('external_stores/0/store_logo')
expect(response_body).to have_json_type(Float).at_path('external_stores/0/longitude')
expect(response_body).to have_json_type(Float).at_path('external_stores/0/latitude')
expect(response_body).to have_json_type(Float).at_path('external_stores/0/distance')
expect(response_body).to have_json_type(String).at_path('external_stores/0/city')
expect(response_body).to have_json_type(String).at_path('external_stores/0/address')
expect(response_body).to have_json_type(String).at_path('external_stores/0/zip')
expect(response_body).to have_json_type(String).at_path('external_stores/0/state')
expect(response_body).to have_json_type(String).at_path('external_stores/0/phone_number')
end
end
get '/external-products/search' do
parameter :q, 'The query string to search', required: true
parameter :lat, 'The latitude to search', required: true
parameter :long, 'The longitude to search', required: true
parameter :radius, 'The radius, in miles, to search'
example 'Search a given region for products by query string' do
do_request q: q, user_email: @user.email, user_token: @token, timestamp: @timestamp
expect(response_body).to have_json_type(Array).at_path('external_products')
expect(response_body).to have_json_type(String).at_path('external_products/0/id')
expect(response_body).to have_json_type(String).at_path('external_products/0/name')
expect(response_body).to have_json_type(String).at_path('external_products/0/seo_slug')
expect(response_body).to have_json_type(String).at_path('external_products/0/description')
expect(response_body).to have_json_type(Array).at_path('external_products/0/images')
expect(response_body).to have_json_type(String).at_path('external_products/0/price')
end
end
get '/external-products/:id/deals' do
before(:each) do
solr_setup
store.location.save
store.location.reload
store.location.index!
end
let(:retailer) { create :retailer }
let!(:deal) { create :deal, retailer_id: retailer.id }
let!(:store) do
create :store, retailer_id: retailer.id,
location: (create :location, latitude: lat, longitude: long)
end
let!(:retailigence_retailer) do
create :retailigence_retailers_retailer, retailer_id: retailer.id,
retailigence_retailer_id: '39bfd9a5-f979-4ef1-816b-f9a38093494a'
end
let!(:content_location) do
create :content_location, store_id: store.id,
locatable_id: deal.id, locatable_type: 'Deal'
end
parameter :id, 'The external id to search', required: true
parameter :lat, 'The latitude to search', required: true
parameter :long, 'The longitude to search', required: true
parameter :radius, 'The radius, in miles, to search'
example 'Search a given region for deals related to a particular product' do
do_request id: id, user_email: @user.email, user_token: @token, timestamp: @timestamp
expect(response_body).to have_json_type(Array).at_path('deals')
expect(response_body).to have_json_type(Integer).at_path('deals/0/id')
expect(response_body).to have_json_type(Integer).at_path('deals/0/retailer_id')
expect(response_body).to have_json_type(String).at_path('deals/0/title')
expect(response_body).to have_json_type(String).at_path('deals/0/seo_slug')
expect(response_body).to have_json_type(String).at_path('deals/0/name')
expect(response_body).to have_json_type(String).at_path('deals/0/sort_name')
expect(response_body).to have_json_type(String).at_path('deals/0/description')
expect(response_body).to have_json_type(:boolean).at_path('deals/0/is_local')
expect(response_body).to have_json_type(:boolean).at_path('deals/0/is_featured')
expect(response_body).to have_json_type(Array).at_path('images')
end
end
get '/external-products/search/deals' do
before(:each) do
solr_setup
store.location.save
store.location.reload
store.location.index!
end
let(:retailer) { create :retailer }
let!(:deal) { create :deal, retailer_id: retailer.id }
let!(:store) do
create :store, retailer_id: retailer.id,
location: (create :location, latitude: lat, longitude: long)
end
let!(:retailigence_retailer) do
create :retailigence_retailers_retailer, retailer_id: retailer.id,
retailigence_retailer_id: 'eea1722b-ac89-4cce-95ec-26c2414646d7'
end
let!(:content_location) do
create :content_location, store_id: store.id,
locatable_id: deal.id, locatable_type: 'Deal'
end
parameter :q, 'The query string to search', required: true
parameter :lat, 'The latitude to search', required: true
parameter :long, 'The longitude to search', required: true
parameter :radius, 'The radius, in miles, to search'
example 'Search a given region for related deals by query string' do
do_request q: q, lat: lat, long: long,
user_email: @user.email, user_token: @token, timestamp: @timestamp
expect(response_body).to have_json_type(Array).at_path('deals')
expect(response_body).to have_json_type(Integer).at_path('deals/0/id')
expect(response_body).to have_json_type(Integer).at_path('deals/0/retailer_id')
expect(response_body).to have_json_type(String).at_path('deals/0/title')
expect(response_body).to have_json_type(String).at_path('deals/0/seo_slug')
expect(response_body).to have_json_type(String).at_path('deals/0/name')
expect(response_body).to have_json_type(String).at_path('deals/0/sort_name')
expect(response_body).to have_json_type(String).at_path('deals/0/description')
expect(response_body).to have_json_type(:boolean).at_path('deals/0/is_local')
expect(response_body).to have_json_type(:boolean).at_path('deals/0/is_featured')
expect(response_body).to have_json_type(Array).at_path('images')
end
end
end
retailigence_service.rb:
The retailigence_service.rb:
class RetailigenceService
NEGATIVE_KEYWORDS = 'AND !DVD AND !CD AND !"compact disc"'
MAX_QUERY_TIME = 5000
attr_accessor :products, :locations, :params
def self.products(params = {})
fetch(params).products
end
def self.locations(params = {})
fetch_locations(params).locations
end
def self.fetch(params = {})
service = new
service.fetch(params)
service
end
def self.fetch_locations(params = {})
service = new
service.fetch_locations(params)
service
end
def fetch(params = {})
@params = { offset: 0, limit: 25 }.merge(params)
@params.symbolize_keys!
search_result = Retailigence::Product.search(search_params)
@products = search_result.results
build_products
rescue Retailigence::NoResults
@products = []
rescue Retailigence::APIException
@products = []
end
def fetch_locations(params = {})
@params = { offset: 0, limit: 25 }.merge(params)
@params.symbolize_keys!
Rails.logger.debug "[SENDING] #{location_params}"
search_result = Retailigence::Location.search(location_params)
@locations = search_result.results.map { |retailer| retailer.locations }.flatten
build_locations
rescue Retailigence::NoResults
@locations = []
rescue Retailigence::APIException
@locations = []
end
private
def keywords
keywords = @params[:keywords] || ''
keywords << ' ' << NEGATIVE_KEYWORDS
keywords.gsub(/^\ AND\ /, '')
end
def page_size
@params[:limit]
end
def page
(@params[:offset] / @params[:limit]) + 1
end
def location_params
{
userlocation: @params[:userlocation],
requestorid: RETAILIGENCE_REQUESTOR_ID,
productid: @params[:productid],
pagesize: page_size,
page: page,
maxquerytime: MAX_QUERY_TIME,
excludeadultcontent: true
}
end
def search_params
search_params = {
userlocation: @params[:userlocation],
requestorid: RETAILIGENCE_REQUESTOR_ID,
pagesize: page_size, page: page,
maxquerytime: MAX_QUERY_TIME,
excludeadultcontent: true
}
search_params[:keywords] = keywords unless @params[:product_id]
search_params[:productid] = @params[:product_id] if @params[:product_id]
search_params
end
def format_price_prefix(prefix)
prefix = '$' if prefix == 'USD'
prefix
end
def build_products
@products.map! do |p|
p.images ||= []
p.description_long ||= ''
RetailigenceProduct.new(
id: p.id, name: p.name, seo_slug: p.name.slugify,
description: p.description_long,
images: p.images.map { |img| img.link },
price: "#{format_price_prefix p.msrp_currency}#{p.price}",
retailigence_retailer_id: p.location.retailer.id)
end
end
def build_locations
@locations.map! do |l|
RetailigenceLocation.new(
id: l.id, name: l.retailer.name,
latitude: l.latitude, longitude: l.longitude,
phone_number: l.phone, address: l.address.address1,
city: l.address.city, state: l.address.state,
zip: l.address.postal, store_logo: l.retailer.logo,
distance: l.distance.distance)
end
end
end
这是我们在 support/sunspot.rb 中的 Sunspot 设置:
Here is our Sunspot setup in support/sunspot.rb:
$original_sunspot_session = Sunspot.session
Sunspot.session = Sunspot::Rails::StubSessionProxy.new($original_sunspot_session)
module SolrSpecHelper
def solr_setup
unless $sunspot
$sunspot = Sunspot::Rails::Server.new
pid = fork do
STDERR.reopen('/dev/null')
STDOUT.reopen('/dev/null')
$sunspot.run
end
# shut down the Solr server
at_exit { Process.kill('TERM', pid) }
# wait for solr to start
sleep 5
end
Sunspot.session = $original_sunspot_session
end
end
推荐答案
我以前没有遇到过这个确切的问题,但是我有两个建议/建议,可能对将来遇到它的人有所帮助.如果您认为成功或不成功,请发表评论.
I haven't encountered this exact problem before, however I have two suggestions/recommendations that may be helpful to those who encounter it in the future. Please comment if you find it successful or unsuccessful.
虽然不太理想,但您可以从 Gemfile 的测试组中删除spring" gem(如果它已包含在那里).
While less than ideal you can remove the 'spring' gem from your test group of your Gemfile if it has been included there.
尝试运行 bundle exec spring binstub --all
以弹簧化"bin/
目录中的可执行文件.
Try running bundle exec spring binstub --all
to "springify" the executables in your bin/
directory.
这篇关于ruby 2.1 rails 4 sunspot solr 测试在套件中失败但单独通过的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!