m 1.4.0 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,7 +2,9 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "coveralls", :require => false, :group => :coverage
5
+ gem "coveralls", require: false
6
+ gem "benchmark-ips"
7
+ gem "allocation_stats"
6
8
  gem "test-unit"
7
9
 
8
- gemspec :path => "../"
10
+ gemspec path: "../"
@@ -1,80 +1,71 @@
1
1
  PATH
2
- remote: ../
2
+ remote: ..
3
3
  specs:
4
- m (1.3.4)
4
+ m (1.5.1)
5
5
  method_source (>= 0.6.7)
6
6
  rake (>= 0.9.2.2)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- activesupport (4.2.3)
12
- i18n (~> 0.7)
13
- json (~> 1.7, >= 1.7.7)
14
- minitest (~> 5.1)
15
- thread_safe (~> 0.3, >= 0.3.4)
16
- tzinfo (~> 1.1)
17
- appraisal (2.0.2)
11
+ activesupport (6.1.4.1)
12
+ concurrent-ruby (~> 1.0, >= 1.0.2)
13
+ i18n (>= 1.6, < 2)
14
+ minitest (>= 5.1)
15
+ tzinfo (~> 2.0)
16
+ zeitwerk (~> 2.3)
17
+ allocation_stats (0.1.5)
18
+ appraisal (2.4.1)
18
19
  bundler
19
20
  rake
20
21
  thor (>= 0.14.0)
21
- coveralls (0.8.2)
22
- json (~> 1.8)
23
- rest-client (>= 1.6.8, < 2)
24
- simplecov (~> 0.10.0)
22
+ benchmark-ips (2.9.1)
23
+ concurrent-ruby (1.1.9)
24
+ coveralls (0.8.23)
25
+ json (>= 1.8, < 3)
26
+ simplecov (~> 0.16.1)
25
27
  term-ansicolor (~> 1.3)
26
- thor (~> 0.19.1)
27
- docile (1.1.5)
28
- domain_name (0.5.24)
29
- unf (>= 0.0.5, < 1.0.0)
30
- http-cookie (1.0.2)
31
- domain_name (~> 0.5)
32
- i18n (0.7.0)
33
- json (1.8.3)
34
- json (1.8.3-java)
35
- method_source (0.8.2)
36
- mime-types (2.6.1)
37
- minitest (5.7.0)
38
- mustache (1.0.2)
39
- netrc (0.10.3)
40
- power_assert (0.2.4)
41
- rake (10.4.2)
42
- rdiscount (2.1.8)
43
- redcarpet (3.3.2)
44
- rest-client (1.8.0)
45
- http-cookie (>= 1.0.2, < 2.0)
46
- mime-types (>= 1.16, < 3.0)
47
- netrc (~> 0.7)
28
+ thor (>= 0.19.4, < 2.0)
29
+ tins (~> 1.6)
30
+ docile (1.4.0)
31
+ i18n (1.8.10)
32
+ concurrent-ruby (~> 1.0)
33
+ json (2.5.1)
34
+ method_source (1.0.0)
35
+ minitest (5.14.4)
36
+ mustache (1.1.1)
37
+ power_assert (2.0.1)
38
+ rake (13.0.6)
39
+ rdiscount (2.2.0.2)
40
+ redcarpet (3.5.1)
48
41
  rocco (0.8.2)
49
42
  mustache
50
43
  redcarpet
51
- simplecov (0.10.0)
52
- docile (~> 1.1.0)
53
- json (~> 1.8)
44
+ simplecov (0.16.1)
45
+ docile (~> 1.1)
46
+ json (>= 1.8, < 3)
54
47
  simplecov-html (~> 0.10.0)
55
- simplecov-html (0.10.0)
56
- term-ansicolor (1.3.2)
48
+ simplecov-html (0.10.2)
49
+ sync (0.5.0)
50
+ term-ansicolor (1.7.1)
57
51
  tins (~> 1.0)
58
- test-unit (3.1.2)
52
+ test-unit (3.4.4)
59
53
  power_assert
60
- thor (0.19.1)
61
- thread_safe (0.3.5)
62
- thread_safe (0.3.5-java)
63
- tins (1.5.4)
64
- tzinfo (1.2.2)
65
- thread_safe (~> 0.1)
66
- unf (0.1.4)
67
- unf_ext
68
- unf (0.1.4-java)
69
- unf_ext (0.0.7.1)
54
+ thor (1.1.0)
55
+ tins (1.29.1)
56
+ sync
57
+ tzinfo (2.0.4)
58
+ concurrent-ruby (~> 1.0)
59
+ zeitwerk (2.4.2)
70
60
 
71
61
  PLATFORMS
72
- java
73
62
  ruby
74
63
 
75
64
  DEPENDENCIES
76
65
  activesupport
66
+ allocation_stats
77
67
  appraisal
68
+ benchmark-ips
78
69
  coveralls
79
70
  m!
80
71
  rdiscount
@@ -82,4 +73,4 @@ DEPENDENCIES
82
73
  test-unit
83
74
 
84
75
  BUNDLED WITH
85
- 1.10.6
76
+ 2.2.26
@@ -0,0 +1,7 @@
1
+ require_relative "../../test/test_helper.rb"
2
+
3
+ class ErrorTest < MTest
4
+ def test_purposeful_error
5
+ raise RuntimeError
6
+ end
7
+ end
data/lib/m/executor.rb CHANGED
@@ -12,7 +12,7 @@ module M
12
12
 
13
13
  def execute
14
14
  # Locate tests to run that may be inside of this line. There could be more than one!
15
- tests_to_run = tests.within(testable.line)
15
+ tests_to_run = tests.within(testable.lines)
16
16
 
17
17
  # If we found any tests,
18
18
  if tests_to_run.size > 0
@@ -23,10 +23,10 @@ module M
23
23
  test_arguments = ["-n", "/^(#{test_names})$/"]
24
24
 
25
25
  # directly run the tests from here and exit with the status of the tests passing or failing
26
- runner.run(test_arguments)
26
+ runner.run(test_arguments + testable.passthrough_options)
27
27
  elsif tests.size > 0
28
28
  # Otherwise we found no tests on this line, so you need to pick one.
29
- message = "No tests found on line #{testable.line}. Valid tests to run:\n\n"
29
+ message = "No tests found on line #{testable.lines.join(', ')}. Valid tests to run:\n\n"
30
30
 
31
31
  # For every test ordered by line number,
32
32
  # spit out the test name and line number where it starts,
data/lib/m/frameworks.rb CHANGED
@@ -30,12 +30,16 @@ module M
30
30
  self.class.test_unit?
31
31
  end
32
32
 
33
+ def self.minitest_version_major
34
+ defined?(Minitest) ? Minitest::Unit::VERSION.slice(/\d+/) : nil
35
+ end
36
+
33
37
  def self.minitest5?
34
- defined?(Minitest) && Minitest::Unit::VERSION.start_with?("5")
38
+ minitest_version_major == "5"
35
39
  end
36
40
 
37
41
  def self.minitest4?
38
- defined?(MiniTest)
42
+ minitest_version_major == "4"
39
43
  end
40
44
 
41
45
  def self.test_unit?
data/lib/m/parser.rb CHANGED
@@ -15,8 +15,17 @@ module M
15
15
  else
16
16
  parse_options! argv
17
17
 
18
- # Parse out ARGV, it should be coming in in a format like `test/test_file.rb:9`
19
- testable.file, testable.line = argv.first.split(':')
18
+ if argv.first.start_with?("--")
19
+ exec "rake test #{argv.join}"
20
+ exit 0
21
+ else
22
+ # Parse out ARGV, it should be coming in in a format like `test/test_file.rb:9:19`
23
+ parsed = argv.shift.split(':')
24
+ testable.file = parsed.shift
25
+ testable.lines = parsed if testable.lines.none?
26
+ # Anything else on ARGV will be passed along to the runner
27
+ testable.passthrough_options = argv
28
+ end
20
29
 
21
30
  # If this file is a directory, not a file, run the tests inside of this directory
22
31
  if Dir.exist?(testable.file)
@@ -25,15 +34,16 @@ module M
25
34
  Rake::TestTask.new(:m_custom) do |t|
26
35
  t.libs << 'test'
27
36
  t.libs << 'spec'
28
- t.test_files = FileList["#{testable.file}/*test*.rb", "#{testable.file}/*spec*.rb"]
37
+ t.test_files = FileList[wildcard("test"), wildcard("spec")]
38
+ t.warning = false
29
39
  end
30
40
  # Invoke the rake task and exit, hopefully it'll work!
31
41
  begin
32
42
  Rake::Task['m_custom'].invoke
33
43
  rescue RuntimeError
34
- exit
44
+ exit(1)
35
45
  ensure
36
- exit
46
+ exit($?.exitstatus)
37
47
  end
38
48
  else
39
49
  return testable
@@ -64,11 +74,24 @@ module M
64
74
 
65
75
  opts.on '-l', '--line LINE', Integer, 'Line number for file.' do |line|
66
76
  p "parsing line #{line}"
67
- testable.line = line
77
+ testable.lines = [line]
78
+ end
79
+
80
+ opts.on '-r', '--recursive DIR', 'Search provided directory recursively.' do |directory|
81
+ testable.recursive = true
82
+ argv << directory
68
83
  end
69
84
 
70
85
  opts.parse! argv
71
86
  end
72
87
  end
88
+
89
+ def wildcard(type)
90
+ if testable.recursive
91
+ "#{testable.file}/**/*#{type}*.rb"
92
+ else
93
+ "#{testable.file}/*#{type}*.rb"
94
+ end
95
+ end
73
96
  end
74
97
  end
@@ -17,13 +17,12 @@ module M
17
17
 
18
18
  # Slice out tests that may be within the given line.
19
19
  # Returns a new TestCollection with the results.
20
- def within(line)
20
+ def within(lines)
21
21
  # Into a new collection, filter only the tests that...
22
- self.class.new(select do |test|
23
- # are within the given boundary for this method
24
- # or include everything if the line given is zero (no line)
25
- line.zero? || (test.start_line..test.end_line).include?(line)
26
- end)
22
+ collection = select do |test|
23
+ lines.none? || lines.any? { |line| (test.start_line..test.end_line).include?(line) }
24
+ end
25
+ self.class.new(collection)
27
26
  end
28
27
 
29
28
  # Used to line up method names in `#sprintf` when `m` aborts
data/lib/m/test_method.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require "method_source"
2
+
1
3
  module M
2
4
  ### Simple data structure for what a test method contains.
3
5
  #
@@ -22,7 +24,7 @@ module M
22
24
  #
23
25
  # The end line should be the number of line breaks in the method source,
24
26
  # added to the starting line and subtracted by one.
25
- require "method_source"
27
+
26
28
  end_line = method.source.split("\n").size + start_line - 1
27
29
 
28
30
  # Shove the given attributes into a new databag
data/lib/m/testable.rb CHANGED
@@ -1,15 +1,17 @@
1
1
  module M
2
2
  class Testable
3
- attr_accessor :file
4
- attr_reader :line
3
+ attr_accessor :file, :recursive, :passthrough_options
4
+ attr_reader :lines
5
5
 
6
- def initialize(file = "", line = nil)
6
+ def initialize(file = "", lines = [], recursive = false)
7
7
  @file = file
8
- @line = line
8
+ @recursive = recursive
9
+ @passthrough_options = []
10
+ self.lines = lines
9
11
  end
10
12
 
11
- def line=(line)
12
- @line ||= line.to_i
13
+ def lines=(lines)
14
+ @lines = lines.map(&:to_i)
13
15
  end
14
16
  end
15
17
  end
data/lib/m/version.rb ADDED
@@ -0,0 +1,3 @@
1
+ module M
2
+ VERSION = "1.6.0"
3
+ end
data/lib/m.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  ### M, your metal test runner
2
2
  # Maybe this gem should have a longer name? Metal?
3
- require_relative 'version'
3
+ require_relative 'm/version'
4
4
  require_relative 'm/frameworks'
5
5
  require_relative 'm/runner'
6
6
 
@@ -2,28 +2,28 @@ require 'test_helper'
2
2
 
3
3
  class ActiveSupportTest < MTest
4
4
  def test_run_simple_test_by_line_number
5
- output = m('examples/active_support_example_test.rb:11')
6
- assert_output(/1 tests, 1 assertions/, output)
5
+ output = m('examples/active_support_example_test.rb:12')
6
+ assert_output(/1 (runs|tests), 1 assertions/, output)
7
7
  end
8
8
 
9
9
  def test_runs_entire_test_without_line_number
10
10
  output = m('examples/active_support_example_test.rb')
11
- assert_output(/4 tests/, output)
11
+ assert_output(/4 (runs|tests)/, output)
12
12
  end
13
13
 
14
14
  def test_run_inside_of_test
15
- output = m('examples/active_support_example_test.rb:12')
16
- assert_output(/1 tests, 1 assertions/, output)
15
+ output = m('examples/active_support_example_test.rb:13')
16
+ assert_output(/1 (runs|tests), 1 assertions/, output)
17
17
  end
18
18
 
19
19
  def test_run_on_end_of_test
20
- output = m('examples/active_support_example_test.rb:13')
21
- assert_output(/1 tests, 1 assertions/, output)
20
+ output = m('examples/active_support_example_test.rb:14')
21
+ assert_output(/1 (runs|tests), 1 assertions/, output)
22
22
  end
23
23
 
24
24
  def test_run_inside_big_test
25
- output = m('examples/active_support_example_test.rb:17')
26
- assert_output(/1 tests, 3 assertions/, output)
25
+ output = m('examples/active_support_example_test.rb:18')
26
+ assert_output(/1 (runs|tests), 3 assertions/, output)
27
27
  end
28
28
 
29
29
  def test_run_on_blank_line_orders_tests_by_line_number
@@ -33,21 +33,21 @@ class ActiveSupportTest < MTest
33
33
  expected = <<-EOF
34
34
  No tests found on line 2. Valid tests to run:
35
35
 
36
- test_normal: m examples/active_support_example_test.rb:7
37
- test_carrot: m examples/active_support_example_test.rb:11
38
- test_daikon: m examples/active_support_example_test.rb:15
39
- test_eggplant_fig: m examples/active_support_example_test.rb:21
36
+ test_normal: m examples/active_support_example_test.rb:8
37
+ test_carrot: m examples/active_support_example_test.rb:12
38
+ test_daikon: m examples/active_support_example_test.rb:16
39
+ test_eggplant_fig: m examples/active_support_example_test.rb:22
40
40
  EOF
41
41
  assert_equal expected.strip, output
42
42
  end
43
43
 
44
44
  def test_run_on_test_with_spaces
45
- output = m('examples/active_support_example_test.rb:21')
46
- assert_output(/1 tests, 1 assertions/, output)
45
+ output = m('examples/active_support_example_test.rb:22')
46
+ assert_output(/1 (runs|tests), 1 assertions/, output)
47
47
  end
48
48
 
49
49
  def test_run_on_test_with_unescaped_regular_express_characters
50
- output = m('examples/active_support_unescaped_example_test.rb:7')
51
- assert_output(/1 tests, 1 assertions/, output)
50
+ output = m('examples/active_support_unescaped_example_test.rb:8')
51
+ assert_output(/1 (runs|tests), 1 assertions/, output)
52
52
  end
53
53
  end
@@ -3,7 +3,7 @@ require 'test_helper'
3
3
  class EverythingTest < MTest
4
4
  def test_runs_entire_test_suite_with_no_arguments
5
5
  output = m('')
6
- assert_output(/12 tests/, output)
6
+ assert_output(/12 (runs|tests)/, output)
7
7
  end
8
8
 
9
9
  def test_missing_file_gives_a_decent_error_message
@@ -19,15 +19,15 @@ class EverythingTest < MTest
19
19
 
20
20
  def test_running_tests_within_a_subdirectory
21
21
  output = m('examples/subdir')
22
- assert_output(/3 tests/, output)
22
+ assert_output(/3 (runs|tests)/, output)
23
23
 
24
24
  output = m('examples')
25
- assert_output(/12 tests/, output)
25
+ assert_output(/12 (runs|tests)/, output)
26
26
  end
27
27
 
28
28
  def test_running_tests_with_failures_within_a_subdirectory
29
29
  output = m('examples/subdir_with_failures')
30
- assert_output(/1 tests, 1 assertions, 1 failures/, output)
30
+ assert_output_for_failed_execution(/1 (runs|tests), 1 assertions, 1 failures/, output)
31
31
  end
32
32
 
33
33
  def test_blank_file_is_quieter
@@ -1,3 +1,4 @@
1
+ require 'active_support'
1
2
  require 'active_support/test_case'
2
3
 
3
4
  class ActiveSupportExampleTest < ActiveSupport::TestCase
@@ -1,3 +1,4 @@
1
+ require 'active_support'
1
2
  require 'active_support/test_case'
2
3
 
3
4
  class ActiveSupportExampleTest < ActiveSupport::TestCase
@@ -0,0 +1,36 @@
1
+ require 'minitest/unit'
2
+
3
+ class Meme
4
+ def i_can_has_cheezburger?
5
+ "OHAI!"
6
+ end
7
+
8
+ def will_it_blend?
9
+ "YES!"
10
+ end
11
+ end
12
+
13
+ Test = M::Frameworks.minitest4? ? MiniTest::Unit::TestCase : Minitest::Test
14
+
15
+ class TestMeme < Test
16
+ def setup
17
+ @meme = Meme.new
18
+ end
19
+
20
+ def test_that_kitty_can_eat
21
+ assert_equal "OHAI!", @meme.i_can_has_cheezburger?
22
+ end
23
+
24
+ def test_that_it_will_not_blend
25
+ refute_match(/^maybe/i, @meme.will_it_blend?)
26
+ refute_match(/^no/i, @meme.will_it_blend?)
27
+ refute_match(/^lolz/i, @meme.will_it_blend?)
28
+ end
29
+
30
+ def test_that_kitty_can_eat_two_time
31
+ assert_equal "OHAI!", @meme.i_can_has_cheezburger?
32
+ assert_equal "OHAI!", @meme.i_can_has_cheezburger?
33
+ end
34
+
35
+ Minitest.after_run { p "ran after run block" } if Minitest.respond_to?(:after_run)
36
+ end