diff options
Diffstat (limited to 'railties/lib/rails/test_unit')
-rw-r--r-- | railties/lib/rails/test_unit/minitest_plugin.rb | 14 | ||||
-rw-r--r-- | railties/lib/rails/test_unit/reporter.rb | 22 | ||||
-rw-r--r-- | railties/lib/rails/test_unit/runner.rb | 137 | ||||
-rw-r--r-- | railties/lib/rails/test_unit/testing.rake | 48 |
4 files changed, 195 insertions, 26 deletions
diff --git a/railties/lib/rails/test_unit/minitest_plugin.rb b/railties/lib/rails/test_unit/minitest_plugin.rb new file mode 100644 index 0000000000..70ce9d3360 --- /dev/null +++ b/railties/lib/rails/test_unit/minitest_plugin.rb @@ -0,0 +1,14 @@ +require "minitest" +require "rails/test_unit/reporter" + +def Minitest.plugin_rails_init(options) + self.reporter << Rails::TestUnitReporter.new(options[:io], options) + if $rails_test_runner && (method = $rails_test_runner.find_method) + options[:filter] = method + end + + if !($rails_test_runner && $rails_test_runner.show_backtrace?) + Minitest.backtrace_filter = Rails.backtrace_cleaner + end +end +Minitest.extensions << 'rails' diff --git a/railties/lib/rails/test_unit/reporter.rb b/railties/lib/rails/test_unit/reporter.rb new file mode 100644 index 0000000000..64e99626eb --- /dev/null +++ b/railties/lib/rails/test_unit/reporter.rb @@ -0,0 +1,22 @@ +require "minitest" + +module Rails + class TestUnitReporter < Minitest::StatisticsReporter + def report + return if results.empty? + io.puts + io.puts "Failed tests:" + io.puts + io.puts aggregated_results + end + + def aggregated_results # :nodoc: + filtered_results = results.dup + filtered_results.reject!(&:skipped?) unless options[:verbose] + filtered_results.map do |result| + location, line = result.method(result.name).source_location + "bin/rails test #{location}:#{line}" + end.join "\n" + end + end +end diff --git a/railties/lib/rails/test_unit/runner.rb b/railties/lib/rails/test_unit/runner.rb new file mode 100644 index 0000000000..5573fa6904 --- /dev/null +++ b/railties/lib/rails/test_unit/runner.rb @@ -0,0 +1,137 @@ +require "optparse" +require "rake/file_list" +require "method_source" + +module Rails + class TestRunner + class Options + def self.parse(args) + options = { backtrace: !ENV["BACKTRACE"].nil?, name: nil, environment: "test" } + + opt_parser = ::OptionParser.new do |opts| + opts.banner = "Usage: bin/rails test [options] [file or directory]" + + opts.separator "" + opts.on("-e", "--environment [ENV]", + "Run tests in the ENV environment") do |env| + options[:environment] = env.strip + end + opts.separator "" + opts.separator "Filter options:" + opts.separator "" + opts.separator <<-DESC + You can run a single test by appending the line number to filename: + + bin/rails test test/models/user_test.rb:27 + + DESC + + opts.on("-n", "--name [NAME]", + "Only run tests matching NAME") do |name| + options[:name] = name + end + opts.on("-p", "--pattern [PATTERN]", + "Only run tests matching PATTERN") do |pattern| + options[:name] = "/#{pattern}/" + end + + opts.separator "" + opts.separator "Output options:" + + opts.on("-b", "--backtrace", + "Show the complete backtrace") do + options[:backtrace] = true + end + + opts.separator "" + opts.separator "Common options:" + + opts.on_tail("-h", "--help", "Show this message") do + puts opts + exit + end + end + + opt_parser.order!(args) + + options[:patterns] = [] + while arg = args.shift + if (file_and_line = arg.split(':')).size > 1 + options[:filename], options[:line] = file_and_line + options[:filename] = File.expand_path options[:filename] + options[:line] &&= options[:line].to_i + else + arg = arg.gsub(':', '') + if Dir.exist?("#{arg}") + options[:patterns] << File.expand_path("#{arg}/**/*_test.rb") + elsif File.file?(arg) + options[:patterns] << File.expand_path(arg) + end + end + end + options + end + end + + def initialize(options = {}) + @options = options + end + + def self.run(arguments) + options = Rails::TestRunner::Options.parse(arguments) + Rails::TestRunner.new(options).run + end + + def run + $rails_test_runner = self + ENV["RAILS_ENV"] = @options[:environment] + run_tests + end + + def find_method + return @options[:name] if @options[:name] + return unless @options[:line] + method = test_methods.find do |location, test_method, start_line, end_line| + location == @options[:filename] && + (start_line..end_line).include?(@options[:line].to_i) + end + method[1] if method + end + + def show_backtrace? + @options[:backtrace] + end + + def test_files + return [@options[:filename]] if @options[:filename] + if @options[:patterns] && @options[:patterns].count > 0 + pattern = @options[:patterns] + else + pattern = "test/**/*_test.rb" + end + Rake::FileList[pattern] + end + + private + def run_tests + test_files.to_a.each do |file| + require File.expand_path file + end + end + + def test_methods + methods_map = [] + suites = Minitest::Runnable.runnables.shuffle + suites.each do |suite_class| + suite_class.runnable_methods.each do |test_method| + method = suite_class.instance_method(test_method) + location = method.source_location + start_line = location.last + end_line = method.source.split("\n").size + start_line - 1 + methods_map << [File.expand_path(location.first), test_method, start_line, end_line] + end + end + methods_map + end + end +end diff --git a/railties/lib/rails/test_unit/testing.rake b/railties/lib/rails/test_unit/testing.rake index 957deb8a60..0f26621b59 100644 --- a/railties/lib/rails/test_unit/testing.rake +++ b/railties/lib/rails/test_unit/testing.rake @@ -1,48 +1,44 @@ -require 'rake/testtask' -require 'rails/test_unit/sub_test_task' +require "rails/test_unit/runner" task default: :test -desc 'Runs test:units, test:functionals, test:generators, test:integration, test:jobs together' +desc "Runs all tests in test folder" task :test do - Rails::TestTask.test_creator(Rake.application.top_level_tasks).invoke_rake_task + $: << "test" + args = ARGV[0] == "test" ? ARGV[1..-1] : [] + Rails::TestRunner.run(args) end namespace :test do task :prepare do - # Placeholder task for other Railtie and plugins to enhance. See Active Record for an example. + # Placeholder task for other Railtie and plugins to enhance. + # If used with Active Record, this task runs before the database schema is synchronized. end - task :run => ['test:units', 'test:functionals', 'test:generators', 'test:integration', 'test:jobs'] + task :run => %w[test] - # Inspired by: http://ngauthier.com/2012/02/quick-tests-with-bash.html - desc "Run tests quickly by merging all types and not resetting db" - Rails::TestTask.new(:all) do |t| - t.pattern = "test/**/*_test.rb" - end - - namespace :all do - desc "Run tests quickly, but also reset db" - task :db => %w[db:test:prepare test:all] - end - - Rails::TestTask.new(single: "test:prepare") + desc "Run tests quickly, but also reset db" + task :db => %w[db:test:prepare test] ["models", "helpers", "controllers", "mailers", "integration", "jobs"].each do |name| - Rails::TestTask.new(name => "test:prepare") do |t| - t.pattern = "test/#{name}/**/*_test.rb" + task name => "test:prepare" do + $: << "test" + Rails::TestRunner.run(["test/#{name}"]) end end - Rails::TestTask.new(generators: "test:prepare") do |t| - t.pattern = "test/lib/generators/**/*_test.rb" + task :generators => "test:prepare" do + $: << "test" + Rails::TestRunner.run(["test/lib/generators"]) end - Rails::TestTask.new(units: "test:prepare") do |t| - t.pattern = 'test/{models,helpers,unit}/**/*_test.rb' + task :units => "test:prepare" do + $: << "test" + Rails::TestRunner.run(["test/models", "test/helpers", "test/unit"]) end - Rails::TestTask.new(functionals: "test:prepare") do |t| - t.pattern = 'test/{controllers,mailers,functional}/**/*_test.rb' + task :functionals => "test:prepare" do + $: << "test" + Rails::TestRunner.run(["test/controllers", "test/mailers", "test/functional"]) end end |