Narnach-minitest 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
- # - Lookup all spec files in the spec/ directory.
7
- # - Lookup all possible associated files in the lib/ and app/ directories.
8
- # - Remember the mtimes (last modification times) of all relevant files.
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 :source_extensions
19
- attr_accessor :spec_cmd
20
- attr_accessor :spec_opts
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
- DEFAULT_RECENT_TIME = 3600
24
- DEFAULT_SOURCE_DIRS = %w[lib app]
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} -- " + self.unique_specs.join(" ")
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=self.unique_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
- find_specs
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
- def unique_specs
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 find_specs
171
- Dir.glob("spec/**/*_spec.rb").each do |spec|
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
@@ -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.2.2
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-06-21 00:00:00 -07:00
12
+ date: 2008-08-14 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency