Noosfero/noosfero

View on GitHub
lib/tasks/plugins_tests.rake

Summary

Maintainability
Test Coverage
$broken_plugins = %w[
  anti_spam
  bsc
  environment_notification
  comment_classification
  comment_group
  ldap
  solr
  variables
]

@all_plugins = Dir.glob("plugins/*").map { |f| File.basename(f) } - ["template"]
@all_plugins.sort!

@all_tasks = [:units, :api, :functionals, :integration, :cucumber, :selenium]

def enabled_plugins
  Dir.glob("{baseplugins,config/plugins}/*").map { |f| File.basename(f) } - ["README"]
end

@original_enabled_plugins = enabled_plugins

def disabled_plugins
  @all_plugins - enabled_plugins
end

def enable_plugins(plugins)
  plugins = Array(plugins)
  command = ["./script/noosfero-plugins", "-q", "enable", *plugins]
  puts plugins.join(" ")
  Bundler.clean_system *command
end

def disable_plugins(plugins = "*")
  if plugins == "*"
    sh "./script/noosfero-plugins", "-q", "disableall"
  else
    plugins = Array(plugins)
    sh "./script/noosfero-plugins", "-q", "disable", *plugins
  end
end

def rollback_plugins_state
  puts
  puts "==> Rolling back plugins to their original states..."
  disable_plugins
  enable_plugins(@original_enabled_plugins)
end

task "db:test:plugins:prepare" do
  if Dir.glob("config/plugins/*/db/migrate/*.rb").empty?
    puts "I: skipping database setup, enabled plugins have no migrations"
  else
    Rake::Task["db:test:prepare"].execute
    sh "rake db:migrate RAILS_ENV=test SCHEMA=/dev/null"
  end
end

def plugin_name(plugin)
  "#{plugin} plugin"
end

def plugin_enabled?(plugin)
  File.exist?(File.join("config", "plugins", plugin)) || File.exist?(File.join("baseplugins", plugin))
end

def plugin_disabled_warning(plugin)
  puts "E: you should enable #{plugin} plugin before running it's tests!"
end

def task2ext(task)
  (task == :selenium || task == :cucumber) ? :feature : :rb
end

def task2profile(task, plugin)
  if task == :cucumber
    return plugin
  elsif task == :selenium
    return "#{plugin}_selenium"
  else
    return "default"
  end
end

def filename2plugin(filename)
  filename.split("/")[1]
end

def task2folder(task)
  result = case task.to_sym
           when :units
             :unit
           when :api
             :api
           when :functionals
             :functional
           when :integration
             :integration
           when :cucumber
             :features
           when :selenium
             :features
  end

  return result
end

def run_test(name, files)
  files = Array(files)
  plugin = filename2plugin(files.first)
  if name == :cucumber || name == :selenium
    run_cucumber task2profile(name, plugin), files
  else
    run_minitest files
  end
end

def run_minitest(files)
  files = files.map { |f| File.join(Rails.root, f) }
  sh "ruby", "-Itest", "-e ARGV.each{|f| require f}", *files
end

def run_cucumber(profile, files)
  sh "ruby", "-S", "cucumber", "--profile", profile.to_s, "--format", ENV["CUCUMBER_FORMAT"] || "progress", *files
end

def custom_run(name, files, run = :all)
  case run
  when :all
    run_test name, files
  when :individually
    files.each do |file|
      run_test name, file
    end
  when :by_plugin
  end
end

def run_tests(name, plugins, run = :all)
  plugins = Array(plugins)
  if name == :cucumber || name == :selenium
    glob =  "plugins/{#{plugins.join(',')}}/#{task2folder(name)}/**/*.#{task2ext(name)}"
  else
    glob =  "plugins/{#{plugins.join(',')}}/test/#{task2folder(name)}/**/*.#{task2ext(name)}"
  end
  files = Dir.glob(glob)
  if files.empty?
    puts "I: no tests to run #{name}"
  else
    custom_run(name, files, run)
  end
end

def test_sequence(plugins, tasks)
  failed = {}
  disable_plugins
  plugins = @all_plugins if plugins == "*"
  plugins = Array(plugins)
  tasks = Array(tasks)
  plugins.each do |plugin|
    failed[plugin] = []
    enable_plugins(plugin)
    next if !plugin_enabled?(plugin)

    begin
      Rake::Task["db:test:plugins:prepare"].execute
    rescue Exception => ex
      failed[plugin] << :migration
    end
    tasks.each do |task|
      begin
        run_tests(task, plugin)
      rescue Exception => ex
        puts ex
        failed[plugin] << task
      end
    end
    disable_plugins
  end
  fail_flag = false
  failed.each do |plugin, tasks|
    unless tasks.empty?
      puts "Tests failed on #{plugin} plugin: #{tasks.join(', ')}"
      fail_flag = true
    end
  end
  rollback_plugins_state
  yield(failed) if block_given?
  fail "There are broken tests to be fixed!" if fail_flag
end

def plugin_test_task(plugin, task, run = :all)
  desc "Run #{task} tests for #{plugin_name(plugin)}"
  task task do
    test_sequence(plugin, task)
  end
end

namespace :test do
  namespace :noosfero_plugins do
    @all_plugins.each do |plugin|
      namespace plugin do
        @all_tasks.each do |taskname|
          plugin_test_task plugin, taskname
        end
      end

      desc "Run all tests for #{plugin_name(plugin)}"
      task plugin do
        test_sequence([plugin], @all_tasks)
      end
    end

    @all_tasks.each do |taskname|
      desc "Run #{taskname} tests for all plugins"
      task taskname do
        test_sequence(@all_plugins - $broken_plugins, taskname)
      end
    end
  end

  desc "Run all tests for all plugins"
  task :noosfero_plugins do
    plugins    = @all_plugins - $broken_plugins
    if slice   = ENV["SLICE"]
      sel, size = slice.split "/"
      size     = (plugins.size / size.to_f).ceil
      plugins  = plugins.each_slice(size).to_a[sel.to_i - 1]
    end

    test_sequence plugins, @all_tasks do |failed|
      plugins_status_report(failed)
    end
  end
end

def plugins_status_report(failed)
  w = @all_plugins.map { |s| s.size }.max

  puts
  printf ("=" * (w + 21)) + "\n"
  puts "Plugins status report"
  printf ("=" * (w + 21)) + "\n"
  printf "%-#{w}s %s\n", "Plugin", "Status"
  printf ("-" * w) + " " + ("-" * 20) + "\n"

  @all_plugins.each do |plugin|
    if $broken_plugins.include?(plugin)
      status = "BROKEN"
    elsif failed[plugin].nil?
      status = "SKIP"
    elsif failed[plugin].empty?
      status = "PASS"
    else
      status = "FAIL: #{failed[plugin].join(', ')}"
    end
    printf "%-#{w}s %s\n", plugin, status
  end
  printf ("=" * (w + 21)) + "\n"
  puts
end