Class: Minitest::TestTask

Inherits:
Rake::TaskLib
  • Object
show all
Defined in:
lib/minitest/test_task.rb

Overview

Minitest::TestTask is a rake helper that generates several rake tasks under the main test task’s name-space.

task <name>      :: the main test task
task <name>:cmd  :: prints the command to use
task <name>:deps :: runs each test file by itself to find dependency errors
task <name>:slow :: runs the tests and reports the slowest 25 tests.

Examples:

Minitest::TestTask.create

The most basic and default setup.

Minitest::TestTask.create :my_tests

The most basic/default setup, but with a custom name

Minitest::TestTask.create :unit do |t|
  t.test_globs = ["test/unit/**/*_test.rb"]
  t.warning = false
end

Customize the name and only run unit tests.

NOTE: To hook this task up to the default, make it a dependency:

task default: :unit

Constant Summary collapse

WINDOWS =

:nodoc:

RbConfig::CONFIG["host_os"] =~ /mswin|mingw/

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name = :test) ⇒ TestTask

Use TestTask.create instead.



109
110
111
112
113
114
115
116
117
118
119
# File 'lib/minitest/test_task.rb', line 109

def initialize name = :test # :nodoc:
  self.extra_args   = []
  self.framework    = %(require "minitest/autorun")
  self.libs         = %w[lib test .]
  self.name         = name
  self.test_globs   = ["test/**/test_*.rb",
                       "test/**/*_test.rb"]
  self.test_prelude = nil
  self.verbose      = Rake.application.options.trace
  self.warning      = true
end

Instance Attribute Details

#extra_argsObject

Extra arguments to pass to the tests. Defaults empty but gets populated by a number of enviroment variables:

N (-n flag)

a string or regexp of tests to run.

X (-e flag)

a string or regexp of tests to exclude.

A (arg)

quick way to inject an arbitrary argument (eg A=–help).

See #process_env



62
63
64
# File 'lib/minitest/test_task.rb', line 62

def extra_args
  @extra_args
end

#frameworkObject

The code to load the framework. Defaults to requiring minitest/autorun…

Why do I have this as an option?



70
71
72
# File 'lib/minitest/test_task.rb', line 70

def framework
  @framework
end

#libsObject

Extra library directories to include. Defaults to %w[lib test .]. Also uses $MT_LIB_EXTRAS allowing you to dynamically override/inject directories for custom runs.



77
78
79
# File 'lib/minitest/test_task.rb', line 77

def libs
  @libs
end

#nameObject

The name of the task and base name for the other tasks generated.



82
83
84
# File 'lib/minitest/test_task.rb', line 82

def name
  @name
end

#test_globsObject

File globs to find test files. Defaults to something sensible to find test files under the test directory.



88
89
90
# File 'lib/minitest/test_task.rb', line 88

def test_globs
  @test_globs
end

#test_preludeObject

Optional: Additional ruby to run before the test framework is loaded.



98
99
100
# File 'lib/minitest/test_task.rb', line 98

def test_prelude
  @test_prelude
end

#verboseObject

Print out commands as they run. Defaults to Rake’s trace (-t flag) option.



104
105
106
# File 'lib/minitest/test_task.rb', line 104

def verbose
  @verbose
end

#warningObject

Turn on ruby warnings (-w flag). Defaults to true.



93
94
95
# File 'lib/minitest/test_task.rb', line 93

def warning
  @warning
end

Class Method Details

.create(name = :test, &block) ⇒ Object

Create several test-oriented tasks under name. Takes an optional block to customize variables.



44
45
46
47
48
49
50
# File 'lib/minitest/test_task.rb', line 44

def self.create name = :test, &block
  task = new name
  task.instance_eval(&block) if block
  task.process_env
  task.define
  task
end

Instance Method Details

#defineObject

:nodoc:



163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/minitest/test_task.rb', line 163

def define # :nodoc:
  desc "Run the test suite. Use N, X, A, and TESTOPTS to add flags/args."
  task name do
    ruby make_test_cmd, verbose:verbose
  end

  desc "Print out the test command. Good for profiling and other tools."
  task "#{name}:cmd" do
    puts "ruby #{make_test_cmd}"
  end

  desc "Show which test files fail when run in isolation."
  task "#{name}:isolated" do
    tests = Dir[*self.test_globs].uniq

    # 3 seems to be the magic number... (tho not by that much)
    bad, good, n = {}, [], (ENV.delete("K") || 3).to_i
    file = ENV.delete("F")
    times = {}

    tt0 = Time.now

    n.threads_do tests.sort do |path|
      t0 = Time.now
      output = `#{Gem.ruby} #{make_test_cmd path} 2>&1`
      t1 = Time.now - t0

      times[path] = t1

      if $?.success?
        $stderr.print "."
        good << path
      else
        $stderr.print "x"
        bad[path] = output
      end
    end

    puts "done"
    puts "Ran in %.2f seconds" % [ Time.now - tt0 ]

    if file then
      require "json"
      File.open file, "w" do |io|
        io.puts JSON.pretty_generate times
      end
    end

    unless good.empty?
      puts
      puts "# Good tests:"
      puts
      good.sort.each do |path|
        puts "%.2fs: %s" % [times[path], path]
      end
    end

    unless bad.empty?
      puts
      puts "# Bad tests:"
      puts
      bad.keys.sort.each do |path|
        puts "%.2fs: %s" % [times[path], path]
      end
      puts
      puts "# Bad Test Output:"
      puts
      bad.sort.each do |path, output|
        puts
        puts "# #{path}:"
        puts output
      end
      exit 1
    end
  end

  task "#{name}:deps" => "#{name}:isolated" # now just an alias

  desc "Show bottom 25 tests wrt time."
  task "#{name}:slow" do
    sh ["rake #{name} A=-v",
        "egrep '#test_.* s = .'",
        "sort -n -k2 -t=",
        "tail -25"].join " | "
  end
end

#make_test_cmd(globs = test_globs) ⇒ Object

Generate the test command-line.



253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
# File 'lib/minitest/test_task.rb', line 253

def make_test_cmd globs = test_globs
  tests = []
  tests.concat Dir[*globs].sort.shuffle # TODO: SEED -> srand first?
  tests.map! { |f| %(require "#{f}") }

  runner = []
  runner << test_prelude if test_prelude
  runner << framework
  runner.concat tests
  runner = runner.join "; "

  args  = []
  args << "-I#{libs.join(File::PATH_SEPARATOR)}" unless libs.empty?
  args << "-w" if warning
  args << '-e'
  args << "'#{runner}'"
  args << '--'
  args << extra_args.map(&:shellescape)

  args.join " "
end

#process_envObject

Extract variables from the environment and convert them to command line arguments. See #extra_args.

Environment Variables:

MT_LIB_EXTRAS

Extra libs to dynamically override/inject for custom runs.

N

Tests to run (string or /regexp/).

X

Tests to exclude (string or /regexp/).

A

Any extra arguments. Honors shell quoting.

Deprecated:

TESTOPTS

For argument passing, use A.

N

For parallel testing, use MT_CPU.

FILTER

Same as TESTOPTS.



138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/minitest/test_task.rb', line 138

def process_env
  warn "TESTOPTS is deprecated in Minitest::TestTask. Use A instead" if
    ENV["TESTOPTS"]
  warn "FILTER is deprecated in Minitest::TestTask. Use A instead" if
    ENV["FILTER"]
  warn "N is deprecated in Minitest::TestTask. Use MT_CPU instead" if
    ENV["N"] && ENV["N"].to_i > 0

  lib_extras = (ENV["MT_LIB_EXTRAS"] || "").split File::PATH_SEPARATOR
  self.libs[0,0] = lib_extras

  extra_args << "-n" << ENV["N"]                      if ENV["N"]
  extra_args << "-e" << ENV["X"]                      if ENV["X"]
  extra_args.concat Shellwords.split(ENV["TESTOPTS"]) if ENV["TESTOPTS"]
  extra_args.concat Shellwords.split(ENV["FILTER"])   if ENV["FILTER"]
  extra_args.concat Shellwords.split(ENV["A"])        if ENV["A"]

  ENV.delete "N" if ENV["N"]

  # TODO? RUBY_DEBUG = ENV["RUBY_DEBUG"]
  # TODO? ENV["RUBY_FLAGS"]

  extra_args.compact!
end