testbot_instructure 0.7.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.gemtest +0 -0
  3. data/CHANGELOG +264 -0
  4. data/Gemfile +3 -0
  5. data/README.markdown +141 -0
  6. data/Rakefile +35 -0
  7. data/bin/testbot +59 -0
  8. data/lib/generators/testbot/templates/testbot.rake.erb +35 -0
  9. data/lib/generators/testbot/templates/testbot.yml.erb +45 -0
  10. data/lib/generators/testbot/testbot_generator.rb +19 -0
  11. data/lib/railtie.rb +16 -0
  12. data/lib/requester/requester.rb +171 -0
  13. data/lib/runner/job.rb +112 -0
  14. data/lib/runner/runner.rb +222 -0
  15. data/lib/runner/safe_result_text.rb +29 -0
  16. data/lib/server/build.rb +36 -0
  17. data/lib/server/group.rb +48 -0
  18. data/lib/server/job.rb +64 -0
  19. data/lib/server/memory_model.rb +91 -0
  20. data/lib/server/runner.rb +47 -0
  21. data/lib/server/server.rb +103 -0
  22. data/lib/server/status/javascripts/jquery-1.4.4.min.js +167 -0
  23. data/lib/server/status/status.html +48 -0
  24. data/lib/server/status/stylesheets/status.css +14 -0
  25. data/lib/shared/adapters/adapter.rb +27 -0
  26. data/lib/shared/adapters/cucumber_adapter.rb +91 -0
  27. data/lib/shared/adapters/helpers/ruby_env.rb +47 -0
  28. data/lib/shared/adapters/rspec2_adapter.rb +61 -0
  29. data/lib/shared/adapters/rspec_adapter.rb +79 -0
  30. data/lib/shared/adapters/test_unit_adapter.rb +44 -0
  31. data/lib/shared/color.rb +16 -0
  32. data/lib/shared/simple_daemonize.rb +25 -0
  33. data/lib/shared/ssh_tunnel.rb +36 -0
  34. data/lib/shared/testbot.rb +132 -0
  35. data/lib/shared/version.rb +12 -0
  36. data/lib/tasks/testbot.rake +30 -0
  37. data/lib/testbot.rb +2 -0
  38. data/test/fixtures/local/Rakefile +7 -0
  39. data/test/fixtures/local/config/testbot.yml +5 -0
  40. data/test/fixtures/local/log/test.log +0 -0
  41. data/test/fixtures/local/script/spec +2 -0
  42. data/test/fixtures/local/spec/models/car_spec.rb +0 -0
  43. data/test/fixtures/local/spec/models/house_spec.rb +0 -0
  44. data/test/fixtures/local/spec/spec.opts +0 -0
  45. data/test/fixtures/local/tmp/restart.txt +0 -0
  46. data/test/integration_test.rb +55 -0
  47. data/test/requester/requester_test.rb +407 -0
  48. data/test/requester/testbot.yml +7 -0
  49. data/test/requester/testbot_with_erb.yml +2 -0
  50. data/test/runner/job_test.rb +94 -0
  51. data/test/runner/safe_result_text_test.rb +20 -0
  52. data/test/server/group_test.rb +43 -0
  53. data/test/server/server_test.rb +511 -0
  54. data/test/shared/adapters/adapter_test.rb +22 -0
  55. data/test/shared/adapters/cucumber_adapter_test.rb +72 -0
  56. data/test/shared/adapters/helpers/ruby_env_test.rb +108 -0
  57. data/test/shared/adapters/rspec_adapter_test.rb +109 -0
  58. data/test/shared/testbot_test.rb +185 -0
  59. data/testbot.gemspec +34 -0
  60. metadata +313 -0
@@ -0,0 +1,27 @@
1
+ class Adapter
2
+
3
+ FILES = Dir[File.dirname(__FILE__) + "/*_adapter.rb"]
4
+ FILES.each { |file| require(file) }
5
+
6
+ def self.all
7
+ FILES.map { |file| load_adapter(file) }
8
+ end
9
+
10
+ def self.find(type)
11
+ if adapter = all.find { |adapter| adapter.type == type.to_s }
12
+ adapter
13
+ else
14
+ raise "Unknown adapter: #{type}"
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def self.load_adapter(file)
21
+ eval("::" + File.basename(file).
22
+ gsub(/\.rb/, '').
23
+ gsub(/(?:^|_)(.)/) { $1.upcase })
24
+ end
25
+
26
+ end
27
+
@@ -0,0 +1,91 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/helpers/ruby_env"))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), "../color"))
3
+
4
+ class CucumberAdapter
5
+
6
+ def self.command(project_path, ruby_interpreter, files)
7
+ cucumber_command = RubyEnv.ruby_command(project_path, :script => "script/cucumber", :bin => "cucumber",
8
+ :ruby_interpreter => ruby_interpreter)
9
+ "export AUTOTEST=1; #{cucumber_command} -f progress --backtrace -r features/support -r features/step_definitions #{files} -t ~@disabled"
10
+ end
11
+
12
+ def self.test_files(dir)
13
+ Dir["#{dir}/#{file_pattern}"]
14
+ end
15
+
16
+ def self.get_sizes(files)
17
+ files.map { |file| File.stat(file).size }
18
+ end
19
+
20
+ def self.requester_port
21
+ 2230
22
+ end
23
+
24
+ def self.pluralized
25
+ 'features'
26
+ end
27
+
28
+ def self.base_path
29
+ pluralized
30
+ end
31
+
32
+ def self.name
33
+ 'Cucumber'
34
+ end
35
+
36
+ def self.type
37
+ pluralized
38
+ end
39
+
40
+ # This is an optional method. It gets passed the entire test result and summarizes it. See the tests.
41
+ def self.sum_results(text)
42
+ scenarios, steps = parse_scenarios_and_steps(text)
43
+
44
+ scenarios_line = "#{scenarios[:total]} scenarios (" + [
45
+ (Color.colorize("#{scenarios[:failed]} failed", :red) if scenarios[:failed] > 0),
46
+ (Color.colorize("#{scenarios[:undefined]} undefined", :orange) if scenarios[:undefined] > 0),
47
+ (Color.colorize("#{scenarios[:passed]} passed", :green) if scenarios[:passed] > 0)
48
+ ].compact.join(', ') + ")"
49
+
50
+ steps_line = "#{steps[:total]} steps (" + [
51
+ (Color.colorize("#{steps[:failed]} failed", :red) if steps[:failed] > 0),
52
+ (Color.colorize("#{steps[:skipped]} skipped", :cyan) if steps[:skipped] > 0),
53
+ (Color.colorize("#{steps[:undefined]} undefined", :orange) if steps[:undefined] > 0),
54
+ (Color.colorize("#{steps[:passed]} passed", :green) if steps[:passed] > 0)
55
+ ].compact.join(', ') + ")"
56
+
57
+ scenarios_line + "\n" + steps_line
58
+ end
59
+
60
+ private
61
+
62
+ def self.parse_scenarios_and_steps(text)
63
+ results = {
64
+ :scenarios => { :total => 0, :passed => 0, :failed => 0, :undefined => 0 },
65
+ :steps => { :total => 0, :passed => 0, :failed => 0, :skipped => 0, :undefined => 0 }
66
+ }
67
+
68
+ Color.strip(text).split("\n").each do |line|
69
+ type = line.include?("scenarios") ? :scenarios : :steps
70
+
71
+ if match = line.match(/\((.+)\)/)
72
+ results[type][:total] += line.split.first.to_i
73
+ parse_status_counts(results[type], match[1])
74
+ end
75
+ end
76
+
77
+ [ results[:scenarios], results[:steps] ]
78
+ end
79
+
80
+ def self.parse_status_counts(results, status_counts)
81
+ status_counts.split(', ').each do |part|
82
+ results.keys.each do |key|
83
+ results[key] += part.split.first.to_i if part.include?(key.to_s)
84
+ end
85
+ end
86
+ end
87
+
88
+ def self.file_pattern
89
+ '**/**/*.feature'
90
+ end
91
+ end
@@ -0,0 +1,47 @@
1
+ class RubyEnv
2
+ def self.bundler?(project_path)
3
+ gem_exists?("bundler") && File.exists?("#{project_path}/Gemfile")
4
+ end
5
+
6
+ def self.gem_exists?(gem)
7
+ if Gem::Specification.respond_to?(:find_by_name)
8
+ Gem::Specification.find_by_name(gem)
9
+ else
10
+ # older depricated method
11
+ Gem.available?(gem)
12
+ end
13
+ rescue Gem::LoadError
14
+ false
15
+ end
16
+
17
+ def self.ruby_command(project_path, opts = {})
18
+ ruby_interpreter = opts[:ruby_interpreter] || "ruby"
19
+
20
+ if opts[:script] && File.exists?("#{project_path}/#{opts[:script]}")
21
+ command = opts[:script]
22
+ elsif opts[:bin]
23
+ command = opts[:bin]
24
+ else
25
+ command = nil
26
+ end
27
+
28
+ if bundler?(project_path)
29
+ "#{rvm_prefix(project_path)} #{ruby_interpreter} -S bundle exec #{command}".strip
30
+ else
31
+ "#{rvm_prefix(project_path)} #{ruby_interpreter} -S #{command}".strip
32
+ end
33
+ end
34
+
35
+ def self.rvm_prefix(project_path)
36
+ if rvm?
37
+ rvmrc_path = File.join project_path, ".rvmrc"
38
+ if File.exists?(rvmrc_path)
39
+ File.read(rvmrc_path).to_s.strip + " exec"
40
+ end
41
+ end
42
+ end
43
+
44
+ def self.rvm?
45
+ system("rvm info") != nil
46
+ end
47
+ end
@@ -0,0 +1,61 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/helpers/ruby_env"))
2
+
3
+ class Rspec2Adapter
4
+
5
+ def self.command(project_path, ruby_interpreter, files)
6
+ spec_command = RubyEnv.ruby_command(project_path,
7
+ :bin => "rspec",
8
+ :ruby_interpreter => ruby_interpreter)
9
+
10
+ if File.exists?("#{project_path}/spec/spec.opts")
11
+ spec_command += " -O spec/spec.opts"
12
+ end
13
+
14
+ "export RSPEC_COLOR=true; #{spec_command} #{files}"
15
+ end
16
+
17
+ def self.test_files(dir)
18
+ if ENV['SELENIUM_SPECS']
19
+ puts 'running selenium specs'
20
+ test_files = FileList['spec/selenium/**/*_spec.rb'] + FileList['vendor/plugins/*/spec_canvas/selenium/*_spec.rb']
21
+ elsif ENV['PLUGIN_SPECS']
22
+ puts 'running plugin specs'
23
+ test_files = FileList['vendor/plugins/*/spec_canvas/**/*_spec.rb'].exclude('vendor/plugins/*/spec_canvas/selenium/*_spec.rb') + FileList['spec/**/*_spec.rb'].exclude('spec/selenium/**/*_spec.rb')
24
+ :ew3else
25
+ puts 'normal pattern'
26
+ test_files = Dir["#{dir}/#{file_pattern}"]
27
+ end
28
+ test_files
29
+ end
30
+
31
+ def self.get_sizes(files)
32
+ files.map { |file| File.stat(file).size }
33
+ end
34
+
35
+ def self.requester_port
36
+ 2299
37
+ end
38
+
39
+ def self.pluralized
40
+ 'specs'
41
+ end
42
+
43
+ def self.base_path
44
+ "spec"
45
+ end
46
+
47
+ def self.name
48
+ 'RSpec2'
49
+ end
50
+
51
+ def self.type
52
+ 'rspec'
53
+ end
54
+
55
+ private
56
+
57
+ def self.file_pattern
58
+ '**/**/*_spec.rb'
59
+ end
60
+
61
+ end
@@ -0,0 +1,79 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/helpers/ruby_env"))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), "../color"))
3
+
4
+ class RspecAdapter
5
+
6
+ def self.command(project_path, ruby_interpreter, files)
7
+ spec_command = RubyEnv.ruby_command(project_path, :script => "script/spec", :bin => "rspec",
8
+ :ruby_interpreter => ruby_interpreter)
9
+ if File.exists?("#{project_path}/spec/spec.opts")
10
+ spec_command += " -O spec/spec.opts"
11
+ end
12
+
13
+ "export RSPEC_COLOR=true; #{spec_command} #{files}"
14
+ end
15
+
16
+ def self.test_files(dir)
17
+ Dir["#{dir}/#{file_pattern}"]
18
+ end
19
+
20
+ def self.get_sizes(files)
21
+ files.map { |file| File.stat(file).size }
22
+ end
23
+
24
+ def self.requester_port
25
+ 2299
26
+ end
27
+
28
+ def self.pluralized
29
+ 'specs'
30
+ end
31
+
32
+ def self.base_path
33
+ type
34
+ end
35
+
36
+ def self.name
37
+ 'RSpec'
38
+ end
39
+
40
+ def self.type
41
+ 'spec'
42
+ end
43
+
44
+ # This is an optional method. It gets passed the entire test result and summarizes it. See the tests.
45
+ def self.sum_results(results)
46
+ examples, failures, pending = 0, 0, 0
47
+ results.split("\n").each do |line|
48
+ line =~ /(\d+) examples?, (\d+) failures?(, (\d+) pending)?/
49
+ next unless $1
50
+ examples += $1.to_i
51
+ failures += $2.to_i
52
+ pending += $4.to_i
53
+ end
54
+
55
+ result = [ pluralize(examples, 'example'), pluralize(failures, 'failure'), (pending > 0 ? "#{pending} pending" : nil) ].compact.join(', ')
56
+ if failures == 0 && pending == 0
57
+ Color.colorize(result, :green)
58
+ elsif failures == 0 && pending > 0
59
+ Color.colorize(result, :orange)
60
+ else
61
+ Color.colorize(result, :red)
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ def self.pluralize(count, singular)
68
+ if count == 1
69
+ "#{count} #{singular}"
70
+ else
71
+ "#{count} #{singular}s"
72
+ end
73
+ end
74
+
75
+ def self.file_pattern
76
+ '**/**/*_spec.rb'
77
+ end
78
+
79
+ end
@@ -0,0 +1,44 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "/helpers/ruby_env"))
2
+
3
+ class TestUnitAdapter
4
+
5
+ def self.command(project_path, ruby_interpreter, files)
6
+ ruby_command = RubyEnv.ruby_command(project_path, :ruby_interpreter => ruby_interpreter)
7
+ %{#{ruby_command} -Itest -e '%w(#{files}).each { |file| require(Dir.pwd + "/" + file) }'}
8
+ end
9
+
10
+ def self.test_files(dir)
11
+ Dir["#{dir}/#{file_pattern}"]
12
+ end
13
+
14
+ def self.get_sizes(files)
15
+ files.map { |file| File.stat(file).size }
16
+ end
17
+
18
+ def self.requester_port
19
+ 2231
20
+ end
21
+
22
+ def self.pluralized
23
+ 'tests'
24
+ end
25
+
26
+ def self.base_path
27
+ type
28
+ end
29
+
30
+ def self.name
31
+ 'Test::Unit'
32
+ end
33
+
34
+ def self.type
35
+ 'test'
36
+ end
37
+
38
+ private
39
+
40
+ def self.file_pattern
41
+ '**/**/*_test.rb'
42
+ end
43
+
44
+ end
@@ -0,0 +1,16 @@
1
+ class Color
2
+ def self.colorize(text, color)
3
+ colors = { :green => 32, :orange => 33, :red => 31, :cyan => 36 }
4
+
5
+ if colors[color]
6
+ "\033[#{colors[color]}m#{text}\033[0m"
7
+ else
8
+ raise "Color not implemented: #{color}"
9
+ end
10
+ end
11
+
12
+ def self.strip(text)
13
+ text.gsub(/\e.+?m/, '')
14
+ end
15
+ end
16
+
@@ -0,0 +1,25 @@
1
+ require 'rubygems'
2
+ require 'daemons'
3
+
4
+ class SimpleDaemonize
5
+
6
+ def self.start(proc, pid_path, app_name)
7
+ working_dir = Dir.pwd
8
+
9
+ group = Daemons::ApplicationGroup.new(app_name)
10
+ group.new_application(:mode => :none).start
11
+
12
+ File.open(pid_path, 'w') { |file| file.write(Process.pid) }
13
+ Dir.chdir(working_dir)
14
+ proc.call
15
+ end
16
+
17
+ def self.stop(pid_path)
18
+ return unless File.exists?(pid_path)
19
+ pid = File.read(pid_path)
20
+
21
+ system "kill -9 #{pid} &> /dev/null"
22
+ system "rm #{pid_path} &> /dev/null"
23
+ end
24
+
25
+ end
@@ -0,0 +1,36 @@
1
+ require 'rubygems'
2
+ require 'net/ssh'
3
+
4
+ class SSHTunnel
5
+
6
+ def initialize(host, user, local_port = 2288)
7
+ @host, @user, @local_port = host, user, local_port
8
+ end
9
+
10
+ def open
11
+ connect
12
+
13
+ start_time = Time.now
14
+ while true
15
+ break if @up
16
+ sleep 0.5
17
+
18
+ if Time.now - start_time > 5
19
+ puts "SSH connection failed, trying again..."
20
+ start_time = Time.now
21
+ connect
22
+ end
23
+ end
24
+ end
25
+
26
+ def connect
27
+ @thread.kill! if @thread
28
+ @thread = Thread.new do
29
+ Net::SSH.start(@host, @user, { :timeout => 1 }) do |ssh|
30
+ ssh.forward.local(@local_port, 'localhost', Testbot::SERVER_PORT)
31
+ ssh.loop { @up = true }
32
+ end
33
+ end
34
+ end
35
+
36
+ end
@@ -0,0 +1,132 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), '/version'))
2
+ require File.expand_path(File.join(File.dirname(__FILE__), '/simple_daemonize'))
3
+ require File.expand_path(File.join(File.dirname(__FILE__), '/adapters/adapter'))
4
+ require 'fileutils'
5
+
6
+ module Testbot
7
+ require 'railtie' if defined?(Rails)
8
+
9
+ if ENV['INTEGRATION_TEST']
10
+ SERVER_PID = "/tmp/integration_test_testbot_server.pid"
11
+ RUNNER_PID = "/tmp/integration_test_testbot_runner.pid"
12
+ else
13
+ SERVER_PID = "/tmp/testbot_server.pid"
14
+ RUNNER_PID = "/tmp/testbot_runner.pid"
15
+ end
16
+
17
+ DEFAULT_WORKING_DIR = "/tmp/testbot"
18
+ DEFAULT_SERVER_PATH = "/tmp/testbot/#{ENV['USER']}"
19
+ DEFAULT_USER = "testbot"
20
+ DEFAULT_PROJECT = "project"
21
+ DEFAULT_RUNNER_USAGE = "100%"
22
+ SERVER_PORT = ENV['INTEGRATION_TEST'] ? 22880 : 2288
23
+
24
+ class CLI
25
+
26
+ def self.run(argv)
27
+ return false if argv == []
28
+ opts = parse_args(argv)
29
+
30
+ if opts[:help]
31
+ return false
32
+ elsif opts[:version]
33
+ puts "Testbot #{Testbot.version}"
34
+ elsif [ true, 'run', 'start' ].include?(opts[:server])
35
+ start_server(opts[:server])
36
+ elsif opts[:server] == 'stop'
37
+ stop('server', Testbot::SERVER_PID)
38
+ elsif [ true, 'run', 'start' ].include?(opts[:runner])
39
+ require File.expand_path(File.join(File.dirname(__FILE__), '/../runner/runner'))
40
+ return false unless valid_runner_opts?(opts)
41
+ start_runner(opts)
42
+ elsif opts[:runner] == 'stop'
43
+ stop('runner', Testbot::RUNNER_PID)
44
+ elsif adapter = Adapter.all.find { |adapter| opts[adapter.type.to_sym] }
45
+ require File.expand_path(File.join(File.dirname(__FILE__), '/../requester/requester'))
46
+ start_requester(opts, adapter)
47
+ end
48
+
49
+ true
50
+ end
51
+
52
+ def self.parse_args(argv)
53
+ last_setter = nil
54
+ hash = {}
55
+ str = ''
56
+ argv.each_with_index do |arg, i|
57
+ if arg.include?('--')
58
+ str = ''
59
+ last_setter = arg.split('--').last.to_sym
60
+ hash[last_setter] = true if (i == argv.size - 1) || argv[i+1].include?('--')
61
+ else
62
+ str += ' ' + arg
63
+ hash[last_setter] = str.strip
64
+ end
65
+ end
66
+ hash
67
+ end
68
+
69
+ def self.start_runner(opts)
70
+ stop('runner', Testbot::RUNNER_PID)
71
+
72
+ proc = lambda {
73
+ working_dir = opts[:working_dir] || Testbot::DEFAULT_WORKING_DIR
74
+ FileUtils.mkdir_p(working_dir)
75
+ Dir.chdir(working_dir)
76
+ runner = Runner::Runner.new(:server_host => opts[:connect],
77
+ :auto_update => opts[:auto_update], :max_instances => opts[:cpus],
78
+ :ssh_tunnel => opts[:ssh_tunnel], :server_user => opts[:user],
79
+ :max_jruby_instances => opts[:max_jruby_instances],
80
+ :dev_gem_root => opts[:dev_gem_root],
81
+ :wait_for_updated_gem => opts[:wait_for_updated_gem],
82
+ :jruby_opts => opts[:jruby_opts])
83
+ runner.run!
84
+ }
85
+
86
+ if opts[:runner] == 'run'
87
+ proc.call
88
+ else
89
+ puts "Testbot runner started (pid: #{Process.pid})"
90
+ SimpleDaemonize.start(proc, Testbot::RUNNER_PID, "testbot (runner)")
91
+ end
92
+ end
93
+
94
+ def self.start_server(type)
95
+ stop('server', Testbot::SERVER_PID)
96
+ require File.expand_path(File.join(File.dirname(__FILE__), '/../server/server'))
97
+
98
+ if type == 'run'
99
+ Sinatra::Application.run! :environment => "production"
100
+ else
101
+ puts "Testbot server started (pid: #{Process.pid})"
102
+ SimpleDaemonize.start(lambda {
103
+ Sinatra::Application.run! :environment => "production"
104
+ }, Testbot::SERVER_PID, "testbot (server)")
105
+ end
106
+ end
107
+
108
+ def self.stop(name, pid)
109
+ puts "Testbot #{name} stopped" if SimpleDaemonize.stop(pid)
110
+ end
111
+
112
+ def self.start_requester(opts, adapter)
113
+ requester = Requester::Requester.new(:server_host => opts[:connect],
114
+ :rsync_path => opts[:rsync_path],
115
+ :rsync_ignores => opts[:rsync_ignores].to_s,
116
+ :available_runner_usage => nil,
117
+ :project => opts[:project],
118
+ :ssh_tunnel => opts[:ssh_tunnel], :server_user => opts[:user])
119
+ requester.run_tests(adapter, adapter.base_path)
120
+ end
121
+
122
+ def self.valid_runner_opts?(opts)
123
+ opts[:connect].is_a?(String)
124
+ end
125
+
126
+ def self.lib_path
127
+ File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib'))
128
+ end
129
+
130
+ end
131
+
132
+ end
@@ -0,0 +1,12 @@
1
+ module Testbot
2
+ # Don't forget to update readme and changelog
3
+ def self.version
4
+ version = "0.7.8"
5
+ dev_version_file = File.join(File.dirname(__FILE__), '..', '..', 'DEV_VERSION')
6
+ if File.exists?(dev_version_file)
7
+ version += File.read(dev_version_file)
8
+ end
9
+ version
10
+ end
11
+ end
12
+
@@ -0,0 +1,30 @@
1
+ require File.dirname(__FILE__) + '/../shared/adapters/adapter'
2
+
3
+ namespace :testbot do
4
+
5
+ def run_and_show_results(adapter, custom_path)
6
+ 'testbot:before_request'.tap { |t| Rake::Task.task_defined?(t) && Rake::Task[t].invoke }
7
+
8
+ require File.expand_path(File.join(File.dirname(__FILE__), '..', 'requester', 'requester.rb'))
9
+ requester = Testbot::Requester::Requester.create_by_config("#{Rails.root}/config/testbot.yml")
10
+
11
+ puts "Running #{adapter.pluralized}..."
12
+ start_time = Time.now
13
+
14
+ path = custom_path ? "#{adapter.base_path}/#{custom_path}" : adapter.base_path
15
+ success = requester.run_tests(adapter, path)
16
+
17
+ puts
18
+ puts "Finished in #{Time.now - start_time} seconds."
19
+ success
20
+ end
21
+
22
+ Adapter.all.each do |adapter|
23
+
24
+ desc "Run the #{adapter.name} tests using testbot"
25
+ task adapter.type, :custom_path do |_, args|
26
+ exit 1 unless run_and_show_results(adapter, args[:custom_path])
27
+ end
28
+
29
+ end
30
+ end
data/lib/testbot.rb ADDED
@@ -0,0 +1,2 @@
1
+ # Rails plugin hook
2
+ require File.expand_path(File.join(File.dirname(__FILE__), '/shared/testbot'))
@@ -0,0 +1,7 @@
1
+ namespace :testbot do
2
+
3
+ task :before_run do
4
+ puts "prepare got called"
5
+ end
6
+
7
+ end
@@ -0,0 +1,5 @@
1
+ server_host: localhost
2
+ rsync_path: ../server
3
+ available_runner_usage: 100%
4
+ rsync_ignores: log/* tmp/*
5
+
File without changes
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env ruby
2
+ puts "script/spec got called with #{ARGV.inspect}"
File without changes
File without changes
File without changes
File without changes