bundle gem会默认生成以下rakefile,其中包含了对rake/testtask的使用

require "bundler/gem_tasks"
require "rake/testtask"

Rake::TestTask.new(:test) do |t|
  t.libs << "test"
  t.libs << "lib"
  t.test_files = FileList['test/**/*_test.rb']
end

task :default => :test


Rake::TestTask源码如下,它根据block中收集到的参数,来拼接成cli,然后用rake的dsl语句“ruby”来调用

testtask本身对测试脚本的位置默认是lib,不过pattern又默认是test/test*.rb …… 所幸gem默认给它增加test目录,并设置pattern为test/**/*_test.rb

当然你也自己可以通过block来对libs和pattern这两个attr_accessor来重写(也可以在Rake::TestTask对象生成后直接操作其attr_accessor),甚至在运行前通过TEST参数来制定只执行某个脚本

module Rake
  class TestTask < TaskLib

    attr_accessor :libs
    attr_accessor :pattern

    def initialize(name=:test)
      @name = name
      @libs = ["lib"]
      # ...
      @description = "Run tests" + (@name == :test ? "" : " for #{@name}")
      @deps = []
      if @name.is_a?(Hash)
        @deps = @name.values.first
        @name = @name.keys.first
      end
      yield self if block_given?
      @pattern = "test/test*.rb" if @pattern.nil? && @test_files.nil?
      define
    end

    def define
      desc @description
      task @name => Array(deps) do
        FileUtilsExt.verbose(@verbose) do
          puts "Use TESTOPTS=\"--verbose\" to pass --verbose" \
            ", etc. to runners." if ARGV.include? "--verbose"
          args =
            "#{ruby_opts_string} #{run_code} " +
            "#{file_list_string} #{option_list}"
          ruby args do |ok, status|
            if !ok && status.respond_to?(:signaled?) && status.signaled?
              raise SignalException.new(status.termsig)
            elsif !ok
              status  = "Command failed with status (#{status.exitstatus})"
              details = ": [ruby #{args}]"
              message =
                if Rake.application.options.trace or @verbose
                  status + details
                else
                  status
                end

              fail message
            end
          end
        end
      end
      self
    end

    def file_list_string # :nodoc:
      file_list.map { |fn| "\"#{fn}\"" }.join(" ")
    end

    def file_list # :nodoc:
      if ENV["TEST"]
        FileList[ENV["TEST"]]
      else
        result = []
        result += @test_files.to_a if @test_files
        result += FileList[@pattern].to_a if @pattern
        result
      end
    end