abt 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|