rspactor 0.0.2

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.
Binary file
Binary file
data/bin/rspactor ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'interactor')
4
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'listener')
5
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'inspector')
6
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'runner')
7
+
8
+ Runner.load
data/lib/inspector.rb ADDED
@@ -0,0 +1,92 @@
1
+ # The inspector make some assumptions about how your project is structured and where your spec files are located.
2
+ # That said: The 'spec' directory, containing all your test files, must rest in the root directory of your project.
3
+ # Futhermore it tries to locate controller, model, helper and view specs for a rails app (or projects with an identical structure)
4
+ # in root/spec/controllers, root/spec/models, root/spec/helpers and root/spec/views.
5
+
6
+ class Inspector
7
+
8
+ attr_accessor :base_spec_root
9
+
10
+ def self.file_is_invalid?(file)
11
+ return true unless File.basename(file) =~ /.rb\z|.rhtml\z|.erb\z|.haml\z/
12
+ false
13
+ end
14
+
15
+ def find_spec_file(file)
16
+ begin
17
+ return file if file_is_a_spec?(file)
18
+ spec_root = find_base_spec_root_by_file(file)
19
+ if spec_root
20
+ guessed_spec_location = guess_spec_location(file, spec_root)
21
+ if File.exist?(guessed_spec_location)
22
+ @base_spec_root = spec_root
23
+ return guessed_spec_location
24
+ end
25
+ end
26
+ nil
27
+ rescue => e
28
+ puts "Error while parsing a file: '#{file}'"
29
+ puts e
30
+ end
31
+ end
32
+
33
+ def inner_spec_directory(path)
34
+ spec_base_root = find_base_spec_root_by_file(Dir.pwd + "/.")
35
+ inner_location = extract_inner_project_location(Dir.pwd, spec_base_root)
36
+ File.join(spec_base_root, inner_location)
37
+ end
38
+
39
+ def find_base_spec_root_by_file(file)
40
+ if @base_spec_root
41
+ return @base_spec_root
42
+ else
43
+ dir_parts = File.dirname(file).split("/")
44
+ dir_parts.size.times do |i|
45
+ search_dir = dir_parts[0..dir_parts.length - i - 1].join("/") + "/"
46
+ if Dir.entries(search_dir).include?('spec')
47
+ @assumed_spec_root = search_dir + "spec"
48
+ break
49
+ end
50
+ end
51
+ return @assumed_spec_root
52
+ end
53
+ end
54
+
55
+ def guess_spec_location(file, spec_root)
56
+ inner_location = extract_inner_project_location(file, spec_root)
57
+ append_spec_file_extension(File.join(spec_root, inner_location))
58
+ end
59
+
60
+ def project_root(spec_root)
61
+ spec_root.split("/")[0...-1].join("/")
62
+ end
63
+
64
+ def extract_inner_project_location(file, spec_root)
65
+ location = file.sub(project_root(spec_root), "")
66
+ adapt_rails_specific_app_structure(location)
67
+ end
68
+
69
+ def adapt_rails_specific_app_structure(location)
70
+ # Removing 'app' if its a rails controller, model, helper or view
71
+ fu = location.split("/")
72
+ if fu[1] == "app" && (fu[2] == 'controllers' || fu[2] == 'helpers' || fu[2] == 'models' || fu[2] == 'views')
73
+ return "/" + fu[2..fu.length].join("/")
74
+ end
75
+ location
76
+ end
77
+
78
+ def append_spec_file_extension(spec_file)
79
+ if File.extname(spec_file) == ".rb"
80
+ return File.join(File.dirname(spec_file), File.basename(spec_file, ".rb")) + "_spec.rb"
81
+ else
82
+ return spec_file + "_spec.rb"
83
+ end
84
+ end
85
+
86
+ def file_is_a_spec?(file)
87
+ if file.split("/").include?('spec') && File.basename(file).match(/_spec.rb\z/)
88
+ return true
89
+ end
90
+ false
91
+ end
92
+ end
data/lib/interactor.rb ADDED
@@ -0,0 +1,34 @@
1
+ require 'timeout'
2
+
3
+ class Interactor
4
+
5
+ def wait_for_enter_key(seconds_to_wait)
6
+ begin
7
+ Timeout::timeout(seconds_to_wait) do
8
+ loop do
9
+ sleep 0.2
10
+ return true if $stdin.gets
11
+ end
12
+ end
13
+ rescue Timeout::Error
14
+ false
15
+ end
16
+ end
17
+
18
+ def start_termination_handler
19
+ @main_thread = Thread.current
20
+ Thread.new do
21
+ loop do
22
+ sleep 0.5
23
+ if $stdin.gets
24
+ puts "** Running all specs.. Hit <enter> twice to exit RSpactor."
25
+ if wait_for_enter_key(1)
26
+ @main_thread.exit
27
+ exit
28
+ end
29
+ Runner.run_all_specs
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
data/lib/listener.rb ADDED
@@ -0,0 +1,55 @@
1
+ # Some code borrowed from http://rails.aizatto.com/2007/11/28/taming-the-autotest-beast-with-fsevents/
2
+
3
+ class Listener
4
+
5
+ def initialize(&block)
6
+ require 'osx/foundation'
7
+ begin
8
+ @spec_run_time = Time.now
9
+ callback = lambda do |stream, ctx, num_events, paths, marks, event_ids|
10
+ changed_files = extract_changed_files_from_paths(split_paths(paths, num_events))
11
+ @spec_run_time = Time.now
12
+ yield changed_files
13
+ end
14
+
15
+ OSX.require_framework '/System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework'
16
+ stream = OSX::FSEventStreamCreate(OSX::KCFAllocatorDefault, callback, nil, [Dir.pwd], OSX::KFSEventStreamEventIdSinceNow, 0.5, 0)
17
+ unless stream
18
+ puts "Failed to create stream"
19
+ exit
20
+ end
21
+
22
+ OSX::FSEventStreamScheduleWithRunLoop(stream, OSX::CFRunLoopGetCurrent(), OSX::KCFRunLoopDefaultMode)
23
+ unless OSX::FSEventStreamStart(stream)
24
+ puts "Failed to start stream"
25
+ exit
26
+ end
27
+
28
+ OSX::CFRunLoopRun()
29
+ rescue Interrupt
30
+ OSX::FSEventStreamStop(stream)
31
+ OSX::FSEventStreamInvalidate(stream)
32
+ OSX::FSEventStreamRelease(stream)
33
+ end
34
+ end
35
+
36
+ def split_paths(paths, num_events)
37
+ paths.regard_as('*')
38
+ rpaths = []
39
+ num_events.times { |i| rpaths << paths[i] }
40
+ rpaths
41
+ end
42
+
43
+ def extract_changed_files_from_paths(paths)
44
+ changed_files = []
45
+ paths.each do |path|
46
+ Dir.glob(path + "*").each do |file|
47
+ next if Inspector.file_is_invalid?(file)
48
+ file_time = File.stat(file).mtime
49
+ changed_files << file if file_time > @spec_run_time
50
+ end
51
+ end
52
+ changed_files
53
+ end
54
+
55
+ end
data/lib/resulting.rb ADDED
@@ -0,0 +1,47 @@
1
+ class RSpactorFormatter
2
+ attr_accessor :example_group, :options, :where
3
+ def initialize(options, where)
4
+ @options = options
5
+ @where = where
6
+ end
7
+
8
+ def dump_summary(duration, example_count, failure_count, pending_count)
9
+ img = (failure_count == 0) ? "rails_ok.png" : "rails_fail.png"
10
+ growl "Test Results", "#{example_count} examples, #{failure_count} failures", File.dirname(__FILE__) + "/../asset/#{img}", 0
11
+ end
12
+
13
+ def start(example_count)
14
+ end
15
+
16
+ def add_example_group(example_group)
17
+ end
18
+
19
+ def example_started(example)
20
+ end
21
+
22
+ def example_passed(example)
23
+ end
24
+
25
+ def example_failed(example, counter, failure)
26
+ end
27
+
28
+ def example_pending(example_group_description, example, message)
29
+ end
30
+
31
+ def start_dump
32
+ end
33
+
34
+ def dump_failure(counter, failure)
35
+ end
36
+
37
+ def dump_pending
38
+ end
39
+
40
+ def close
41
+ end
42
+
43
+ def growl(title, msg, img, pri = 0)
44
+ %x(growlnotify -w -n rspactor --image #{img} -p #{pri} -m #{msg.inspect} #{title})
45
+ end
46
+ end
47
+
data/lib/runner.rb ADDED
@@ -0,0 +1,78 @@
1
+ class Runner
2
+
3
+ def self.load
4
+ @inspector = Inspector.new
5
+ @interactor = Interactor.new
6
+
7
+ puts ">> RSpactor is now watching at '#{Dir.pwd}'"
8
+
9
+ run_all_specs unless initial_spec_run_abort
10
+
11
+ @interactor.start_termination_handler
12
+ Listener.new do |files|
13
+ files_to_spec = []
14
+ files.each do |file|
15
+ spec_file = @inspector.find_spec_file(file)
16
+ if spec_file
17
+ puts spec_file
18
+ files_to_spec << spec_file
19
+ end
20
+ end
21
+ run_spec_command(files_to_spec) unless files_to_spec.empty?
22
+ end
23
+ end
24
+
25
+ def self.run_all_specs
26
+ run_spec_command([@inspector.inner_spec_directory(Dir.pwd)])
27
+ end
28
+
29
+ def self.run_specs_for_files(files, verbose = false)
30
+ files_to_spec = []
31
+ files.each do |file|
32
+ spec_file = @inspector.find_spec_file(file)
33
+ if spec_file
34
+ puts spec_file if verbose
35
+ files_to_spec << spec_file
36
+ end
37
+ end
38
+ run_spec_command(files_to_spec) unless files_to_spec.empty?
39
+ end
40
+
41
+ def self.run_spec_command(locations)
42
+ base_spec_root = extract_spec_root(locations.first)
43
+ spec_runner_bin = script_runner(locations.first)
44
+ locations = locations.join(" ")
45
+ cmd = "RAILS_ENV=test; "
46
+ cmd << "#{spec_runner_bin} "
47
+ cmd << "#{locations} #{spec_opts(base_spec_root)} "
48
+ cmd << "-r #{File.dirname(__FILE__)}/../lib/resulting.rb -f RSpactorFormatter:STDOUT"
49
+ #puts cmd
50
+ system(cmd)
51
+ end
52
+
53
+ def self.extract_spec_root(file)
54
+ file[0..file.index("spec") + 4]
55
+ end
56
+
57
+ def self.spec_opts(base_spec_root)
58
+ if File.exist?("#{base_spec_root}spec.opts")
59
+ return "-O #{base_spec_root}spec.opts"
60
+ else
61
+ return "-c -f progress"
62
+ end
63
+ end
64
+
65
+ def self.initial_spec_run_abort
66
+ puts "** Hit <enter> to skip initial spec run.."
67
+ @interactor.wait_for_enter_key(2)
68
+ end
69
+
70
+ def self.script_runner(file)
71
+ root = file[0..file.index("spec") - 1]
72
+ if File.exist?(root + "script/spec")
73
+ return root + "script/spec"
74
+ else
75
+ "spec"
76
+ end
77
+ end
78
+ end
metadata ADDED
@@ -0,0 +1,60 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rspactor
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Andreas Wolff
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-03-11 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: treas@dynamicdudes.com
18
+ executables:
19
+ - rspactor
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - bin/rspactor
26
+ - lib/inspector.rb
27
+ - lib/interactor.rb
28
+ - lib/listener.rb
29
+ - lib/resulting.rb
30
+ - lib/runner.rb
31
+ - asset/rails_fail.png
32
+ - asset/rails_ok.png
33
+ has_rdoc: true
34
+ homepage: http://rubyphunk.com
35
+ post_install_message:
36
+ rdoc_options: []
37
+
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ version: "0"
45
+ version:
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ requirements: []
53
+
54
+ rubyforge_project: rspactor
55
+ rubygems_version: 1.0.1
56
+ signing_key:
57
+ specification_version: 2
58
+ summary: RSpactor is a little command line tool to automatically run your changed specs (much like autotest).
59
+ test_files: []
60
+