Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 73692f9

Browse files
committed
! Added Minitest::TestTask.
[git-p4: depot-paths = "//src/minitest/dev/": change = 13430]
1 parent 2d64718 commit 73692f9

4 files changed

Lines changed: 386 additions & 6 deletions

File tree

Manifest.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ lib/minitest/pride.rb
1717
lib/minitest/pride_plugin.rb
1818
lib/minitest/spec.rb
1919
lib/minitest/test.rb
20+
lib/minitest/test_task.rb
2021
lib/minitest/unit.rb
2122
test/minitest/metametameta.rb
2223
test/minitest/test_minitest_assertions.rb
@@ -25,3 +26,4 @@ test/minitest/test_minitest_mock.rb
2526
test/minitest/test_minitest_reporter.rb
2627
test/minitest/test_minitest_spec.rb
2728
test/minitest/test_minitest_test.rb
29+
test/minitest/test_minitest_test_task.rb

README.rdoc

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ extract-method refactorings still apply.
7070
* minitest/mock - a simple and clean mock/stub system.
7171
* minitest/benchmark - an awesome way to assert your algorithm's performance.
7272
* minitest/pride - show your pride in testing!
73+
* minitest/test_task - a full-featured and clean rake task generator.
7374
* Incredibly small and fast runner, but no bells and whistles.
7475
* Written by squishy human beings. Software can never be perfect. We will all eventually die.
7576

@@ -264,9 +265,8 @@ new non-existing method:
264265

265266
=== Running Your Tests
266267

267-
Ideally, you'll use a rake task to run your tests, either piecemeal or
268-
all at once. Both rake and rails ship with rake tasks for running your
269-
tests. BUT! You don't have to:
268+
Ideally, you'll use a rake task to run your tests (see below), either
269+
piecemeal or all at once. BUT! You don't have to:
270270

271271
% ruby -Ilib:test test/minitest/test_minitest_test.rb
272272
Run options: --seed 37685
@@ -294,18 +294,45 @@ provided via plugins. To see them, simply run with +--help+:
294294
-p, --pride Pride. Show your testing pride!
295295
-a, --autotest Connect to autotest server.
296296

297+
=== Rake Tasks
298+
297299
You can set up a rake task to run all your tests by adding this to your Rakefile:
298300

299-
require "rake/testtask"
301+
require "minitest/test_task"
302+
303+
Minitest::TestTask.create # named test, sensible defaults
300304

301-
Rake::TestTask.new(:test) do |t|
305+
# or more explicitly:
306+
307+
Minitest::TestTask.create(:test) do |t|
302308
t.libs << "test"
303309
t.libs << "lib"
304-
t.test_files = FileList["test/**/test_*.rb"]
310+
t.warning = false
311+
t.test_globs = ["test/**/*_test.rb"]
305312
end
306313

307314
task :default => :test
308315

316+
Each of these will generate 4 tasks:
317+
318+
rake test :: Run the test suite.
319+
rake test:cmd :: Print out the test command.
320+
rake test:isolated :: Show which test files fail when run separately.
321+
rake test:slow :: Show bottom 25 tests sorted by time.
322+
323+
=== Rake Task Variables
324+
325+
There are a bunch of variables you can supply to rake to modify the run.
326+
327+
MT_LIB_EXTRAS :: Extra libs to dynamically override/inject for custom runs.
328+
N :: -n: Tests to run (string or /regexp/).
329+
X :: -x: Tests to exclude (string or /regexp/).
330+
A :: Any extra arguments. Honors shell quoting.
331+
MT_CPU :: How many threads to use for parallel test runs
332+
SEED :: -s --seed Sets random seed.
333+
TESTOPTS :: Deprecated, same as A
334+
FILTER :: Deprecated, same as A
335+
309336
== Writing Extensions
310337

311338
To define a plugin, add a file named minitest/XXX_plugin.rb to your

lib/minitest/test_task.rb

Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
require "shellwords"
2+
require "rbconfig"
3+
require "rake/tasklib"
4+
5+
module Minitest # :nodoc:
6+
7+
##
8+
# Minitest::TestTask is a rake helper that generates several rake
9+
# tasks under the main test task's name-space.
10+
#
11+
# task <name> :: the main test task
12+
# task <name>:cmd :: prints the command to use
13+
# task <name>:deps :: runs each test file by itself to find dependency errors
14+
# task <name>:slow :: runs the tests and reports the slowest 25 tests.
15+
#
16+
# Examples:
17+
#
18+
# Minitest::TestTask.create
19+
#
20+
# The most basic and default setup.
21+
#
22+
# Minitest::TestTask.create :my_tests
23+
#
24+
# The most basic/default setup, but with a custom name
25+
#
26+
# Minitest::TestTask.create :unit do |t|
27+
# t.test_globs = ["test/unit/**/*_test.rb"]
28+
# t.warning = false
29+
# end
30+
#
31+
# Customize the name and only run unit tests.
32+
33+
class TestTask < Rake::TaskLib
34+
WINDOWS = RbConfig::CONFIG["host_os"] =~ /mswin|mingw/ # :nodoc:
35+
36+
##
37+
# Create several test-oriented tasks under +name+. Takes an
38+
# optional block to customize variables.
39+
40+
def self.create name = :test, &block
41+
task = new name
42+
task.instance_eval(&block) if block
43+
task.process_env
44+
task.define
45+
task
46+
end
47+
48+
##
49+
# Extra arguments to pass to the tests. Defaults empty but gets
50+
# populated by a number of enviroment variables:
51+
#
52+
# N (-n flag) :: a string or regexp of tests to run.
53+
# X (-e flag) :: a string or regexp of tests to exclude.
54+
# A (arg) :: quick way to inject an arbitrary argument (eg A=--help).
55+
#
56+
# See #process_env
57+
58+
attr_accessor :extra_args
59+
60+
##
61+
# The code to load the framework. Defaults to requiring
62+
# minitest/autorun...
63+
#
64+
# Why do I have this as an option?
65+
66+
attr_accessor :framework
67+
68+
##
69+
# Extra library directories to include. Defaults to %w[lib test
70+
# .]. Also uses $MT_LIB_EXTRAS allowing you to dynamically
71+
# override/inject directories for custom runs.
72+
73+
attr_accessor :libs
74+
75+
##
76+
# The name of the task and base name for the other tasks generated.
77+
78+
attr_accessor :name
79+
80+
##
81+
# File globs to find test files. Defaults to something sensible to
82+
# find test files under the test directory.
83+
84+
attr_accessor :test_globs
85+
86+
##
87+
# Turn on ruby warnings (-w flag). Defaults to true.
88+
89+
attr_accessor :warning
90+
91+
##
92+
# Optional: Additional ruby to run before the test framework is loaded.
93+
94+
attr_accessor :test_prelude
95+
96+
##
97+
# Print out commands as they run. Defaults to Rake's +trace+ (-t
98+
# flag) option.
99+
100+
attr_accessor :verbose
101+
102+
##
103+
# Use TestTask.create instead.
104+
105+
def initialize name = :test # :nodoc:
106+
self.extra_args = []
107+
self.framework = %(require "minitest/autorun")
108+
self.libs = %w[lib test .]
109+
self.name = name
110+
self.test_globs = ["test/**/test_*.rb",
111+
"test/**/*_test.rb"]
112+
self.test_prelude = nil
113+
self.verbose = Rake.application.options.trace
114+
self.warning = true
115+
end
116+
117+
##
118+
# Extract variables from the environment and convert them to
119+
# command line arguments. See #extra_args.
120+
#
121+
# Environment Variables:
122+
#
123+
# MT_LIB_EXTRAS :: Extra libs to dynamically override/inject for custom runs.
124+
# N :: Tests to run (string or /regexp/).
125+
# X :: Tests to exclude (string or /regexp/).
126+
# A :: Any extra arguments. Honors shell quoting.
127+
#
128+
# Deprecated:
129+
#
130+
# TESTOPTS :: For argument passing, use +A+.
131+
# N :: For parallel testing, use +MT_CPU+.
132+
# FILTER :: Same as +TESTOPTS+.
133+
134+
def process_env
135+
warn "TESTOPTS is deprecated in Minitest::TestTask. Use A instead" if
136+
ENV["TESTOPTS"]
137+
warn "FILTER is deprecated in Minitest::TestTask. Use A instead" if
138+
ENV["FILTER"]
139+
warn "N is deprecated in Minitest::TestTask. Use MT_CPU instead" if
140+
ENV["N"] && ENV["N"].to_i > 0
141+
142+
lib_extras = (ENV["MT_LIB_EXTRAS"] || "").split File::PATH_SEPARATOR
143+
self.libs[0,0] = lib_extras
144+
145+
extra_args << "-n" << ENV["N"] if ENV["N"]
146+
extra_args << "-e" << ENV["X"] if ENV["X"]
147+
extra_args.concat Shellwords.split(ENV["TESTOPTS"]) if ENV["TESTOPTS"]
148+
extra_args.concat Shellwords.split(ENV["FILTER"]) if ENV["FILTER"]
149+
extra_args.concat Shellwords.split(ENV["A"]) if ENV["A"]
150+
151+
ENV.delete "N" if ENV["N"]
152+
153+
# TODO? RUBY_DEBUG = ENV["RUBY_DEBUG"]
154+
# TODO? ENV["RUBY_FLAGS"]
155+
156+
extra_args.compact!
157+
end
158+
159+
def define # :nodoc:
160+
default_tasks = []
161+
162+
desc "Run the test suite. Use N, X, A, and TESTOPTS to add flags/args."
163+
task name do
164+
ruby make_test_cmd, verbose:verbose
165+
end
166+
167+
desc "Print out the test command. Good for profiling and other tools."
168+
task "#{name}:cmd" do
169+
puts "ruby #{make_test_cmd}"
170+
end
171+
172+
desc "Show which test files fail when run in isolation."
173+
task "#{name}:isolated" do
174+
tests = Dir[*self.test_globs].uniq
175+
176+
# 3 seems to be the magic number... (tho not by that much)
177+
bad, good, n = {}, [], (ENV.delete("K") || 3).to_i
178+
file = ENV.delete("F")
179+
times = {}
180+
181+
tt0 = Time.now
182+
183+
n.threads_do tests.sort do |path|
184+
t0 = Time.now
185+
output = `#{Gem.ruby} #{make_test_cmd path} 2>&1`
186+
t1 = Time.now - t0
187+
188+
times[path] = t1
189+
190+
if $?.success?
191+
$stderr.print "."
192+
good << path
193+
else
194+
$stderr.print "x"
195+
bad[path] = output
196+
end
197+
end
198+
199+
puts "done"
200+
puts "Ran in %.2f seconds" % [ Time.now - tt0 ]
201+
202+
if file then
203+
require "json"
204+
File.open file, "w" do |io|
205+
io.puts JSON.pretty_generate times
206+
end
207+
end
208+
209+
unless good.empty?
210+
puts
211+
puts "# Good tests:"
212+
puts
213+
good.sort.each do |path|
214+
puts "%.2fs: %s" % [times[path], path]
215+
end
216+
end
217+
218+
unless bad.empty?
219+
puts
220+
puts "# Bad tests:"
221+
puts
222+
bad.keys.sort.each do |path|
223+
puts "%.2fs: %s" % [times[path], path]
224+
end
225+
puts
226+
puts "# Bad Test Output:"
227+
puts
228+
bad.sort.each do |path, output|
229+
puts
230+
puts "# #{path}:"
231+
puts output
232+
end
233+
exit 1
234+
end
235+
end
236+
237+
task "#{name}:deps" => "#{name}:isolated" # now just an alias
238+
239+
desc "Show bottom 25 tests wrt time."
240+
task "#{name}:slow" do
241+
sh ["rake #{name} TESTOPTS=-v",
242+
"egrep '#test_.* s = .'",
243+
"sort -n -k2 -t=",
244+
"tail -25"].join " | "
245+
end
246+
247+
default_tasks << name
248+
249+
desc "Run the default task(s)."
250+
task :default => default_tasks
251+
end
252+
253+
##
254+
# Generate the test command-line.
255+
256+
def make_test_cmd globs = test_globs
257+
tests = []
258+
tests.concat Dir[*globs].sort.shuffle # TODO: SEED -> srand first?
259+
tests.map! { |f| %(require "#{f}") }
260+
261+
runner = []
262+
runner << test_prelude if test_prelude
263+
runner << framework
264+
runner.concat tests
265+
runner = runner.join "; "
266+
267+
args = []
268+
args << "-I#{libs.join(File::PATH_SEPARATOR)}" unless libs.empty?
269+
args << "-w" if warning
270+
args << '-e'
271+
args << "'#{runner}'"
272+
args << '--'
273+
args << extra_args.map(&:shellescape)
274+
275+
args.join " "
276+
end
277+
end
278+
end
279+
280+
class Work < Queue
281+
def initialize jobs = []
282+
super()
283+
284+
jobs.each do |job|
285+
self << job
286+
end
287+
288+
close
289+
end
290+
end
291+
292+
class Integer
293+
def threads_do(jobs) # :nodoc:
294+
require "thread"
295+
q = Work.new jobs
296+
297+
self.times.map {
298+
Thread.new do
299+
while job = q.pop # go until quit value
300+
yield job
301+
end
302+
end
303+
}.each(&:join)
304+
end
305+
end

0 commit comments

Comments
 (0)