nestor 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/doc/state-diagram.graffle +2135 -1855
- data/doc/state-diagram.png +0 -0
- data/lib/nestor/cli.rb +1 -1
- data/lib/nestor/machine.rb +2 -1
- data/lib/nestor/strategies/test/unit.rb +30 -19
- data/lib/nestor/strategies.rb +3 -3
- data/lib/nestor/watchers/rails.rb +3 -3
- data/lib/nestor/watchers/rails_script.rb +7 -1
- data/spec/machine_spec.rb +0 -47
- data/spec/test_unit_strategy_spec.rb +41 -0
- metadata +4 -2
data/doc/state-diagram.png
CHANGED
Binary file
|
data/lib/nestor/cli.rb
CHANGED
@@ -32,7 +32,7 @@ module Nestor
|
|
32
32
|
else
|
33
33
|
puts "Launching..."
|
34
34
|
end
|
35
|
-
Nestor::Watchers::Rails.run(:script => Pathname.new(options[:script]))
|
35
|
+
Nestor::Watchers::Rails.run(:script => options[:script] ? Pathname.new(options[:script]) : nil)
|
36
36
|
end
|
37
37
|
|
38
38
|
desc("customize PATH", <<-EODESC.gsub(/^\s{6}/, ""))
|
data/lib/nestor/machine.rb
CHANGED
@@ -47,7 +47,7 @@ module Nestor
|
|
47
47
|
# The list of failing tests or examples being focused on right now
|
48
48
|
attr_reader :focuses # :nodoc:
|
49
49
|
|
50
|
-
# +strategy+ is required, and must implement a couple of methods. See Nestor::Strategies for the required calls.
|
50
|
+
# +strategy+ is required, and must implement a couple of methods. See {Nestor::Strategies} for the required calls.
|
51
51
|
def initialize(strategy)
|
52
52
|
super() # Have to specify no-args, or else it'll raise an ArgumentError
|
53
53
|
|
@@ -79,6 +79,7 @@ module Nestor
|
|
79
79
|
end
|
80
80
|
|
81
81
|
event :run do
|
82
|
+
transition [:running_all, :running_multi, :running_focused] => same
|
82
83
|
transition :run_focused_pending => :running_focused
|
83
84
|
transition :run_multi_pending => :running_multi
|
84
85
|
end
|
@@ -52,6 +52,33 @@ module Nestor
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
+
# Utility method to extract data from a Test::Unit failure.
|
56
|
+
#
|
57
|
+
# @param failure [Test::Unit::Failure, Test::Unit::Error] The Test::Unit failure or error from which to extract information.
|
58
|
+
# @param test_files [Array<String>] The list of files that might have generated this failure. This is used to detect the file that caused the failure.
|
59
|
+
#
|
60
|
+
# @return [String, String] Returns the filename and test name as a 2 element Array.
|
61
|
+
def self.parse_failure(failure, test_files)
|
62
|
+
filename = if failure.respond_to?(:location) then
|
63
|
+
failure.location.map do |loc|
|
64
|
+
filename = loc.split(":", 2).first
|
65
|
+
test_files.detect {|tf| filename.include?(tf)}
|
66
|
+
end.compact.first
|
67
|
+
elsif failure.respond_to?(:exception) then
|
68
|
+
failure.exception.backtrace.map do |loc|
|
69
|
+
filename = loc.split(":", 2).first
|
70
|
+
loc = loc[1..-1] if loc[0,1] == "/"
|
71
|
+
test_files.detect {|tf| filename.include?(tf)}
|
72
|
+
end.compact.first
|
73
|
+
else
|
74
|
+
raise "Unknown object type received as failure: #{failure.inspect} doesn't have #exception or #location methods."
|
75
|
+
end
|
76
|
+
|
77
|
+
test_name = failure.test_name.split("(", 2).first.strip.sub(/\.$/, "")
|
78
|
+
|
79
|
+
[filename, test_name]
|
80
|
+
end
|
81
|
+
|
55
82
|
private
|
56
83
|
|
57
84
|
# Since we forked, we can't call into the Machine from the child process. Upstream
|
@@ -61,26 +88,10 @@ module Nestor
|
|
61
88
|
info = {"status" => test_runner.passed? ? "successful" : "failed", "failures" => {}}
|
62
89
|
failures = info["failures"]
|
63
90
|
test_runner.faults.each do |failure|
|
64
|
-
filename =
|
65
|
-
failure.location.detect do |loc|
|
66
|
-
filename = loc.split(":", 2).first
|
67
|
-
test_files.detect {|tf| filename.include?(tf)}
|
68
|
-
end
|
69
|
-
elsif failure.respond_to?(:exception) then
|
70
|
-
failure.exception.backtrace.detect do |loc|
|
71
|
-
filename = loc.split(":", 2).first
|
72
|
-
test_files.detect {|tf| filename.include?(tf)}
|
73
|
-
end
|
74
|
-
else
|
75
|
-
raise "Unknown object type received as failure: #{failure.inspect} doesn't have #exception or #location methods."
|
76
|
-
end
|
77
|
-
|
78
|
-
test_name = failure.test_name.split("(", 2).first.strip
|
91
|
+
filename, test_name = self.class.parse_failure(failure, test_files)
|
79
92
|
if filename.nil? then
|
80
|
-
log("Could not map #{failure.test_name.inspect} to a specific test file: mapping to #{test_files.length}")
|
81
|
-
|
82
|
-
failures[test_name] = tf
|
83
|
-
end
|
93
|
+
log("Could not map #{failure.test_name.inspect} to a specific test file: mapping to #{test_files.length} files")
|
94
|
+
failures[test_name] = test_files
|
84
95
|
else
|
85
96
|
log("Failed #{failure.test_name.inspect} in #{filename.inspect}")
|
86
97
|
failures[test_name] = filename
|
data/lib/nestor/strategies.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
module Nestor
|
2
|
-
# Nestor::Cli will require a file named +nestor/strategies/#{strategy_name}+. If you want
|
2
|
+
# {Nestor::Cli} will require a file named +nestor/strategies/#{strategy_name}+. If you want
|
3
3
|
# to provide custom strategies, make it available to Nestor using the correct path.
|
4
4
|
#
|
5
5
|
# Strategies are simple objects that implement the following protocol:
|
6
6
|
#
|
7
7
|
# <tt>log(message)</tt>:: Logs a simple message, either to the console or a logfile.
|
8
|
-
# The Machine will use the +log+ method to notify about it's
|
8
|
+
# The {Nestor::Machine} will use the +log+ method to notify about it's
|
9
9
|
# state transitions.
|
10
10
|
#
|
11
11
|
# <tt>run_all</tt>:: Runs all the tests, no matter what. In the Rails &
|
12
|
-
#
|
12
|
+
# {Nestor::Strategies::Test::Unit} case, this means <tt>Dir["test/**/*_test.rb"]</tt>.
|
13
13
|
#
|
14
14
|
# <tt>run(tests_files, focused_cases=[])</tt>:: Runs only a subset of the tests, maybe
|
15
15
|
# focusing on only a couple of tests / examples.
|
@@ -5,12 +5,12 @@ module Nestor
|
|
5
5
|
module Watchers
|
6
6
|
# Knows how to map file change events from Rails conventions to the corresponding test case.
|
7
7
|
module Rails
|
8
|
-
# Launches a Watchr::Controller to and never returns. The Controller will
|
8
|
+
# Launches a {Watchr::Controller} to and never returns. The Controller will
|
9
9
|
# listen for file change events and trigger appropriate events on the Machine.
|
10
10
|
#
|
11
|
-
# By default, the Rails watcher will use the +Test::Unit+ strategy.
|
11
|
+
# By default, the Rails watcher will use the +{Nestor::Strategies::Test::Unit}+ strategy.
|
12
12
|
#
|
13
|
-
# @option options :strategy [Nestor::Strategies] The strategy to use. Must be an instance of a class that implements the protocol defined in Nestor::Strategies.
|
13
|
+
# @option options :strategy [Nestor::Strategies] ({Nestor::Strategies::Test::Unit}) The strategy to use. Must be an instance of a class that implements the protocol defined in {Nestor::Strategies}.
|
14
14
|
# @option options :script The path to the Watchr script.
|
15
15
|
#
|
16
16
|
# @return Never...
|
@@ -26,6 +26,7 @@ def sendoff(timeout=0.8, path="tmp/nestor-sendoff") #:nodoc:
|
|
26
26
|
end
|
27
27
|
|
28
28
|
def changed!(filename) #:nodoc:
|
29
|
+
return if File.directory?(filename)
|
29
30
|
@machine.changed! filename
|
30
31
|
sendoff
|
31
32
|
end
|
@@ -59,6 +60,11 @@ watch 'test/test_helper\.rb' do |md|
|
|
59
60
|
@machine.reset!
|
60
61
|
end
|
61
62
|
|
63
|
+
watch 'db/schema.rb' do |_|
|
64
|
+
log "Detected changed schema: preparing test DB"
|
65
|
+
system("rake db:test:prepare")
|
66
|
+
end
|
67
|
+
|
62
68
|
watch 'test/(?:unit|functional|integration|performance)/.*' do |md|
|
63
69
|
log "#{md[0].inspect} => #{md[0].inspect}"
|
64
70
|
changed! md[0]
|
@@ -72,7 +78,7 @@ watch 'tmp/nestor-results.yml' do |md|
|
|
72
78
|
info = YAML.load_file(md[0])
|
73
79
|
log "New results in: #{info.inspect}"
|
74
80
|
failures = info["failures"]
|
75
|
-
@machine.send("run_#{info["status"]}!", failures.values.uniq, failures.keys)
|
81
|
+
@machine.send("run_#{info["status"]}!", failures.values.flatten.uniq, failures.keys)
|
76
82
|
end
|
77
83
|
|
78
84
|
watch 'tmp/nestor-sendoff' do |_|
|
data/spec/machine_spec.rb
CHANGED
@@ -7,50 +7,3 @@ describe Nestor::Machine do
|
|
7
7
|
machine.strategy.should be_equal(strategy)
|
8
8
|
end
|
9
9
|
end
|
10
|
-
|
11
|
-
describe Nestor::Machine do
|
12
|
-
before(:each) do
|
13
|
-
@strategy = mock
|
14
|
-
@strategy.stub(:run_all)
|
15
|
-
end
|
16
|
-
|
17
|
-
it "should start in the :running_all state" do
|
18
|
-
@machine = Nestor::Machine.new(@strategy)
|
19
|
-
machine.should be_running_all
|
20
|
-
end
|
21
|
-
|
22
|
-
it "should tell the strategy to run all tests" do
|
23
|
-
strategy = mock
|
24
|
-
strategy.should_receive(:run_all).with().once
|
25
|
-
Nestor::Machine.new(strategy)
|
26
|
-
end
|
27
|
-
|
28
|
-
it "should transition to :green when calling #successful" do
|
29
|
-
machine.successful
|
30
|
-
machine.should be_green
|
31
|
-
end
|
32
|
-
|
33
|
-
it "should transition to :run_focused when calling #failed" do
|
34
|
-
machine.failed
|
35
|
-
machine.should be_run_focused
|
36
|
-
end
|
37
|
-
|
38
|
-
def machine
|
39
|
-
@machine ||= Nestor::Machine.new(@strategy)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
describe Nestor::Machine, "when in the run_focused state" do
|
44
|
-
before(:each) do
|
45
|
-
@strategy = mock
|
46
|
-
@strategy.stub(:run_all)
|
47
|
-
@machine = Nestor::Machine.new(@strategy)
|
48
|
-
@machine.failed
|
49
|
-
end
|
50
|
-
|
51
|
-
it "should transition to :running_focused when calling #changed!(filename)" do
|
52
|
-
@strategy.should_receive(:run).with(["spec/machine_spec.rb"])
|
53
|
-
@machine.changed!("spec/machine_spec.rb")
|
54
|
-
@machine.should be_running_focused
|
55
|
-
end
|
56
|
-
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/spec_helper"
|
2
|
+
require "nestor/strategies/test/unit"
|
3
|
+
|
4
|
+
describe Nestor::Strategies::Test::Unit, "#parse_failure" do
|
5
|
+
it "should return the file and test name as reported by a failure" do
|
6
|
+
failure = mock
|
7
|
+
failure.stub(:location).and_return(
|
8
|
+
["/test/functional/api/templates_controller_test.rb:12:in `__bind_1256961206_373905'",
|
9
|
+
"/Library/Ruby/Gems/1.8/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/context.rb:351:in `call'",
|
10
|
+
"/Library/Ruby/Gems/1.8/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/context.rb:351:in `test: Api::TemplatesController should flunk. '",
|
11
|
+
"/Users/francois/Projects/nestor/lib/nestor/strategies/test/unit.rb:109:in `run'"])
|
12
|
+
failure.stub(:test_name).and_return("test: Api::TemplatesController should flunk. (Api::TemplatesControllerTest)")
|
13
|
+
|
14
|
+
test_files = ["test/functional/api/templates_controller_test.rb"]
|
15
|
+
|
16
|
+
filename, test_name = Nestor::Strategies::Test::Unit.parse_failure(failure, test_files)
|
17
|
+
|
18
|
+
filename.should == "test/functional/api/templates_controller_test.rb"
|
19
|
+
test_name.should == "test: Api::TemplatesController should flunk"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should return the file and test name as reported by an error" do
|
23
|
+
exception = RuntimeError.new("bad")
|
24
|
+
exception.set_backtrace(["./test/functional/api/templates_controller_test.rb:12:in `__bind_1256962198_402597'",
|
25
|
+
"/Library/Ruby/Gems/1.8/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/context.rb:351:in `call'",
|
26
|
+
"/Library/Ruby/Gems/1.8/gems/thoughtbot-shoulda-2.10.2/lib/shoulda/context.rb:351:in `test: Api::TemplatesController should flunk. '",
|
27
|
+
"/Library/Ruby/Gems/1.8/gems/activesupport-2.3.4/lib/active_support/testing/setup_and_teardown.rb:62:in `__send__'",
|
28
|
+
"/Library/Ruby/Gems/1.8/gems/activesupport-2.3.4/lib/active_support/testing/setup_and_teardown.rb:62:in `run'"])
|
29
|
+
|
30
|
+
failure = mock
|
31
|
+
failure.stub(:exception).and_return(exception)
|
32
|
+
failure.stub(:test_name).and_return("test: Api::TemplatesController should flunk. (Api::TemplatesControllerTest)")
|
33
|
+
|
34
|
+
test_files = ["test/functional/api/templates_controller_test.rb"]
|
35
|
+
|
36
|
+
filename, test_name = Nestor::Strategies::Test::Unit.parse_failure(failure, test_files)
|
37
|
+
|
38
|
+
filename.should == "test/functional/api/templates_controller_test.rb"
|
39
|
+
test_name.should == "test: Api::TemplatesController should flunk"
|
40
|
+
end
|
41
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nestor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- "Fran\xC3\xA7ois Beausoleil"
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-10-
|
12
|
+
date: 2009-10-31 00:00:00 -04:00
|
13
13
|
default_executable: nestor
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -92,6 +92,7 @@ files:
|
|
92
92
|
- lib/nestor/watchers/rails_script.rb
|
93
93
|
- spec/machine_spec.rb
|
94
94
|
- spec/spec_helper.rb
|
95
|
+
- spec/test_unit_strategy_spec.rb
|
95
96
|
- vendor/watchr-0.5.7/.gitignore
|
96
97
|
- vendor/watchr-0.5.7/History.txt
|
97
98
|
- vendor/watchr-0.5.7/LICENSE
|
@@ -150,3 +151,4 @@ summary: Nestor keeps the place tidy by running your specs/tests everytime a fil
|
|
150
151
|
test_files:
|
151
152
|
- spec/machine_spec.rb
|
152
153
|
- spec/spec_helper.rb
|
154
|
+
- spec/test_unit_strategy_spec.rb
|