tester 0.1.0

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/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 jugyo
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,18 @@
1
+ Tester
2
+ ======
3
+
4
+ Continuation testing tool.
5
+
6
+ Usage
7
+ ------
8
+
9
+
10
+
11
+ Installation
12
+ ------
13
+
14
+
15
+
16
+ == Copyright
17
+
18
+ Copyright (c) 2010 jugyo. See LICENSE for details.
@@ -0,0 +1,55 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "tester"
8
+ gem.summary = %Q{Continuation testing tool.}
9
+ gem.description = %Q{Continuation testing tool for project that use git.}
10
+ gem.email = "jugyo.org@gmail.com"
11
+ gem.homepage = "http://github.com/jugyo/tester"
12
+ gem.authors = ["jugyo"]
13
+ gem.add_development_dependency "shoulda", ">= 0"
14
+ gem.add_development_dependency "rr", ">= 0"
15
+ gem.add_dependency 'kvs'
16
+ gem.add_dependency 'sinatra'
17
+ gem.add_dependency 'choice'
18
+ end
19
+ rescue LoadError
20
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
21
+ end
22
+
23
+ require 'rake/testtask'
24
+ Rake::TestTask.new(:test) do |test|
25
+ test.libs << 'lib' << 'test'
26
+ test.pattern = 'test/**/test_*.rb'
27
+ test.verbose = true
28
+ end
29
+
30
+ begin
31
+ require 'rcov/rcovtask'
32
+ Rcov::RcovTask.new do |test|
33
+ test.libs << 'test'
34
+ test.pattern = 'test/**/test_*.rb'
35
+ test.verbose = true
36
+ end
37
+ rescue LoadError
38
+ task :rcov do
39
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
40
+ end
41
+ end
42
+
43
+ task :test => :check_dependencies
44
+
45
+ task :default => :test
46
+
47
+ require 'rake/rdoctask'
48
+ Rake::RDocTask.new do |rdoc|
49
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
50
+
51
+ rdoc.rdoc_dir = 'rdoc'
52
+ rdoc.title = "tester #{version}"
53
+ rdoc.rdoc_files.include('README*')
54
+ rdoc.rdoc_files.include('lib/**/*.rb')
55
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,86 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.dirname(__FILE__) + "/../lib")
4
+
5
+ require 'rubygems'
6
+ require 'tester'
7
+ require 'choice'
8
+
9
+ Choice.options do
10
+ banner "Usage: #{File.basename(__FILE__)} [-hpv] path_to_git_repo"
11
+ header ''
12
+ header 'Server options:'
13
+
14
+ option :host do
15
+ d = "0.0.0.0"
16
+ short '-h'
17
+ long '--host=HOST'
18
+ desc "The hostname or ip of the host to bind to (default #{d})"
19
+ default d
20
+ end
21
+
22
+ option :port do
23
+ d = 4567
24
+ short '-p'
25
+ long '--port=PORT'
26
+ desc "The port to listen on (default #{d})"
27
+ cast Integer
28
+ default d
29
+ end
30
+
31
+ option :branch do
32
+ d = 'master'
33
+ short '-b'
34
+ long '--branch=BRANCH'
35
+ desc "The branch to test (default #{d})"
36
+ default d
37
+ end
38
+
39
+ option :command do
40
+ d = 'rake'
41
+ short '-c'
42
+ long '--command=COMMAND'
43
+ desc "The test command (default #{d})"
44
+ default d
45
+ end
46
+
47
+ option :interval do
48
+ d = 60
49
+ short '-i'
50
+ long '--interval=INTERVAL'
51
+ desc "The interval to check update (default #{d})"
52
+ cast Integer
53
+ default d
54
+ end
55
+
56
+ separator ''
57
+ separator 'Common options: '
58
+
59
+ option :help do
60
+ long '--help'
61
+ desc 'Show this message'
62
+ end
63
+
64
+ option :version do
65
+ short '-v'
66
+ long '--version'
67
+ desc 'Show version'
68
+ action do
69
+ puts "#{File.basename(__FILE__)} v#{CIJoe::Version}"
70
+ exit
71
+ end
72
+ end
73
+ end
74
+
75
+ options = Choice.choices
76
+
77
+ Tester::Runner.start(
78
+ :branch => options[:branch],
79
+ :test_command => options[:command],
80
+ :interval => options[:interval]
81
+ )
82
+
83
+ Tester::Server.run!(
84
+ :host => options[:host],
85
+ :port => options[:port]
86
+ )
@@ -0,0 +1,16 @@
1
+ unless File.exists?('.git')
2
+ puts 'not git dir'
3
+ exit!
4
+ end
5
+
6
+ require 'kvs'
7
+ require 'singleton'
8
+ require 'sinatra'
9
+
10
+ work_dir = '.tester'
11
+ Dir.mkdir(work_dir) unless File.exists?(work_dir)
12
+ KVS.dir = work_dir
13
+
14
+ Dir[File.join(File.dirname(__FILE__), 'tester', '*.rb')].each do |filename|
15
+ require filename
16
+ end
@@ -0,0 +1,26 @@
1
+ module Tester
2
+ class Checker
3
+ attr_reader :branch
4
+ attr_accessor :last_hash
5
+
6
+ def initialize(branch)
7
+ @branch = branch
8
+ end
9
+
10
+ def if_updated(&block)
11
+ hash = head
12
+ if KVS['HEAD'] != hash
13
+ block.call(hash)
14
+ KVS['HEAD'] = self.last_hash = hash
15
+ end
16
+ end
17
+
18
+ def update
19
+ `git fetch origin && git reset --hard origin/#{branch}`
20
+ end
21
+
22
+ def head
23
+ `git rev-parse origin/#{branch}`.chomp
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,18 @@
1
+ module Tester
2
+ module Log
3
+ class << self
4
+ def []=(hash, result)
5
+ KVS['logs'] = logs << hash
6
+ KVS[hash] = result
7
+ end
8
+
9
+ def [](hash)
10
+ KVS[hash]
11
+ end
12
+
13
+ def logs
14
+ KVS['logs'] || []
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,54 @@
1
+ module Tester
2
+ class Runner
3
+ def self.start(options)
4
+ self.new(options).start
5
+ end
6
+
7
+ attr_reader :config, :checker
8
+ attr_accessor :testing, :started
9
+
10
+ def initialize(options)
11
+ @config = (KVS['config'] || {}).merge(options)
12
+ @checker = Checker.new(@config[:branch])
13
+ end
14
+
15
+ def start
16
+ return if started
17
+ Thread.start do
18
+ loop do
19
+ begin
20
+ test_if_updated
21
+ rescue Exception => e
22
+ puts "#{e.message}\n #{e.backtrace.join("\n ")}"
23
+ ensure
24
+ sleep config[:interval]
25
+ end
26
+ end
27
+ end
28
+ self.started = true
29
+ end
30
+
31
+ def test_if_updated
32
+ checker.if_updated do |hash|
33
+ begin
34
+ self.testing = true
35
+ test(hash)
36
+ ensure
37
+ self.testing = false
38
+ end
39
+ end
40
+ end
41
+
42
+ def test(hash)
43
+ process = TestProcess.new(config[:test_command])
44
+ process.start
45
+ puts "#{hash} => #{process.status}"
46
+ puts process.output
47
+ Log[hash] = process.to_hash.merge(
48
+ :hash => hash,
49
+ :created_at => Time.now,
50
+ :branch => config[:branch]
51
+ )
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,25 @@
1
+ module Tester
2
+ class Server < Sinatra::Base
3
+ dir = File.dirname(File.expand_path(__FILE__))
4
+
5
+ set :views, "#{dir}/views"
6
+ set :public, "#{dir}/public"
7
+ set :static, true
8
+ set :lock, true
9
+
10
+ get '/' do
11
+ @logs = Log.logs.map {|key| Log[key]}
12
+ haml :index
13
+ end
14
+
15
+ get '/css' do
16
+ sass :styles
17
+ end
18
+
19
+ get '/logs/:hash' do
20
+ @hash = params[:hash]
21
+ @log = Log[@hash]
22
+ haml :show
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,22 @@
1
+ module Tester
2
+ class TestProcess < Struct.new(:status, :pid)
3
+ attr_reader :command, :status, :pid, :output
4
+
5
+ def initialize(command)
6
+ @command = command
7
+ end
8
+
9
+ def start
10
+ IO.popen("#{command} 2>&1") do |io|
11
+ @pid = pid
12
+ @output = io.read
13
+ end
14
+ @status = $?.exitstatus.to_i
15
+ rescue Exception => e
16
+ end
17
+
18
+ def to_hash
19
+ {:status => status, :output => output}
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,12 @@
1
+ %table
2
+ - @logs.each do |log|
3
+ %tr
4
+ %td
5
+ %a{:href => "/logs/#{log[:hash]}"}= log[:hash]
6
+ %td
7
+ -if log[:status] == 0
8
+ .success Success!
9
+ - else
10
+ .failure Failure!
11
+ %td
12
+ = log[:created_at]
@@ -0,0 +1,16 @@
1
+ %html
2
+ %head
3
+ %meta{:"http-equiv"=>"Content-Type", :content=>"text/html;charset=UTF-8"}
4
+ %title Tester
5
+ %link{:rel=>'stylesheet', :type=>'text/css', :href=>'/css', :media=>'screen,tv,projection'}
6
+ %body
7
+ #wrap
8
+ #header
9
+ %h1
10
+ %a{:href => '/'} Tester
11
+
12
+ #content
13
+ = yield
14
+
15
+ #footer
16
+ %a{:href => 'http://github.com/jugyo/tester'} Tester
@@ -0,0 +1,12 @@
1
+ %a{:href => '/'} « logs
2
+
3
+ %h2= @hash
4
+
5
+ -if @log[:status] == 0
6
+ %h3.success Success!
7
+ - else
8
+ %h3.failure Failure!
9
+
10
+ = @log[:created_at]
11
+
12
+ %pre= @log[:output]
@@ -0,0 +1,35 @@
1
+ body {
2
+ font-family: Verdana, Helvetica;
3
+ font-size: 13.0px;
4
+ margin: 0;
5
+ padding: 0;
6
+ background: url(/background.png);
7
+ background-repeat: no-repeat;
8
+ background-position: top right;
9
+ color: gray; }
10
+
11
+ pre {
12
+ color: white;
13
+ background-color: black;
14
+ border: solid 1px gray;
15
+ overflow: auto; }
16
+
17
+ td {
18
+ padding: 4px;
19
+ border-right: solid 1px silver;
20
+ border-bottom: dashed 1px silver; }
21
+
22
+ #wrap {
23
+ margin: 20px; }
24
+
25
+
26
+ #footer {
27
+ text-align: right; }
28
+
29
+ .success {
30
+ font-weight: bold;
31
+ color: green; }
32
+
33
+ .failure {
34
+ font-weight: bold;
35
+ color: red; }
@@ -0,0 +1,35 @@
1
+ body
2
+ font-family: Verdana, Helvetica
3
+ font-size: 13.0px
4
+ margin: 0
5
+ padding: 0
6
+ background: url(/background.png)
7
+ background-repeat: no-repeat
8
+ background-position: top right
9
+ color: gray
10
+
11
+ pre
12
+ color: white
13
+ background-color: black
14
+ border: solid 1px gray
15
+ overflow: auto
16
+
17
+ td
18
+ padding: 4px
19
+ border-bottom: dashed 1px silver
20
+
21
+ #wrap
22
+ margin: 20px
23
+
24
+ #header
25
+
26
+ #footer
27
+ text-align: right
28
+
29
+ .success
30
+ font-weight: bold
31
+ color: green
32
+
33
+ .failure
34
+ font-weight: bold
35
+ color: red
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'rr'
5
+
6
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
7
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
8
+ require 'tester'
9
+
10
+ class Test::Unit::TestCase
11
+ include RR::Adapters::TestUnit
12
+ end
@@ -0,0 +1,7 @@
1
+ require 'helper'
2
+ require 'tmpdir'
3
+
4
+ class TestTester < Test::Unit::TestCase
5
+ should 'test' do
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ $:.unshift(File.dirname(__FILE__) + "/../lib")
2
+ require 'tester'
3
+ run Tester::Server
@@ -0,0 +1,27 @@
1
+ require 'helper'
2
+ require 'fakefs'
3
+
4
+ class TestChecker < Test::Unit::TestCase
5
+ context 'main' do
6
+ setup do
7
+ KVS.dir = 'foo'
8
+ KVS['HEAD'] = ''
9
+ @checker = Tester::Checker.new('master')
10
+ stub(@checker).update
11
+ end
12
+
13
+ should 'check updated' do
14
+ stub(@checker).head { 'foo' }
15
+ block = lambda {}
16
+ mock(block).call('foo')
17
+ # NOTE: rr が思ったような動作をしてくれないのでこんな書き方になってます...
18
+ @checker.if_updated do |hash|
19
+ block.call(hash)
20
+ end
21
+ mock(block).call('foo').times(0)
22
+ @checker.if_updated do |hash|
23
+ block.call(hash)
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ require 'helper'
2
+ require 'fakefs'
3
+
4
+ class TestLog < Test::Unit::TestCase
5
+ context 'main' do
6
+ setup do
7
+ KVS.dir = 'foo'
8
+ end
9
+
10
+ should 'save log' do
11
+ Tester::Log['test1'] = {:foo => :bar}
12
+ assert_equal(['test1'], Tester::Log.logs)
13
+ assert_equal({:foo => :bar}, Tester::Log['test1'])
14
+ Tester::Log['test2'] = {:FOO => :BAR}
15
+ assert_equal(['test1', 'test2'], Tester::Log.logs)
16
+ assert_equal({:FOO => :BAR}, Tester::Log['test2'])
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,28 @@
1
+ require 'helper'
2
+
3
+ class TestRunner < Test::Unit::TestCase
4
+ context 'main' do
5
+ setup do
6
+ @runner = Tester::Runner.new({:branch => 'foo', :test_command => 'bar', :interval => 10})
7
+ end
8
+
9
+ should 'Runner.new' do
10
+ assert_equal(@runner.config[:branch], @runner.checker.branch)
11
+ end
12
+
13
+ should 'test if updated' do
14
+ test_process_stub = Object.new
15
+ mock(test_process_stub).start
16
+ stub(test_process_stub).to_hash { {:foo => :bar} }
17
+ stub(test_process_stub).status { 0 }
18
+ stub(test_process_stub).output { 'output' }
19
+ mock(Tester::TestProcess).new(@runner.config[:test_command]) { test_process_stub }
20
+ mock(Tester::Log).[]=.with_any_args
21
+ stub(Time).now { 'now' }
22
+
23
+ $stdout = StringIO.new
24
+ @runner.test('XXXX')
25
+ $stdout = STDOUT
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,24 @@
1
+ require 'helper'
2
+ require 'tmpdir'
3
+
4
+ class TestTestProcess < Test::Unit::TestCase
5
+ context 'main' do
6
+ setup do
7
+ @test = Tester::TestProcess.new('foo')
8
+ end
9
+
10
+ should 'pass the test' do
11
+ stub(@test).command {'ls'}
12
+ @test.start
13
+ assert_equal(0, @test.status)
14
+ assert_equal(`ls 2>&1`, @test.output)
15
+ end
16
+
17
+ should 'not pass the test' do
18
+ stub(@test).command {'ls foo'}
19
+ @test.start
20
+ assert_not_equal(0, @test.status)
21
+ assert_equal(`ls foo 2>&1`, @test.output)
22
+ end
23
+ end
24
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tester
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - jugyo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-06 00:00:00 +09:00
13
+ default_executable: tester
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: shoulda
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rr
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: kvs
37
+ type: :runtime
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: sinatra
47
+ type: :runtime
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: choice
57
+ type: :runtime
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ description: Continuation testing tool for project that use git.
66
+ email: jugyo.org@gmail.com
67
+ executables:
68
+ - tester
69
+ extensions: []
70
+
71
+ extra_rdoc_files:
72
+ - LICENSE
73
+ - README.markdown
74
+ files:
75
+ - LICENSE
76
+ - README.markdown
77
+ - Rakefile
78
+ - VERSION
79
+ - bin/tester
80
+ - lib/tester.rb
81
+ - lib/tester/checker.rb
82
+ - lib/tester/log.rb
83
+ - lib/tester/runner.rb
84
+ - lib/tester/server.rb
85
+ - lib/tester/test_process.rb
86
+ - lib/tester/views/index.haml
87
+ - lib/tester/views/layout.haml
88
+ - lib/tester/views/show.haml
89
+ - lib/tester/views/styles.css
90
+ - lib/tester/views/styles.sass
91
+ - test/helper.rb
92
+ - test/test_tester.rb
93
+ - test/tester.ru
94
+ - test/tester/test_checker.rb
95
+ - test/tester/test_log.rb
96
+ - test/tester/test_runner.rb
97
+ - test/tester/test_test_process.rb
98
+ has_rdoc: true
99
+ homepage: http://github.com/jugyo/tester
100
+ licenses: []
101
+
102
+ post_install_message:
103
+ rdoc_options:
104
+ - --charset=UTF-8
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: "0"
112
+ version:
113
+ required_rubygems_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: "0"
118
+ version:
119
+ requirements: []
120
+
121
+ rubyforge_project:
122
+ rubygems_version: 1.3.5
123
+ signing_key:
124
+ specification_version: 3
125
+ summary: Continuation testing tool.
126
+ test_files:
127
+ - test/helper.rb
128
+ - test/test_tester.rb
129
+ - test/tester/test_checker.rb
130
+ - test/tester/test_log.rb
131
+ - test/tester/test_runner.rb
132
+ - test/tester/test_test_process.rb