rspec / rspec-rails

RSpec for Rails 6+
https://rspec.info
MIT License
5.18k stars 1.04k forks source link

write rspec for rake task #1634

Closed VoTaiTri closed 8 years ago

VoTaiTri commented 8 years ago

i have crawler.rake like that:

namespace :crawler do
  area_names = Dir[Rails.root.join("lib", "crawler", "*.rb")].map do |file_name|
    File.basename(file_name, ".rb")
  end

  area_names.delete("base")

  area_names.each do |area_name|
    task area_name.to_sym => :environment do
      logger = Logger.new("log/crawl_#{area_name}.log")

      area_class = area_name.to_s.camelize
      crawler = "Crawler::#{area_class}".safe_constantize.new logger
      scraper = "Scraper::#{area_class}".safe_constantize.new logger

      parallel_results = crawler.crawl
      mutex = Mutex.new
      current_time = Time.zone.now

      Parallel.each(parallel_results, in_threads: [parallel_results.count, CRAWL_CONFIG["building_thread_max"]].min) do |pages|
        begin
          pages.each do |page|
            available_infos = scraper.scrape page
            mutex.synchronize do
              ActiveRecord::Base.connection_pool.with_connection do
                Availability.insert_each_ground_data available_infos
              end
            end
          end
        rescue => e
          logger.error e.message
          e.backtrace.each{|line| logger.error line}
          raise e
        end
      end

      admin_id = "Scraper::#{area_class}".safe_constantize::ADMINISTRATOR_ID
      ground_ids = CrawlMapping.where(administrator_id: admin_id).pluck(:ground_id)
      Availability.update_no_available_for_not_updated_by_grounds_and_time ground_ids, current_time
    end
  end
end

available_infos here is array set of Enumerator with this source code, i'll stop if i get exception and raise error in rspec, i only need pass input is status of action (my app raise error or no) and check result of these case - change of database here

admin_id = "Scraper::#{area_class}".safe_constantize::ADMINISTRATOR_ID
ground_ids = CrawlMapping.where(administrator_id: admin_id).pluck(:ground_id)
Availability.update_no_available_for_not_updated_by_grounds_and_time ground_ids, current_time

i'll run method update_no_available_for_not_updated_by_grounds_and_time to updata database if every thing return ok and opposite. so how can i fake these cases to test? can you help me write rpsec for it! thanks.

JonRowe commented 8 years ago

Extract this code into a normal module or class, and test it normally. Then call that code from your rake task.

JonRowe commented 8 years ago

e.g:

# lib/crawler.rb
class Crawler
  def self.area_names
    area_names = Dir[Rails.root.join("lib", "crawler", "*.rb")].map do |file_name|
      File.basename(file_name, ".rb")
    end
    area_names.delete("base")
    area_names
  end

  def perform
    logger = Logger.new("log/crawl_#{area_name}.log")

    area_class = area_name.to_s.camelize
    crawler = "Crawler::#{area_class}".safe_constantize.new logger
    scraper = "Scraper::#{area_class}".safe_constantize.new logger

    parallel_results = crawler.crawl
    mutex = Mutex.new
    current_time = Time.zone.now

    Parallel.each(parallel_results, in_threads: [parallel_results.count, CRAWL_CONFIG["building_thread_max"]].min) do |pages|
      begin
        pages.each do |page|
          available_infos = scraper.scrape page
          mutex.synchronize do
            ActiveRecord::Base.connection_pool.with_connection do
              Availability.insert_each_ground_data available_infos
            end
          end
        end
      rescue => e
        logger.error e.message
        e.backtrace.each{|line| logger.error line}
        raise e
      end
    end

    admin_id = "Scraper::#{area_class}".safe_constantize::ADMINISTRATOR_ID
    ground_ids = CrawlMapping.where(administrator_id: admin_id).pluck(:ground_id)
    Availability.update_no_available_for_not_updated_by_grounds_and_time ground_ids, current_time
  end
end

# lib/tasks/crawler.rake
namespace :crawler do
  Crawler.area_names.each do |name|
    task name.to_sym => :environment do
      Crawler.new(name).perform
    end
  end
end  
VoTaiTri commented 8 years ago

@JonRowe thanks you so much