cirandas.net

ref: master

lib/tasks/plugins_tests.rake


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
$broken_plugins = %w[
  anti_spam
  bsc
  comment_classification
  ldap
  solr
]

@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 'xvfb-run', '-a', '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