Narnach-minitest 0.2.2 → 0.3.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/README.rdoc +5 -3
- data/Rakefile +0 -16
- data/bin/minitest +0 -1
- data/lib/dir_monitor.rb +9 -9
- data/lib/minitest.rb +33 -125
- data/spec/dir_monitor_spec.rb +14 -14
- metadata +2 -2
data/README.rdoc
CHANGED
@@ -2,6 +2,10 @@
|
|
2
2
|
Minitest is a simple autotester intended to be used with rSpec and rCov.
|
3
3
|
It can be used with 'plain' ruby projects and Ruby on Rails.
|
4
4
|
|
5
|
+
== Recent changes
|
6
|
+
Version 0.3.0 switched to a new file monitoring backend, DirMonitor.
|
7
|
+
The 'recent' feature was removed.
|
8
|
+
|
5
9
|
== Installation
|
6
10
|
=== From gem
|
7
11
|
Use gem to install minitest. The gem is located on github.
|
@@ -15,14 +19,12 @@ This will build the gem and install it for you.
|
|
15
19
|
|
16
20
|
== Usage
|
17
21
|
Minitest has the following command line options:
|
18
|
-
recent:: Only specs for files modified within the last hour are executed on the first run. All files are still monitored for changes, though.
|
19
22
|
profile:: Force rspec output format to 'profile', combined with coloured output and unified diffs.
|
23
|
+
drb:: Use a spec server to execute specs, speeding up their execution.
|
20
24
|
|
21
25
|
== Examples
|
22
26
|
When you start working on a codebase, it makes sense to run all specs:
|
23
27
|
minitest
|
24
|
-
When you resume work on a codebase you recently worked on, it might be useful skip running the specs for unchanged files on the first run:
|
25
|
-
minitest recent
|
26
28
|
When you want to see which specs are slow and could use optimizing:
|
27
29
|
minitest profile
|
28
30
|
You can also combine options:
|
data/Rakefile
CHANGED
@@ -26,19 +26,3 @@ desc 'Package and install the gem for the current version'
|
|
26
26
|
task :install => :gem do
|
27
27
|
system "sudo gem install -l pkg/minitest-%s.gem" % spec.version
|
28
28
|
end
|
29
|
-
|
30
|
-
namespace :gem do
|
31
|
-
desc 'Re-generate the gemspec'
|
32
|
-
task :gemspec do
|
33
|
-
files = Dir["*.rdoc"] + %w( Rakefile MIT-LICENSE ) + Dir["{spec,lib,bin}/**/*"]
|
34
|
-
tests = Dir["spec/**/*"]
|
35
|
-
data = File.read('minitest.gemspec.template')
|
36
|
-
files_string = "[%s]" % files.sort.uniq.map{|f| "'%s'" % f}.join(", ")
|
37
|
-
tests_string = "[%s]" % tests.sort.uniq.map{|f| "'%s'" % f}.join(", ")
|
38
|
-
data.gsub!(':FILES:', files_string)
|
39
|
-
data.gsub!(':TEST_FILES:', tests_string)
|
40
|
-
File.open('minitest.gemspec','wb') { |f| f.puts(data) }
|
41
|
-
puts data
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
data/bin/minitest
CHANGED
@@ -3,7 +3,6 @@ $LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__),'..','lib')
|
|
3
3
|
require 'minitest'
|
4
4
|
|
5
5
|
minitest = Minitest.new
|
6
|
-
minitest.recent = (ARGV.include? "recent")
|
7
6
|
custom_spec_opts = ''
|
8
7
|
custom_spec_opts << " --drb" if ARGV.include? "drb"
|
9
8
|
custom_spec_opts << " --format profile --colour --diff unified" if ARGV.include? "profile"
|
data/lib/dir_monitor.rb
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
# - Link these files to their specs, so Minitest can run the specs.
|
6
6
|
class DirMonitor
|
7
7
|
attr_reader :known_files, :dirs, :last_mtime
|
8
|
-
|
8
|
+
|
9
9
|
# Setup a new DirMonitor.
|
10
10
|
# Directories can be provided in a number of ways:
|
11
11
|
# DirMonitor.new 'lib', 'app'
|
@@ -17,7 +17,7 @@ class DirMonitor
|
|
17
17
|
@known_files = []
|
18
18
|
@last_mtime = {}
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
# Scan for all files in the directories and their sub-directories.
|
22
22
|
# The results are stored as a single array in @known_files.
|
23
23
|
def scan
|
@@ -28,7 +28,7 @@ class DirMonitor
|
|
28
28
|
end
|
29
29
|
@known_files = results
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
# Scan for changes in the known files.
|
33
33
|
# Yields the name of the changed files.
|
34
34
|
# Stores the mtime for all changed files.
|
@@ -41,7 +41,7 @@ class DirMonitor
|
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
# Scans for changed known files, using #scan_changed. Yields the name of both the file and its associated spec.
|
46
46
|
# spec_for is used to determine what the name of the file's spec _should_ be.
|
47
47
|
# Does not yield a file/spec name when the spec does not exist.
|
@@ -51,7 +51,7 @@ class DirMonitor
|
|
51
51
|
block.call(file, spec) if File.exists?(spec)
|
52
52
|
end
|
53
53
|
end
|
54
|
-
|
54
|
+
|
55
55
|
# Scan for new files.
|
56
56
|
# All new file names are yielded.
|
57
57
|
def scan_new(&block) # :yields: file
|
@@ -62,7 +62,7 @@ class DirMonitor
|
|
62
62
|
block.call(new_file)
|
63
63
|
end
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
# Scan for new files and check for changed known files.
|
67
67
|
# Only yields a file once per call.
|
68
68
|
def scan_new_or_changed_with_spec(&block) # :yields: file, spec
|
@@ -73,9 +73,9 @@ class DirMonitor
|
|
73
73
|
yielded_files[file]=nil
|
74
74
|
end
|
75
75
|
scan_new_with_spec(&yield_once_block)
|
76
|
-
scan_changed_with_spec(&yield_once_block)
|
76
|
+
scan_changed_with_spec(&yield_once_block)
|
77
77
|
end
|
78
|
-
|
78
|
+
|
79
79
|
# Scans for new files, like scan_new does, but yields the name of both the file and spec.
|
80
80
|
# spec_for is used to determine what the name of the file's spec _should_ be.
|
81
81
|
# Does not yield a file/spec name when the spec does not exist.
|
@@ -85,7 +85,7 @@ class DirMonitor
|
|
85
85
|
block.call(file, spec) if File.exists?(spec)
|
86
86
|
end
|
87
87
|
end
|
88
|
-
|
88
|
+
|
89
89
|
# Find the (theoretical) spec file name for a given file.
|
90
90
|
# The assumptions are:
|
91
91
|
# - All specs reside in the 'spec' directory.
|
data/lib/minitest.rb
CHANGED
@@ -1,69 +1,54 @@
|
|
1
|
+
require 'set'
|
2
|
+
require 'dir_monitor'
|
3
|
+
|
4
|
+
class Set
|
5
|
+
def join(*args,&block)
|
6
|
+
map.join(*args,&block)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
1
10
|
# = Minitest
|
2
11
|
# The default usage of Minitest is this:
|
3
12
|
# minitest = Minitest.new
|
4
13
|
# minitest.start
|
5
14
|
# This will do the following:
|
6
|
-
# -
|
7
|
-
# -
|
8
|
-
# -
|
9
|
-
# - Every second, check all known relevant files: if their mtime changes, run rspec on their spec file.
|
15
|
+
# - Initialize a DirMonitor
|
16
|
+
# - Map all files in source dirs to specs
|
17
|
+
# - Frequently check for new or changed files; run rspec on their associated specs
|
10
18
|
# - Run rcov (code coverage tester) on all specs when exiting (Press ctrl-C on send SIGINT to the process)
|
11
19
|
class Minitest
|
12
|
-
attr_reader :file_mtime
|
13
|
-
attr_reader :file_spec
|
14
|
-
attr_accessor :rcov_ignores
|
15
|
-
attr_accessor :recent
|
16
|
-
attr_accessor :recent_time
|
17
20
|
attr_accessor :source_dirs
|
18
|
-
attr_accessor :
|
19
|
-
attr_accessor :spec_cmd
|
20
|
-
|
21
|
-
|
21
|
+
attr_accessor :rcov_ignores
|
22
|
+
attr_accessor :spec_cmd, :spec_opts
|
23
|
+
attr_reader :need_testing, :known_specs
|
24
|
+
|
22
25
|
DEFAULT_RCOV_IGNORES = %w[spec/ db/ plugins/ vendor/ config/]
|
23
|
-
|
24
|
-
|
25
|
-
DEFAULT_SOURCE_EXTENSIONS = %w[rb haml rhtml erb]
|
26
|
-
|
26
|
+
DEFAULT_SOURCE_DIRS = %w[lib app spec test]
|
27
|
+
|
27
28
|
def initialize
|
28
|
-
@file_spec = {} # Map files to their specs
|
29
|
-
@file_mtime = {} # Map files to their mtimes
|
30
|
-
@need_testing = [] # Specs that need testing
|
31
|
-
@first_run = true
|
32
29
|
@active = false
|
30
|
+
@known_specs = Set.new
|
31
|
+
@need_testing = Set.new
|
33
32
|
end
|
34
33
|
|
35
34
|
def active?
|
36
35
|
@active == true
|
37
36
|
end
|
38
37
|
|
39
|
-
def first_run?
|
40
|
-
@first_run == true
|
41
|
-
end
|
42
|
-
|
43
38
|
# Partial filepaths to exclude from rcov output
|
44
39
|
def rcov_ignores
|
45
|
-
ignores = @rcov_ignores || DEFAULT_RCOV_IGNORES
|
40
|
+
ignores = (@rcov_ignores || DEFAULT_RCOV_IGNORES).dup
|
46
41
|
ignores << spec_cmd
|
47
42
|
ignores.join(",")
|
48
43
|
end
|
49
44
|
|
50
45
|
# Command line string to run rcov for all monitored specs.
|
51
46
|
def rcov
|
52
|
-
"#{rcov_cmd} -T --exclude \"#{rcov_ignores}\" -Ilib #{spec_cmd} -- " +
|
53
|
-
end
|
54
|
-
|
55
|
-
def recent?
|
56
|
-
@recent == true
|
57
|
-
end
|
58
|
-
|
59
|
-
# Maximum amount of seconds since a file has been changed for it to count as
|
60
|
-
# recently changed.
|
61
|
-
def recent_time
|
62
|
-
@recent_time || DEFAULT_RECENT_TIME
|
47
|
+
"#{rcov_cmd} -T --exclude \"#{rcov_ignores}\" -Ilib #{spec_cmd} -- " + known_specs.join(" ")
|
63
48
|
end
|
64
49
|
|
65
50
|
# Command line string to run rspec for an array of specs. Defaults to all specs.
|
66
|
-
def rspec(specs=
|
51
|
+
def rspec(specs=known_specs)
|
67
52
|
"#{spec_cmd} #{specs.join(" ")} #{spec_opts}"
|
68
53
|
end
|
69
54
|
|
@@ -71,10 +56,6 @@ class Minitest
|
|
71
56
|
@source_dirs || DEFAULT_SOURCE_DIRS
|
72
57
|
end
|
73
58
|
|
74
|
-
def source_extensions
|
75
|
-
@source_extensions || DEFAULT_SOURCE_EXTENSIONS
|
76
|
-
end
|
77
|
-
|
78
59
|
def rcov_cmd
|
79
60
|
@rcov_cmd ||= find_rcov_cmd
|
80
61
|
end
|
@@ -90,23 +71,19 @@ class Minitest
|
|
90
71
|
|
91
72
|
def start
|
92
73
|
@active = true
|
93
|
-
|
94
|
-
|
95
|
-
if self.file_spec.values.uniq.size == 0
|
96
|
-
puts "There are no specs to run."
|
97
|
-
return
|
98
|
-
end
|
99
|
-
|
100
|
-
need_testing = find_first_run_specs
|
101
|
-
|
74
|
+
@dir_monitor = DirMonitor.new(source_dirs)
|
102
75
|
trap_int_for_rcov
|
103
76
|
while active? do
|
77
|
+
reset_need_testing
|
78
|
+
@dir_monitor.scan_new_or_changed_with_spec do |file, spec|
|
79
|
+
known_specs << spec
|
80
|
+
need_testing << spec
|
81
|
+
end
|
104
82
|
if need_testing.size > 0
|
105
83
|
print "\nTesting files: #{need_testing.join(" ")}\n"
|
106
84
|
system rspec(need_testing)
|
107
85
|
end
|
108
86
|
sleep 1
|
109
|
-
need_testing = find_specs_to_check
|
110
87
|
end
|
111
88
|
end
|
112
89
|
|
@@ -119,86 +96,17 @@ class Minitest
|
|
119
96
|
end
|
120
97
|
end
|
121
98
|
|
122
|
-
|
123
|
-
self.file_spec.values.uniq.sort
|
124
|
-
end
|
99
|
+
private
|
125
100
|
|
126
|
-
private
|
127
|
-
|
128
|
-
def find_first_run_specs
|
129
|
-
need_checking = self.file_mtime.keys.dup
|
130
|
-
specs_to_check = []
|
131
|
-
if first_run? and recent?
|
132
|
-
need_checking.reject! { |file| @file_mtime[file] < ( Time.now - recent_time ) }
|
133
|
-
if need_checking.size > 0
|
134
|
-
puts "This first run will only test files changed in the last hour. All other files are still monitored."
|
135
|
-
else
|
136
|
-
puts "No files were changed in the last hour, so no files are tested for the first run."
|
137
|
-
end
|
138
|
-
end
|
139
|
-
specs_to_check = need_checking.map {|f| @file_spec[f]}
|
140
|
-
specs_to_check.uniq!
|
141
|
-
specs_to_check.sort!
|
142
|
-
@first_run = false
|
143
|
-
return specs_to_check
|
144
|
-
end
|
145
|
-
|
146
|
-
def find_sources_for_spec(spec)
|
147
|
-
found_files = []
|
148
|
-
for dir in self.source_dirs
|
149
|
-
next unless spec[0,4]=='spec'
|
150
|
-
|
151
|
-
file = spec.dup
|
152
|
-
file[0,4]=dir
|
153
|
-
file.gsub!("_spec.",".")
|
154
|
-
candidates = self.source_extensions.map { |ext| file.gsub(/[^.]+\Z/, ext)}
|
155
|
-
candidates = candidates.select { |f| File.exist?(f) }
|
156
|
-
found_files += candidates
|
157
|
-
end
|
158
|
-
found_files.uniq!
|
159
|
-
return found_files
|
160
|
-
end
|
161
|
-
|
162
101
|
def find_rcov_cmd
|
163
102
|
`which rcov`.strip
|
164
103
|
end
|
165
|
-
|
104
|
+
|
166
105
|
def find_spec_cmd
|
167
106
|
`which spec`.strip
|
168
107
|
end
|
169
108
|
|
170
|
-
def
|
171
|
-
|
172
|
-
# If a spec changes, run it again.
|
173
|
-
map_file_to_spec(spec,spec)
|
174
|
-
for file in find_sources_for_spec(spec)
|
175
|
-
map_file_to_spec(file,spec)
|
176
|
-
end
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
def find_specs_to_check
|
181
|
-
specs = []
|
182
|
-
@file_mtime.each do |file, old_mtime|
|
183
|
-
current_mtime = File.mtime(file)
|
184
|
-
if current_mtime != old_mtime
|
185
|
-
specs << @file_spec[file]
|
186
|
-
store_mtime file
|
187
|
-
end
|
188
|
-
end
|
189
|
-
specs.uniq!
|
190
|
-
specs.sort!
|
191
|
-
return specs
|
192
|
-
end
|
193
|
-
|
194
|
-
def map_file_to_spec(file,spec)
|
195
|
-
return if @file_mtime.has_key? file
|
196
|
-
@file_spec[file.dup]=spec.dup
|
197
|
-
store_mtime file
|
198
|
-
store_mtime spec
|
199
|
-
end
|
200
|
-
|
201
|
-
def store_mtime(file)
|
202
|
-
@file_mtime[file.dup] = File.mtime(file)
|
109
|
+
def reset_need_testing
|
110
|
+
@need_testing = Set.new
|
203
111
|
end
|
204
112
|
end
|
data/spec/dir_monitor_spec.rb
CHANGED
@@ -11,7 +11,7 @@ describe DirMonitor, ".new" do
|
|
11
11
|
dm = DirMonitor.new(%w[lib app])
|
12
12
|
dm.dirs.should == ['lib','app']
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
it "should have no known files" do
|
16
16
|
dm = DirMonitor.new('lib')
|
17
17
|
dm.known_files.should == []
|
@@ -36,7 +36,7 @@ describe DirMonitor, "#scan_new" do
|
|
36
36
|
Dir.stub!(:glob).with('lib/**/*').and_return(@known_files)
|
37
37
|
@dm = DirMonitor.new 'lib'
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
it "should yield the names of all new files" do
|
41
41
|
yield_results = []
|
42
42
|
@dm.scan_new do |file|
|
@@ -44,7 +44,7 @@ describe DirMonitor, "#scan_new" do
|
|
44
44
|
end
|
45
45
|
yield_results.should == @known_files
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
it "should not yield known file names" do
|
49
49
|
known_files2 = %w[lib/minitest.rb lib/dir_monitor2.rb]
|
50
50
|
Dir.stub!(:glob).with('lib/**/*').and_return(@known_files, known_files2)
|
@@ -64,7 +64,7 @@ describe DirMonitor, "#scan_new_with_spec" do
|
|
64
64
|
Dir.stub!(:glob).with('lib/**/*').and_return([@file])
|
65
65
|
@dm = DirMonitor.new 'lib'
|
66
66
|
end
|
67
|
-
|
67
|
+
|
68
68
|
it "should yield new files and their specs" do
|
69
69
|
File.should_receive(:exists?).with(@spec).and_return(true)
|
70
70
|
results = []
|
@@ -73,7 +73,7 @@ describe DirMonitor, "#scan_new_with_spec" do
|
|
73
73
|
end
|
74
74
|
results.should == [{@file=>@spec}]
|
75
75
|
end
|
76
|
-
|
76
|
+
|
77
77
|
it "should not yield files with non-existent specs" do
|
78
78
|
File.should_receive(:exists?).with(@spec).and_return(false)
|
79
79
|
results = []
|
@@ -93,7 +93,7 @@ describe DirMonitor, "#scan_changed" do
|
|
93
93
|
@dm = DirMonitor.new 'lib'
|
94
94
|
@dm.scan
|
95
95
|
end
|
96
|
-
|
96
|
+
|
97
97
|
it "should yield the names of changed known files" do
|
98
98
|
changes = []
|
99
99
|
@dm.scan_changed do |changed_file|
|
@@ -101,7 +101,7 @@ describe DirMonitor, "#scan_changed" do
|
|
101
101
|
end
|
102
102
|
changes.should == [@file]
|
103
103
|
end
|
104
|
-
|
104
|
+
|
105
105
|
it "should not yield the names of files which did not change since last scan" do
|
106
106
|
@dm.scan_changed { |f| }
|
107
107
|
changes = []
|
@@ -134,7 +134,7 @@ describe DirMonitor, "scan_changed_with_spec" do
|
|
134
134
|
@dm = DirMonitor.new 'lib'
|
135
135
|
@dm.scan
|
136
136
|
end
|
137
|
-
|
137
|
+
|
138
138
|
it "should yield the file name and spec name of changed files with an existing spec" do
|
139
139
|
File.should_receive(:exists?).with(@spec).and_return(true)
|
140
140
|
changes = []
|
@@ -163,7 +163,7 @@ describe DirMonitor, "scan_new_or_changed_with_spec" do
|
|
163
163
|
File.stub!(:mtime).with(@file).and_return(@time)
|
164
164
|
@dm = DirMonitor.new 'lib'
|
165
165
|
end
|
166
|
-
|
166
|
+
|
167
167
|
it "should yield a file and spec when a file is new" do
|
168
168
|
results = []
|
169
169
|
@dm.scan_new_or_changed_with_spec do |file, spec|
|
@@ -171,7 +171,7 @@ describe DirMonitor, "scan_new_or_changed_with_spec" do
|
|
171
171
|
end
|
172
172
|
results.should == [{@file=>@spec}]
|
173
173
|
end
|
174
|
-
|
174
|
+
|
175
175
|
it "should yield a file and spec when a file is not new but has changed" do
|
176
176
|
@dm.scan
|
177
177
|
@dm.scan_changed {|f|}
|
@@ -182,7 +182,7 @@ describe DirMonitor, "scan_new_or_changed_with_spec" do
|
|
182
182
|
end
|
183
183
|
results.should == [{@file=>@spec}]
|
184
184
|
end
|
185
|
-
|
185
|
+
|
186
186
|
it "should not yield a file and spec when a file is not new and has not changed" do
|
187
187
|
@dm.scan
|
188
188
|
@dm.scan_changed {|f|}
|
@@ -198,19 +198,19 @@ describe DirMonitor, "#spec_for" do
|
|
198
198
|
before(:each) do
|
199
199
|
@dm = DirMonitor.new
|
200
200
|
end
|
201
|
-
|
201
|
+
|
202
202
|
it "should find the spec for a given file" do
|
203
203
|
file = 'lib/dir_monitor.rb'
|
204
204
|
spec = 'spec/dir_monitor_spec.rb'
|
205
205
|
@dm.spec_for(file).should == spec
|
206
206
|
end
|
207
|
-
|
207
|
+
|
208
208
|
it "should find the spec for non-ruby files" do
|
209
209
|
file = 'app/views/posts/post.html.haml'
|
210
210
|
spec = 'spec/views/posts/post.html.haml_spec.rb'
|
211
211
|
@dm.spec_for(file).should == spec
|
212
212
|
end
|
213
|
-
|
213
|
+
|
214
214
|
it "should map specs to themselves" do
|
215
215
|
spec = 'spec/dir_monitor_spec.rb'
|
216
216
|
@dm.spec_for(spec).should == spec
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: Narnach-minitest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wes Oldenbeuving
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-
|
12
|
+
date: 2008-08-14 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|