abt 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +68 -0
- data/VERSION.yml +5 -0
- data/lib/abt.rb +1 -0
- data/lib/abt/notifiers/hipchat_notifier.rb +29 -0
- data/lib/abt/notifiers/web_hook_notifier.rb +27 -0
- data/lib/abt/test_collector.rb +89 -0
- data/lib/abt/test_worker.rb +147 -0
- metadata +164 -0
data/README.markdown
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# Always Be Testing!!!
|
2
|
+
|
3
|
+
A test suite that uses IronWorker by http://www.iron.io to run it.
|
4
|
+
|
5
|
+
## Getting Started
|
6
|
+
|
7
|
+
First of all the, code to test must be able to check for a special config variable:
|
8
|
+
|
9
|
+
if defined? $abt_config
|
10
|
+
@config = $abt_config
|
11
|
+
end
|
12
|
+
|
13
|
+
A real world example is here: https://github.com/iron-io/iron_mq_ruby/blob/master/test/test_base.rb
|
14
|
+
|
15
|
+
Get it running locally first, here's an example:
|
16
|
+
|
17
|
+
worker = Abt::TestWorker.new
|
18
|
+
worker.git_url = "git://github.com/iron-io/iron_mq_ruby.git"
|
19
|
+
worker.test_config = @test_config
|
20
|
+
worker.run_local
|
21
|
+
|
22
|
+
Add notifier
|
23
|
+
|
24
|
+
worker.add_notifier("HipchatNotifier",{"hipchat_api_key"=>'secret_api_key',"room_name"=>'Room Name',"title"=>"From"})
|
25
|
+
and/or
|
26
|
+
worker.add_notifier("WebHookNotifier",{"url"=>'notification_url'})
|
27
|
+
you could add as many notifiers as you need
|
28
|
+
|
29
|
+
Then try queuing it up.
|
30
|
+
|
31
|
+
worker.queue
|
32
|
+
|
33
|
+
If that works all good, then:
|
34
|
+
|
35
|
+
## Schedule It!
|
36
|
+
|
37
|
+
Schedule it to run regularly to ensure you're always being covered.
|
38
|
+
|
39
|
+
worker.schedule(:start_at=>Time.now, :run_every=>3600)
|
40
|
+
|
41
|
+
## Custom notifiers
|
42
|
+
|
43
|
+
###All you need:
|
44
|
+
|
45
|
+
* Implement in your notifier following methods:
|
46
|
+
|
47
|
+
setup configuration:
|
48
|
+
|
49
|
+
def initialize(notifier_details)
|
50
|
+
@url = notifier_details["url"]
|
51
|
+
end
|
52
|
+
|
53
|
+
process simple text message
|
54
|
+
|
55
|
+
def send_message(message)
|
56
|
+
puts message
|
57
|
+
end
|
58
|
+
|
59
|
+
if you need you could process more detailed results, 'result' is an instance of Test::Unit::TestResult
|
60
|
+
|
61
|
+
def send_formatted_message(result)
|
62
|
+
result.inspect
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
* Add your custom notifier into 'notifiers' folder or just merge it
|
67
|
+
* Add your notifier to worker
|
68
|
+
worker.add_notifier("YourCustomNotifierClass",{"option_name"=>'option_value'})
|
data/VERSION.yml
ADDED
data/lib/abt.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'abt/test_worker'
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class HipchatNotifier
|
2
|
+
require 'hipchat-api'
|
3
|
+
|
4
|
+
def initialize(notifier_details)
|
5
|
+
@client = HipChat::API.new(notifier_details["hipchat_api_key"])
|
6
|
+
@room_name = notifier_details["room_name"]
|
7
|
+
@title= notifier_details["title"]
|
8
|
+
end
|
9
|
+
|
10
|
+
def send_formatted_message(result)
|
11
|
+
color = result.passed? ? 'green' : 'red'
|
12
|
+
message = "Result: <b>#{result.status}</b> [#{result.pass_percentage}%] <br>
|
13
|
+
<strong>#{result.run_count}</strong> tests, <strong>#{result.assertion_count}</strong> assertions"
|
14
|
+
if result.error_occurred? || result.failure_occurred?
|
15
|
+
message+=", <strong>#{result.failure_count}</strong> failures, <strong>#{result.error_count}</strong>, errors<br/>"
|
16
|
+
result.faults.each { |f| message+="<br><pre>#{f.to_s.gsub(/>/,' ').gsub(/</,' ')}</pre><br/>" }
|
17
|
+
end
|
18
|
+
send_message(message,color)
|
19
|
+
end
|
20
|
+
|
21
|
+
def send_message(message,color='yellow')
|
22
|
+
puts "sending_message #{message}"
|
23
|
+
begin
|
24
|
+
puts @client.rooms_message(@room_name, @title, message, false,color).body
|
25
|
+
rescue =>ex
|
26
|
+
ex.inspect
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
class WebHookNotifier
|
2
|
+
require 'rest-client'
|
3
|
+
|
4
|
+
def initialize(notifier_details)
|
5
|
+
@url = notifier_details["url"]
|
6
|
+
end
|
7
|
+
|
8
|
+
def send_message(message)
|
9
|
+
puts "sending_message #{message}"
|
10
|
+
post(message)
|
11
|
+
end
|
12
|
+
|
13
|
+
def post(message)
|
14
|
+
begin
|
15
|
+
RestClient.post(@url, {:message=>message}, headers)
|
16
|
+
rescue RestClient::Exception => ex
|
17
|
+
ex.inspect
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def headers
|
22
|
+
#coudl be added oauth token
|
23
|
+
{'User-Agent' => "ABT Ruby Client"}
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'test/unit/autorunner'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
module Test
|
5
|
+
module Unit
|
6
|
+
AutoRunner.prepare do |auto_runner|
|
7
|
+
Notify.setup_auto_runner(auto_runner)
|
8
|
+
end
|
9
|
+
|
10
|
+
AutoRunner.setup_option do |auto_runner|
|
11
|
+
Notify.setup_auto_runner(auto_runner)
|
12
|
+
end
|
13
|
+
|
14
|
+
module Notify
|
15
|
+
class << self
|
16
|
+
def setup_auto_runner(auto_runner) # :nodoc:
|
17
|
+
auto_runner.listeners.reject! do |listener|
|
18
|
+
listener.is_a?(Notify::Notifier)
|
19
|
+
end
|
20
|
+
auto_runner.listeners << Notifier.new
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Notifier
|
25
|
+
|
26
|
+
def self.add_params(params={})
|
27
|
+
@params||={}
|
28
|
+
@params.merge!(params)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.get_params
|
32
|
+
@params||{}
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.add_notifier(sender)
|
36
|
+
@senders||=[]
|
37
|
+
@senders<<sender
|
38
|
+
puts "adding sender!#{@senders.inspect}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.get_notifiers
|
42
|
+
@senders||[]
|
43
|
+
end
|
44
|
+
|
45
|
+
def attach_to_mediator(mediator)
|
46
|
+
mediator.add_listener(UI::TestRunnerMediator::STARTED,
|
47
|
+
&method(:started))
|
48
|
+
mediator.add_listener(UI::TestRunnerMediator::FINISHED,
|
49
|
+
&method(:finished))
|
50
|
+
end
|
51
|
+
|
52
|
+
def started(result)
|
53
|
+
@result = result
|
54
|
+
end
|
55
|
+
|
56
|
+
def notify?(params,result)
|
57
|
+
return true unless result.passed?
|
58
|
+
if params && params[:notify_every]
|
59
|
+
((Time.now.hour % params[:notify_every].to_i == 0) && Time.now.min > 0 && Time.now.min < 10)
|
60
|
+
else
|
61
|
+
true
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def finished(elapsed_time)
|
66
|
+
message = "Status:%s [%g%%] (%gs)" % [@result.status,
|
67
|
+
@result.pass_percentage,
|
68
|
+
elapsed_time]
|
69
|
+
puts "Message:#{message}:"
|
70
|
+
puts "TEST_RESULT:#{@result.inspect}"
|
71
|
+
params = Notifier.get_params
|
72
|
+
senders = Notifier.get_notifiers
|
73
|
+
senders.each do |sender|
|
74
|
+
puts "sender:#{sender.inspect}"
|
75
|
+
puts "Notify?:#{notify?(params,@result).inspect}"
|
76
|
+
if sender && notify?(params,@result)
|
77
|
+
if sender.respond_to?(:send_formatted_message)
|
78
|
+
puts sender.send_formatted_message(@result)
|
79
|
+
elsif sender.respond_to?(:send_message)
|
80
|
+
puts sender.send_message(message)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'iron_worker'
|
2
|
+
require 'json'
|
3
|
+
# bump.....
|
4
|
+
ARGV=[]
|
5
|
+
module Abt
|
6
|
+
#
|
7
|
+
#class MiniTestWithHooks < MiniTest::Unit
|
8
|
+
# def before_suites
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# def after_suites
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# def _run_suites(suites, type)
|
15
|
+
# puts 'run_suites ' + suites.inspect + ' type=' + type.inspect
|
16
|
+
# begin
|
17
|
+
# before_suites
|
18
|
+
# super(suites, type)
|
19
|
+
# ensure
|
20
|
+
# after_suites
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
#
|
24
|
+
#
|
25
|
+
#
|
26
|
+
# def _run_suite(suite, type)
|
27
|
+
# puts 'run_suite ' + suite.inspect + ' type=' + type.inspect
|
28
|
+
# begin
|
29
|
+
# # suite.before_suite
|
30
|
+
# super(suite, type)
|
31
|
+
# ensure
|
32
|
+
# # suite.after_suite
|
33
|
+
# end
|
34
|
+
# end
|
35
|
+
#end
|
36
|
+
#
|
37
|
+
#..
|
38
|
+
class TestWorker < IronWorker::Base
|
39
|
+
merge_gem 'minitest', :require=>['minitest/unit', 'minitest/autorun']
|
40
|
+
merge_gem 'test-unit', :require=>['test/unit/priority', 'test/unit/testcase', 'test/unit/assertions', 'test/unit']
|
41
|
+
merge_gem 'git'
|
42
|
+
merge_gem 'hipchat-api'
|
43
|
+
merge_gem 'bundler'
|
44
|
+
merge 'test_collector'
|
45
|
+
merge_folder 'notifiers'
|
46
|
+
attr_accessor :git_url, :test_config, :notifiers, :notify_every
|
47
|
+
|
48
|
+
def add_notifier(notifier_name, notifier_details={})
|
49
|
+
@notifiers||=[]
|
50
|
+
@notifiers<<{"notifier_name"=>notifier_name, "notifier_details"=>notifier_details}
|
51
|
+
end
|
52
|
+
|
53
|
+
def run
|
54
|
+
if is_remote?
|
55
|
+
require File.join(File.dirname(__FILE__), '/gems/minitest/lib/minitest/unit')
|
56
|
+
require File.join(File.dirname(__FILE__), '/gems/test-unit/lib/test/unit/priority')
|
57
|
+
require File.join(File.dirname(__FILE__), '/gems/test-unit/lib/test/unit/testcase')
|
58
|
+
require File.join(File.dirname(__FILE__), '/gems/test-unit/lib/test/unit/assertions')
|
59
|
+
require File.join(File.dirname(__FILE__), '/gems/test-unit/lib/test/unit')
|
60
|
+
require File.join(File.dirname(__FILE__), '/gems/minitest/lib/minitest/autorun')
|
61
|
+
end
|
62
|
+
# Test::Unit.run = false
|
63
|
+
#MiniTest::Unit.runner = MiniTestWithHooks.new
|
64
|
+
# g = Git.open(user_dir, :log => Logger.new(STDOUT))
|
65
|
+
clone_dir = 'cloned'
|
66
|
+
x = File.join(user_dir, clone_dir)
|
67
|
+
p x
|
68
|
+
if is_local?
|
69
|
+
FileUtils.rm_rf(File.join(user_dir, clone_dir))
|
70
|
+
end
|
71
|
+
|
72
|
+
$abt_config = self.test_config
|
73
|
+
|
74
|
+
puts "cloning #{git_url}..."
|
75
|
+
g = Git.clone(git_url, clone_dir, :path => user_dir)
|
76
|
+
old_specs = nil
|
77
|
+
current_gemfile = File.join(File.expand_path(user_dir+clone_dir+'/test'), 'Gemfile')
|
78
|
+
log "GEMFILE:#{current_gemfile}"
|
79
|
+
log "DIR:#{File.join(user_dir+clone_dir+'/test')}"
|
80
|
+
if File.exist?(current_gemfile)
|
81
|
+
log "Bundling gems"
|
82
|
+
system "cd #{File.join(user_dir+clone_dir+'/test')}; bundle install --deployment"
|
83
|
+
log "Gemfile:#{current_gemfile}"
|
84
|
+
old_specs = Gem.loaded_specs.dup
|
85
|
+
Gem.loaded_specs.clear
|
86
|
+
ENV['BUNDLE_GEMFILE'] = current_gemfile
|
87
|
+
log "Bundling!"
|
88
|
+
require 'bundler/setup'
|
89
|
+
log "List of gems from Gemfile: #{Gem.loaded_specs.inspect}"
|
90
|
+
end
|
91
|
+
Dir.glob(File.join(user_dir, clone_dir, 'test', 'test_*')).each { |f|
|
92
|
+
puts "requiring #{f}"
|
93
|
+
require f
|
94
|
+
}
|
95
|
+
|
96
|
+
Test::Unit::Notify::Notifier.add_params({:notify_every=>notify_every}) if notify_every
|
97
|
+
if notifiers
|
98
|
+
notifiers.each do |notifier|
|
99
|
+
puts "NOTIFIER:#{notifier.inspect}"
|
100
|
+
Test::Unit::Notify::Notifier.add_notifier(Kernel.const_get(notifier["notifier_name"]).new(notifier["notifier_details"]))
|
101
|
+
end
|
102
|
+
end
|
103
|
+
Test::Unit::AutoRunner.run
|
104
|
+
|
105
|
+
if old_specs
|
106
|
+
Gem.loaded_specs.clear
|
107
|
+
old_specs.each do |k, v|
|
108
|
+
log "Loading gem:#{k}"
|
109
|
+
Gem.loaded_specs[k]=v
|
110
|
+
end
|
111
|
+
log "Full list of gems: #{Gem.loaded_specs.inspect}"
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
# ...
|
116
|
+
# def suite_results_output(options={})
|
117
|
+
# line_break = "\n"
|
118
|
+
# if options[:format] == 'html'
|
119
|
+
# line_break = "<br/>"
|
120
|
+
# end
|
121
|
+
# s = "Suite Results:#{line_break}"
|
122
|
+
# s << "#{@num_failed} failed out of #{@num_tests} tests.#{line_break}"
|
123
|
+
# if @num_failed > 0
|
124
|
+
# @failed.each do |f|
|
125
|
+
# s << "#{f.test_class}.#{f.test_method} failed: #{f.result.message}#{line_break}"
|
126
|
+
# end
|
127
|
+
# end
|
128
|
+
# s << "Test suite duration: #{duration}ms.#{line_break}"
|
129
|
+
# s
|
130
|
+
# end
|
131
|
+
#
|
132
|
+
# def duration
|
133
|
+
# ((@end_time.to_f - @start_time.to_f) * 1000.0).to_i
|
134
|
+
# end
|
135
|
+
#
|
136
|
+
# def time_in_ms(t)
|
137
|
+
# (t.to_f * 1000.0).to_i
|
138
|
+
# end
|
139
|
+
#
|
140
|
+
# # callbacks
|
141
|
+
# def on_complete
|
142
|
+
#
|
143
|
+
# end
|
144
|
+
#
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
metadata
ADDED
@@ -0,0 +1,164 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: abt
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
prerelease: false
|
10
|
+
segments_generated: true
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Travis Reeder
|
14
|
+
autorequire: !!null
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
date: 2012-02-06 00:00:00.000000000 -08:00
|
18
|
+
default_executable: !!null
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: git
|
22
|
+
requirement: &24643100 !ruby/object:Gem::Requirement
|
23
|
+
none: false
|
24
|
+
requirements:
|
25
|
+
- - ! '>='
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
28
|
+
segments:
|
29
|
+
- 0
|
30
|
+
segments_generated: true
|
31
|
+
type: :runtime
|
32
|
+
prerelease: false
|
33
|
+
version_requirements: *24643100
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: iron_worker
|
36
|
+
requirement: &24641240 !ruby/object:Gem::Requirement
|
37
|
+
none: false
|
38
|
+
requirements:
|
39
|
+
- - ! '>='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
segments:
|
43
|
+
- 0
|
44
|
+
segments_generated: true
|
45
|
+
type: :runtime
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *24641240
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: minitest
|
50
|
+
requirement: &24639900 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
segments:
|
57
|
+
- 0
|
58
|
+
segments_generated: true
|
59
|
+
type: :runtime
|
60
|
+
prerelease: false
|
61
|
+
version_requirements: *24639900
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: test-unit
|
64
|
+
requirement: &24638780 !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
segments:
|
71
|
+
- 0
|
72
|
+
segments_generated: true
|
73
|
+
type: :runtime
|
74
|
+
prerelease: false
|
75
|
+
version_requirements: *24638780
|
76
|
+
- !ruby/object:Gem::Dependency
|
77
|
+
name: bundler
|
78
|
+
requirement: &24637480 !ruby/object:Gem::Requirement
|
79
|
+
none: false
|
80
|
+
requirements:
|
81
|
+
- - ! '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
segments:
|
85
|
+
- 0
|
86
|
+
segments_generated: true
|
87
|
+
type: :runtime
|
88
|
+
prerelease: false
|
89
|
+
version_requirements: *24637480
|
90
|
+
- !ruby/object:Gem::Dependency
|
91
|
+
name: git
|
92
|
+
requirement: &24636300 !ruby/object:Gem::Requirement
|
93
|
+
none: false
|
94
|
+
requirements:
|
95
|
+
- - ! '>='
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: '0'
|
98
|
+
segments:
|
99
|
+
- 0
|
100
|
+
segments_generated: true
|
101
|
+
type: :runtime
|
102
|
+
prerelease: false
|
103
|
+
version_requirements: *24636300
|
104
|
+
- !ruby/object:Gem::Dependency
|
105
|
+
name: iron_worker
|
106
|
+
requirement: &24590740 !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ! '>='
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
segments:
|
113
|
+
- 0
|
114
|
+
segments_generated: true
|
115
|
+
type: :runtime
|
116
|
+
prerelease: false
|
117
|
+
version_requirements: *24590740
|
118
|
+
description: Always Be Testing Yo! A testing framework that runs on IronWorker http://www.iron.io
|
119
|
+
email: travis@iron.io
|
120
|
+
executables: []
|
121
|
+
extensions: []
|
122
|
+
extra_rdoc_files:
|
123
|
+
- README.markdown
|
124
|
+
files:
|
125
|
+
- VERSION.yml
|
126
|
+
- lib/abt.rb
|
127
|
+
- lib/abt/notifiers/hipchat_notifier.rb
|
128
|
+
- lib/abt/notifiers/web_hook_notifier.rb
|
129
|
+
- lib/abt/test_collector.rb
|
130
|
+
- lib/abt/test_worker.rb
|
131
|
+
- README.markdown
|
132
|
+
has_rdoc: true
|
133
|
+
homepage: https://github.com/iron-io/abt
|
134
|
+
licenses: []
|
135
|
+
post_install_message: !!null
|
136
|
+
rdoc_options: []
|
137
|
+
require_paths:
|
138
|
+
- lib
|
139
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
140
|
+
none: false
|
141
|
+
requirements:
|
142
|
+
- - ! '>='
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '1.9'
|
145
|
+
segments:
|
146
|
+
- 1
|
147
|
+
- 9
|
148
|
+
segments_generated: true
|
149
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
150
|
+
none: false
|
151
|
+
requirements:
|
152
|
+
- - ! '>='
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '0'
|
155
|
+
segments:
|
156
|
+
- 0
|
157
|
+
segments_generated: true
|
158
|
+
requirements: []
|
159
|
+
rubyforge_project: !!null
|
160
|
+
rubygems_version: 1.3.7
|
161
|
+
signing_key: !!null
|
162
|
+
specification_version: 3
|
163
|
+
summary: Always Be Testing Yo! A testing framework that runs on IronWorker http://www.iron.io
|
164
|
+
test_files: []
|