Pertanyaan ruby 2.1 rel 4 tes solst sunspot gagal di suite tetapi lulus secara individual


Tim saya telah terhenti pada masalah ini untuk beberapa waktu sekarang dan bingung ke mana harus mencoba selanjutnya. Spec di bawah ini berfungsi dengan benar ketika dijalankan secara individual, namun, ketika kami menjalankan ini di suite kami melalui bundle exec ./bin/rspec spec dua tes ini gagal setiap saat:

  • DAPATKAN / produk eksternal /: id / transaksi
  • DAPATKAN / produk eksternal / pencarian / penawaran

Kami telah mencoba berbagai cara untuk mendekati masalah ini dan saya mulai mencurigai sesuatu yang lain di luar spesifikasi tersebut. Jadi saya harus beralih ke dewa Stack, dan memohon bahwa seseorang di luar sana memiliki pendekatan yang lebih baik atau bahkan pertanyaan yang lebih baik untuk menanyakan masalah ini.

Kesalahan 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>'

Berikut spec_helper.rb kami:

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

Fitur / 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

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

Berikut ini pengaturan Sunspot kami di 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

4
2017-12-18 19:23


asal


Jawaban:


Saya belum pernah menemukan masalah pasti ini sebelumnya, namun saya memiliki dua saran / rekomendasi yang mungkin berguna bagi mereka yang menemukannya di masa depan. Berikan komentar jika Anda berhasil atau tidak berhasil.

  1. Meskipun kurang ideal, Anda dapat menghapus permata 'musim semi' dari grup uji Gemfile Anda jika telah disertakan di sana.

  2. Coba jalankan bundle exec spring binstub --all untuk "memurnikan" file yang dapat dieksekusi di komputer Anda bin/ direktori.


0
2018-05-24 00:09