m 0.0.1 → 1.0.0.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -1
- data/.travis.yml +3 -0
- data/README +18 -0
- data/Rakefile +63 -1
- data/lib/m.rb +191 -9
- data/lib/m/test_collection.rb +18 -0
- data/lib/m/test_method.rb +25 -2
- data/m.gemspec +6 -2
- data/test/Rakefile +6 -0
- data/test/active_support_test.rb +11 -11
- data/test/bench.rb +10 -0
- data/test/everything_test.rb +23 -0
- data/test/examples/active_support_example_test.rb +2 -1
- data/test/examples/multiple_example_test.rb +2 -1
- data/test/examples/subdir/a_test.rb +7 -0
- data/test/examples/subdir/b_test.rb +7 -0
- data/test/examples/subdir/c_test.rb +7 -0
- data/test/examples/test_unit_example_test.rb +1 -1
- data/test/multiple_test.rb +3 -3
- data/test/test_helper.rb +3 -2
- data/test/test_unit_test.rb +8 -8
- metadata +48 -15
- data/README.md +0 -74
- data/lib/m/runner.rb +0 -46
- data/lib/m/version.rb +0 -3
data/.gitignore
CHANGED
data/README
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
________________________________________________________________________________
|
2
|
+
________________________/\\\\____________/\\\\__________________________________
|
3
|
+
________________________\/\\\\\\________/\\\\\\_________________________________
|
4
|
+
_________________________\/\\\//\\\____/\\\//\\\________________________________
|
5
|
+
__________________________\/\\\\///\\\/\\\/_\/\\\_______________________________
|
6
|
+
___________________________\/\\\__\///\\\/___\/\\\______________________________
|
7
|
+
____________________________\/\\\____\///_____\/\\\_____________________________
|
8
|
+
_____________________________\/\\\_____________\/\\\____________________________
|
9
|
+
______________________________\/\\\_____________\/\\\___________________________
|
10
|
+
_______________________________\///______________\///___________________________
|
11
|
+
________________________________________________________________________________
|
12
|
+
|
13
|
+
|
14
|
+
m is a better test/unit test runner for Ruby that can run tests by
|
15
|
+
line number (and more!). Please see the Rocco generated docs for
|
16
|
+
more information:
|
17
|
+
|
18
|
+
<http://quaran.to/m/>
|
data/Rakefile
CHANGED
@@ -1,10 +1,72 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
2
|
require "bundler/gem_tasks"
|
3
|
+
require 'rake/clean'
|
3
4
|
require "rake/testtask"
|
4
5
|
|
5
|
-
task :default => :test
|
6
|
+
task :default => [:test]
|
6
7
|
|
7
8
|
Rake::TestTask.new do |t|
|
8
9
|
t.libs << 'test'
|
9
10
|
t.pattern = 'test/*_test.rb'
|
10
11
|
end
|
12
|
+
|
13
|
+
desc 'Run simple benchmarks'
|
14
|
+
task :bench do
|
15
|
+
exec "ruby test/bench.rb"
|
16
|
+
end
|
17
|
+
|
18
|
+
# ROCCO ===============================================================
|
19
|
+
|
20
|
+
require 'rdiscount'
|
21
|
+
require 'rocco/tasks'
|
22
|
+
Rocco::make 'docs/'
|
23
|
+
|
24
|
+
desc 'Build rocco docs'
|
25
|
+
task :docs => :rocco
|
26
|
+
directory 'docs/'
|
27
|
+
|
28
|
+
desc 'Build docs and open in browser for the reading'
|
29
|
+
task :read => :docs do
|
30
|
+
sh 'open docs/lib/m.html'
|
31
|
+
end
|
32
|
+
|
33
|
+
# Make index.html a copy of rocco.html
|
34
|
+
file 'docs/index.html' => 'docs/lib/m.html' do |f|
|
35
|
+
cp 'docs/lib/m.html', 'docs/index.html', :preserve => true
|
36
|
+
end
|
37
|
+
|
38
|
+
task :docs => 'docs/index.html'
|
39
|
+
CLEAN.include 'docs/index.html'
|
40
|
+
|
41
|
+
# Alias for docs task
|
42
|
+
task :doc => :docs
|
43
|
+
|
44
|
+
# GITHUB PAGES ===============================================================
|
45
|
+
|
46
|
+
desc "really kill docs folder"
|
47
|
+
task :clean_docs do
|
48
|
+
sh "rm -rf docs/"
|
49
|
+
end
|
50
|
+
|
51
|
+
desc 'Update gh-pages branch'
|
52
|
+
task :pages => [:clean_docs, 'docs/.git', :docs] do
|
53
|
+
rev = `git rev-parse --short HEAD`.strip
|
54
|
+
Dir.chdir 'docs' do
|
55
|
+
sh "mv lib/m m"
|
56
|
+
sh "mv lib/m.html m.html"
|
57
|
+
sh "git add -A"
|
58
|
+
sh "git commit -m 'rebuild pages from #{rev}'" do |ok,res|
|
59
|
+
if ok
|
60
|
+
verbose { puts "gh-pages updated" }
|
61
|
+
sh "git push -q o HEAD:gh-pages"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Update the pages/ directory clone
|
68
|
+
file 'docs/.git' => ['docs/'] do |f|
|
69
|
+
sh "cd docs && git init -q && git remote add o ../.git" if !File.exist?(f.name)
|
70
|
+
sh "cd docs && git fetch -q o && git reset -q --hard o/gh-pages && git rm -r . && git commit -m 'blank out' && touch ."
|
71
|
+
end
|
72
|
+
CLOBBER.include 'docs/.git'
|
data/lib/m.rb
CHANGED
@@ -1,15 +1,197 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
1
|
+
#`m` stands for metal, which is a better test/unit test runner that can run
|
2
|
+
#tests by line number.
|
3
|
+
#
|
4
|
+
#[![m ci](https://secure.travis-ci.org/qrush/m.png)](http://travis-ci.org/qrush/m)
|
5
|
+
#
|
6
|
+
#![Rush is a heavy metal band. Look it up on Wikipedia.](https://raw.github.com/qrush/m/master/rush.jpg)
|
7
|
+
#
|
8
|
+
#<sub>[Rush at the Bristol Colston Hall May 1979](http://www.flickr.com/photos/8507625@N02/3468299995/)</sub>
|
9
|
+
### Install
|
10
|
+
#
|
11
|
+
#Install via:
|
12
|
+
#
|
13
|
+
# gem install m
|
14
|
+
#
|
15
|
+
#`m` is Ruby 1.9+ only. Sorry, but `method_source`, `sourcify`, and `ruby_parser`
|
16
|
+
#all have trouble with 1.8 so I'm giving up and only supporting 1.9 for now.
|
17
|
+
#Patches are welcome!
|
18
|
+
#
|
19
|
+
### Usage
|
20
|
+
#
|
21
|
+
#Basically, I was sick of using the `-n` flag to grab one test to run. Instead, I
|
22
|
+
#prefer how RSpec's test runner allows tests to be run by line number.
|
23
|
+
#
|
24
|
+
#Given this file:
|
25
|
+
#
|
26
|
+
# $ cat -n test/example_test.rb
|
27
|
+
# 1 require 'test/unit'
|
28
|
+
# 2
|
29
|
+
# 3 class ExampleTest < Test::Unit::TestCase
|
30
|
+
# 4 def test_apple
|
31
|
+
# 5 assert_equal 1, 1
|
32
|
+
# 6 end
|
33
|
+
# 7
|
34
|
+
# 8 def test_banana
|
35
|
+
# 9 assert_equal 1, 1
|
36
|
+
# 10 end
|
37
|
+
# 11 end
|
38
|
+
#
|
39
|
+
#You can run a test by line number, using format `m TEST_FILE:LINE_NUMBER_OF_TEST`:
|
40
|
+
#
|
41
|
+
# $ m test/example_test.rb:4
|
42
|
+
# Run options: -n /test_apple/
|
43
|
+
#
|
44
|
+
# # Running tests:
|
45
|
+
#
|
46
|
+
# .
|
47
|
+
#
|
48
|
+
# Finished tests in 0.000525s, 1904.7619 tests/s, 1904.7619 assertions/s.
|
49
|
+
#
|
50
|
+
# 1 tests, 1 assertions, 0 failures, 0 errors, 0 skips
|
51
|
+
#
|
52
|
+
#Hit the wrong line number? No problem, `m` helps you out:
|
53
|
+
#
|
54
|
+
# $ m test/example_test.rb:2
|
55
|
+
# No tests found on line 2. Valid tests to run:
|
56
|
+
#
|
57
|
+
# test_apple: m test/examples/test_unit_example_test.rb:4
|
58
|
+
# test_banana: m test/examples/test_unit_example_test.rb:8
|
59
|
+
#
|
60
|
+
#Want to run the whole test? Just leave off the line number.
|
61
|
+
#
|
62
|
+
# $ m test/example_test.rb
|
63
|
+
# Run options:
|
64
|
+
#
|
65
|
+
# # Running tests:
|
66
|
+
#
|
67
|
+
# ..
|
68
|
+
#
|
69
|
+
# Finished tests in 0.001293s, 1546.7904 tests/s, 3093.5808 assertions/s.
|
70
|
+
#
|
71
|
+
# 1 tests, 2 assertions, 0 failures, 0 errors, 0 skips
|
72
|
+
#
|
73
|
+
#`m` also works with `ActiveSupport::TestCase` as well, so it will work great with
|
74
|
+
#your Rails test suites.
|
75
|
+
#
|
76
|
+
### License
|
77
|
+
#
|
78
|
+
#This gem is MIT licensed, please see `LICENSE` for more information.
|
10
79
|
|
80
|
+
### M, your metal test runner
|
81
|
+
# Maybe this gem should have a longer name? Metal?
|
11
82
|
module M
|
83
|
+
VERSION = "1.0.0.pre"
|
84
|
+
|
85
|
+
# Accept arguments coming from bin/m and run tests.
|
12
86
|
def self.run(argv)
|
13
87
|
Runner.new(argv).run
|
14
88
|
end
|
89
|
+
|
90
|
+
### Runner is in charge of running your tests.
|
91
|
+
# Instead of slamming all of this junk in an `M` class, it's here instead.
|
92
|
+
class Runner
|
93
|
+
def initialize(argv)
|
94
|
+
@argv = argv
|
95
|
+
end
|
96
|
+
|
97
|
+
# There's two steps to running our tests:
|
98
|
+
# 1. Parsing the given input for the tests we need to find (or groups of tests)
|
99
|
+
# 2. Run those tests we found that match what you wanted
|
100
|
+
def run
|
101
|
+
parse
|
102
|
+
execute
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
def parse
|
108
|
+
# With no arguments,
|
109
|
+
if @argv.empty?
|
110
|
+
# Just shell out to `rake test`.
|
111
|
+
exec "rake test"
|
112
|
+
else
|
113
|
+
# Parse out ARGV, it should be coming in in a format like `test/test_file.rb:9`
|
114
|
+
@file, line = @argv.first.split(':')
|
115
|
+
@line = line.to_i
|
116
|
+
|
117
|
+
# If this file is a directory, not a file, run the tests inside of this directory
|
118
|
+
if Dir.exist?(@file)
|
119
|
+
# Make a new rake test task with a hopefully unique name, and run every test looking file in it
|
120
|
+
require "rake/testtask"
|
121
|
+
Rake::TestTask.new(:m_custom) do |t|
|
122
|
+
t.libs << 'test'
|
123
|
+
t.pattern = "#{@file}/*test*.rb"
|
124
|
+
end
|
125
|
+
# Invoke the rake task and exit, hopefully it'll work!
|
126
|
+
Rake::Task['m_custom'].invoke
|
127
|
+
exit
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def execute
|
133
|
+
# Locate tests to run that may be inside of this line. There could be more than one!
|
134
|
+
tests_to_run = tests.within(@line)
|
135
|
+
|
136
|
+
# If we found any tests,
|
137
|
+
if tests_to_run.size > 0
|
138
|
+
# assemble the regexp to run these tests,
|
139
|
+
test_names = tests_to_run.map(&:name).join('|')
|
140
|
+
|
141
|
+
# directly run the tests from here and exit with the status of the tests passing or failing
|
142
|
+
exit Test::Unit::AutoRunner.run(false, nil, ["-n", "/(#{test_names})/"])
|
143
|
+
else
|
144
|
+
# Otherwise we found no tests on this line, so you need to pick one.
|
145
|
+
message = "No tests found on line #{@line}. Valid tests to run:\n\n"
|
146
|
+
|
147
|
+
# For every test ordered by line number,
|
148
|
+
# spit out the test name and line number where it starts,
|
149
|
+
tests.by_line_number do |test|
|
150
|
+
message << "#{sprintf("%0#{tests.column_size}s", test.name)}: m #{@file}:#{test.start_line}\n"
|
151
|
+
end
|
152
|
+
|
153
|
+
# fail like a good unix process should.
|
154
|
+
abort message
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Finds all test suites in this test file, with test methods included.
|
159
|
+
def suites
|
160
|
+
# Since we're not using `ruby -Itest` to run the tests, we need to add this directory to the `LOAD_PATH`
|
161
|
+
$:.unshift "./test"
|
162
|
+
|
163
|
+
begin
|
164
|
+
# Fire up this Ruby file. Let's hope it actually has tests.
|
165
|
+
load @file
|
166
|
+
rescue LoadError => e
|
167
|
+
# Fail with a happier error message instead of spitting out a backtrace from this gem
|
168
|
+
abort "Failed loading test file:\n#{e.message}"
|
169
|
+
end
|
170
|
+
|
171
|
+
# Use some janky internal test/unit API to group test methods by test suite.
|
172
|
+
Test::Unit::TestCase.test_suites.inject({}) do |suites, suite_class|
|
173
|
+
# End up with a hash of suite class name to an array of test methods, so we can later find them and ignore empty test suites
|
174
|
+
suites[suite_class] = suite_class.test_methods if suite_class.test_methods.size > 0
|
175
|
+
suites
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
# Shoves tests together in our custom container and collection classes.
|
180
|
+
# Memoize it since it's unnecessary to do this more than one for a given file.
|
181
|
+
def tests
|
182
|
+
@tests ||= begin
|
183
|
+
require "m/test_collection"
|
184
|
+
require "m/test_method"
|
185
|
+
# With each suite and array of tests,
|
186
|
+
# and with each test method present in this test file,
|
187
|
+
# shove a new test method into this collection.
|
188
|
+
suites.inject(TestCollection.new) do |collection, (suite_class, test_methods)|
|
189
|
+
test_methods.each do |test_method|
|
190
|
+
collection << TestMethod.create(suite_class, test_method)
|
191
|
+
end
|
192
|
+
collection
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
15
197
|
end
|
data/lib/m/test_collection.rb
CHANGED
@@ -1,24 +1,42 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
|
1
3
|
module M
|
4
|
+
### Custom wrapper around an array of test methods
|
5
|
+
# In charge of some smart querying, filtering, sorting, etc on the the
|
6
|
+
# test methods
|
2
7
|
class TestCollection
|
3
8
|
include Enumerable
|
4
9
|
extend Forwardable
|
10
|
+
# This should act like an array, so forward some common methods over to the
|
11
|
+
# internal collection
|
5
12
|
def_delegators :@collection, :size, :<<, :each
|
6
13
|
|
7
14
|
def initialize(collection = nil)
|
8
15
|
@collection = collection || []
|
9
16
|
end
|
10
17
|
|
18
|
+
# Slice out tests that may be within the given line.
|
19
|
+
# Returns a new TestCollection with the results.
|
11
20
|
def within(line)
|
21
|
+
# Into a new collection, filter only the tests that...
|
12
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)
|
13
25
|
line.zero? || (test.start_line..test.end_line).include?(line)
|
14
26
|
end)
|
15
27
|
end
|
16
28
|
|
29
|
+
# Used to line up method names in `#sprintf` when `m` aborts
|
17
30
|
def column_size
|
31
|
+
# Boil down the collection of test methods to the name of the method's
|
32
|
+
# size, then find the largest one
|
18
33
|
@column_size ||= map { |test| test.name.to_s.size }.max
|
19
34
|
end
|
20
35
|
|
36
|
+
# Be considerate when printing out tests and pre-sort them by line number
|
21
37
|
def by_line_number(&block)
|
38
|
+
# On each member of the collection, sort by line number and yield
|
39
|
+
# the block into the sorted collection
|
22
40
|
sort_by(&:start_line).each(&block)
|
23
41
|
end
|
24
42
|
end
|
data/lib/m/test_method.rb
CHANGED
@@ -1,10 +1,33 @@
|
|
1
|
+
require "ostruct"
|
2
|
+
|
1
3
|
module M
|
4
|
+
### Simple data structure for what a test method contains.
|
5
|
+
#
|
6
|
+
# Too lazy to make a class for this when it's really just a bag of data
|
7
|
+
# without any behavior.
|
8
|
+
#
|
9
|
+
# Includes the name of this method, what line on the file it begins on,
|
10
|
+
# and where it ends.
|
2
11
|
class TestMethod < Struct.new(:name, :start_line, :end_line)
|
12
|
+
# Set up a new test method for this test suite class
|
3
13
|
def self.create(suite_class, test_method)
|
4
|
-
method
|
14
|
+
# Hopefully it's been defined as an instance method, so we'll need to
|
15
|
+
# look up the ruby Method instance for it
|
16
|
+
method = suite_class.instance_method(test_method)
|
17
|
+
|
18
|
+
# Ruby can find the starting line for us, so pull that out of the array
|
5
19
|
start_line = method.source_location.last
|
6
|
-
end_line = method.source.split("\n").size + start_line - 1
|
7
20
|
|
21
|
+
# Ruby can't find the end line however, and I'm too lazy to write
|
22
|
+
# a parser. Instead, `method_source` adds `Method#source` so we can
|
23
|
+
# deduce this ourselves.
|
24
|
+
#
|
25
|
+
# The end line should be the number of line breaks in the method source,
|
26
|
+
# added to the starting line and subtracted by one.
|
27
|
+
require "method_source"
|
28
|
+
end_line = method.source.split("\n").size + start_line - 1
|
29
|
+
|
30
|
+
# Shove the given attributes into a new databag
|
8
31
|
new(test_method, start_line, end_line)
|
9
32
|
end
|
10
33
|
end
|
data/m.gemspec
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require './lib/m'
|
2
|
+
|
1
3
|
Gem::Specification.new do |gem|
|
2
4
|
gem.authors = ["Nick Quaranto"]
|
3
5
|
gem.email = ["nick@quaran.to"]
|
@@ -8,11 +10,13 @@ Gem::Specification.new do |gem|
|
|
8
10
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
9
11
|
gem.name = "m"
|
10
12
|
gem.require_paths = ["lib"]
|
11
|
-
gem.version =
|
13
|
+
gem.version = M::VERSION
|
12
14
|
|
13
15
|
gem.add_runtime_dependency "method_source", "~> 0.6.7"
|
14
|
-
gem.
|
16
|
+
gem.add_runtime_dependency "rake", "~> 0.9.2.2"
|
15
17
|
gem.add_development_dependency "activesupport"
|
18
|
+
gem.add_development_dependency "rdiscount"
|
19
|
+
gem.add_development_dependency "rocco"
|
16
20
|
|
17
21
|
gem.required_ruby_version = "~> 1.9"
|
18
22
|
|
data/test/Rakefile
ADDED
data/test/active_support_test.rb
CHANGED
@@ -2,47 +2,47 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class ActiveSupportTest < MTest
|
4
4
|
def test_run_simple_test_by_line_number
|
5
|
-
output = m('
|
5
|
+
output = m('examples/active_support_example_test.rb:12')
|
6
6
|
assert_output /1 tests, 1 assertions/, output
|
7
7
|
end
|
8
8
|
|
9
9
|
def test_runs_entire_test_without_line_number
|
10
|
-
output = m('
|
10
|
+
output = m('examples/active_support_example_test.rb')
|
11
11
|
assert_output /4 tests/, output
|
12
12
|
end
|
13
13
|
|
14
14
|
def test_run_inside_of_test
|
15
|
-
output = m('
|
15
|
+
output = m('examples/active_support_example_test.rb:13')
|
16
16
|
assert_output /1 tests, 1 assertions/, output
|
17
17
|
end
|
18
18
|
|
19
19
|
def test_run_on_end_of_test
|
20
|
-
output = m('
|
20
|
+
output = m('examples/active_support_example_test.rb:14')
|
21
21
|
assert_output /1 tests, 1 assertions/, output
|
22
22
|
end
|
23
23
|
|
24
24
|
def test_run_inside_big_test
|
25
|
-
output = m('
|
25
|
+
output = m('examples/active_support_example_test.rb:18')
|
26
26
|
assert_output /1 tests, 3 assertions/, output
|
27
27
|
end
|
28
28
|
|
29
29
|
def test_run_on_blank_line_orders_tests_by_line_number
|
30
|
-
output = m('
|
30
|
+
output = m('examples/active_support_example_test.rb:2')
|
31
31
|
|
32
32
|
assert !$?.success?
|
33
33
|
expected = <<-EOF
|
34
34
|
No tests found on line 2. Valid tests to run:
|
35
35
|
|
36
|
-
test_normal: m
|
37
|
-
test_carrot: m
|
38
|
-
test_daikon: m
|
39
|
-
test_eggplant_fig: m
|
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('
|
45
|
+
output = m('examples/active_support_example_test.rb:22')
|
46
46
|
assert_output /1 tests, 1 assertions/, output
|
47
47
|
end
|
48
48
|
end
|
data/test/bench.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class EverythingTest < MTest
|
4
|
+
def test_runs_entire_test_suite_with_no_arguments
|
5
|
+
output = m('')
|
6
|
+
assert_output /10 tests/, output
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_missing_file_gives_a_decent_error_message
|
10
|
+
output = m('examples/thisdoesnexist_test.rb')
|
11
|
+
assert !$?.success?
|
12
|
+
assert_match /Failed loading test file/, output
|
13
|
+
assert_match /cannot load such file/, output
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_running_tests_within_a_subdirectory
|
17
|
+
output = m('examples/subdir')
|
18
|
+
assert_output /3 tests/, output
|
19
|
+
|
20
|
+
output = m('examples')
|
21
|
+
assert_output /10 tests/, output
|
22
|
+
end
|
23
|
+
end
|
data/test/multiple_test.rb
CHANGED
@@ -2,17 +2,17 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class MultipleTest < MTest
|
4
4
|
def test_run_simple_test_by_line_number
|
5
|
-
output = m('
|
5
|
+
output = m('examples/multiple_example_test.rb:11')
|
6
6
|
assert_output /1 tests, 1 assertions/, output
|
7
7
|
end
|
8
8
|
|
9
9
|
def test_runs_entire_test_without_line_number
|
10
|
-
output = m('
|
10
|
+
output = m('examples/multiple_example_test.rb')
|
11
11
|
assert_output /4 tests/, output
|
12
12
|
end
|
13
13
|
|
14
14
|
def test_runs_all_tests_on_given_line_number
|
15
|
-
output = m('
|
15
|
+
output = m('examples/multiple_example_test.rb:6')
|
16
16
|
assert_output /3 tests/, output
|
17
17
|
end
|
18
18
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,10 +1,11 @@
|
|
1
|
-
require 'rubygems'
|
2
1
|
require 'test/unit'
|
3
2
|
require 'active_support/test_case'
|
4
3
|
|
5
4
|
class MTest < Test::Unit::TestCase
|
6
5
|
def m(arguments)
|
7
|
-
|
6
|
+
Dir.chdir("test") do
|
7
|
+
`ruby -I../lib -I. ../bin/m #{arguments} 2>&1`.strip
|
8
|
+
end
|
8
9
|
end
|
9
10
|
|
10
11
|
def assert_output(regexp, output)
|
data/test/test_unit_test.rb
CHANGED
@@ -2,36 +2,36 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class TestUnitTest < MTest
|
4
4
|
def test_run_simple_test_by_line_number
|
5
|
-
output = m('
|
5
|
+
output = m('examples/test_unit_example_test.rb:7')
|
6
6
|
assert_output /1 tests, 1 assertions/, output
|
7
7
|
end
|
8
8
|
|
9
9
|
def test_runs_entire_test_without_line_number
|
10
|
-
output = m('
|
10
|
+
output = m('examples/test_unit_example_test.rb')
|
11
11
|
assert_output /2 tests/, output
|
12
12
|
end
|
13
13
|
|
14
14
|
def test_run_inside_of_test
|
15
|
-
output = m('
|
15
|
+
output = m('examples/test_unit_example_test.rb:8')
|
16
16
|
assert_output /1 tests, 1 assertions/, output
|
17
17
|
end
|
18
18
|
|
19
19
|
def test_run_on_end_of_test
|
20
|
-
output = m('
|
20
|
+
output = m('examples/test_unit_example_test.rb:9')
|
21
21
|
assert_output /1 tests, 1 assertions/, output
|
22
22
|
end
|
23
23
|
|
24
24
|
def test_run_inside_big_test
|
25
|
-
output = m('
|
25
|
+
output = m('examples/test_unit_example_test.rb:14')
|
26
26
|
assert_output /1 tests, 3 assertions/, output
|
27
27
|
end
|
28
28
|
|
29
29
|
def test_run_on_blank_line
|
30
|
-
output = m('
|
30
|
+
output = m('examples/test_unit_example_test.rb:2')
|
31
31
|
|
32
32
|
assert !$?.success?
|
33
33
|
assert_match /No tests found on line 2. Valid tests to run:/, output
|
34
|
-
assert_match %r{ test_apple: m
|
35
|
-
assert_match %r{test_banana: m
|
34
|
+
assert_match %r{ test_apple: m examples/test_unit_example_test\.rb:7}, output
|
35
|
+
assert_match %r{test_banana: m examples/test_unit_example_test\.rb:11}, output
|
36
36
|
end
|
37
37
|
end
|
metadata
CHANGED
@@ -1,19 +1,19 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: m
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.0.pre
|
5
|
+
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Nick Quaranto
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2012-01-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: method_source
|
16
|
-
requirement: &
|
16
|
+
requirement: &70149914984320 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,21 @@ dependencies:
|
|
21
21
|
version: 0.6.7
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70149914984320
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rake
|
27
|
-
requirement: &
|
27
|
+
requirement: &70149914982960 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.9.2.2
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70149914982960
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: activesupport
|
38
|
+
requirement: &70149914982440 !ruby/object:Gem::Requirement
|
28
39
|
none: false
|
29
40
|
requirements:
|
30
41
|
- - ! '>='
|
@@ -32,10 +43,21 @@ dependencies:
|
|
32
43
|
version: '0'
|
33
44
|
type: :development
|
34
45
|
prerelease: false
|
35
|
-
version_requirements: *
|
46
|
+
version_requirements: *70149914982440
|
36
47
|
- !ruby/object:Gem::Dependency
|
37
|
-
name:
|
38
|
-
requirement: &
|
48
|
+
name: rdiscount
|
49
|
+
requirement: &70149914981880 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70149914981880
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: rocco
|
60
|
+
requirement: &70149914981280 !ruby/object:Gem::Requirement
|
39
61
|
none: false
|
40
62
|
requirements:
|
41
63
|
- - ! '>='
|
@@ -43,7 +65,7 @@ dependencies:
|
|
43
65
|
version: '0'
|
44
66
|
type: :development
|
45
67
|
prerelease: false
|
46
|
-
version_requirements: *
|
68
|
+
version_requirements: *70149914981280
|
47
69
|
description:
|
48
70
|
email:
|
49
71
|
- nick@quaran.to
|
@@ -58,19 +80,23 @@ files:
|
|
58
80
|
- Gemfile
|
59
81
|
- Gemfile.lock
|
60
82
|
- LICENSE
|
61
|
-
- README
|
83
|
+
- README
|
62
84
|
- Rakefile
|
63
85
|
- bin/m
|
64
86
|
- lib/m.rb
|
65
|
-
- lib/m/runner.rb
|
66
87
|
- lib/m/test_collection.rb
|
67
88
|
- lib/m/test_method.rb
|
68
|
-
- lib/m/version.rb
|
69
89
|
- m.gemspec
|
70
90
|
- rush.jpg
|
91
|
+
- test/Rakefile
|
71
92
|
- test/active_support_test.rb
|
93
|
+
- test/bench.rb
|
94
|
+
- test/everything_test.rb
|
72
95
|
- test/examples/active_support_example_test.rb
|
73
96
|
- test/examples/multiple_example_test.rb
|
97
|
+
- test/examples/subdir/a_test.rb
|
98
|
+
- test/examples/subdir/b_test.rb
|
99
|
+
- test/examples/subdir/c_test.rb
|
74
100
|
- test/examples/test_unit_example_test.rb
|
75
101
|
- test/multiple_test.rb
|
76
102
|
- test/test_helper.rb
|
@@ -90,9 +116,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
90
116
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
91
117
|
none: false
|
92
118
|
requirements:
|
93
|
-
- - ! '
|
119
|
+
- - ! '>'
|
94
120
|
- !ruby/object:Gem::Version
|
95
|
-
version:
|
121
|
+
version: 1.3.1
|
96
122
|
requirements: []
|
97
123
|
rubyforge_project:
|
98
124
|
rubygems_version: 1.8.11
|
@@ -100,10 +126,17 @@ signing_key:
|
|
100
126
|
specification_version: 3
|
101
127
|
summary: Run test/unit tests by line number. Metal!
|
102
128
|
test_files:
|
129
|
+
- test/Rakefile
|
103
130
|
- test/active_support_test.rb
|
131
|
+
- test/bench.rb
|
132
|
+
- test/everything_test.rb
|
104
133
|
- test/examples/active_support_example_test.rb
|
105
134
|
- test/examples/multiple_example_test.rb
|
135
|
+
- test/examples/subdir/a_test.rb
|
136
|
+
- test/examples/subdir/b_test.rb
|
137
|
+
- test/examples/subdir/c_test.rb
|
106
138
|
- test/examples/test_unit_example_test.rb
|
107
139
|
- test/multiple_test.rb
|
108
140
|
- test/test_helper.rb
|
109
141
|
- test/test_unit_test.rb
|
142
|
+
has_rdoc:
|
data/README.md
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
# m [![m ci](https://secure.travis-ci.org/qrush/m.png)](http://travis-ci.org/qrush/m)
|
2
|
-
|
3
|
-
`m` stands for :metal: (metal), which is a better test/unit test runner. @sferik took `t` so this was the next best option.
|
4
|
-
|
5
|
-
![Rush is a heavy metal band. Look it up on Wikipedia.](https://raw.github.com/qrush/m/master/rush.jpg)
|
6
|
-
|
7
|
-
<sub>[Rush at the Bristol Colston Hall May 1979](http://www.flickr.com/photos/8507625@N02/3468299995/)</sub>
|
8
|
-
|
9
|
-
## Install
|
10
|
-
|
11
|
-
Install via:
|
12
|
-
|
13
|
-
gem install m
|
14
|
-
|
15
|
-
`m` is Ruby 1.9+ only. Sorry, but `method_source`, `sourcify`, and `ruby_parser` all have trouble with 1.8 so I'm giving up and only supporting 1.9 for now. Patches are welcome!
|
16
|
-
|
17
|
-
## Usage
|
18
|
-
|
19
|
-
Basically, I was sick of using the `-n` flag to grab one test to run, like RSpec's test runner works.
|
20
|
-
|
21
|
-
Given this file:
|
22
|
-
|
23
|
-
$ cat -n test/example_test.rb
|
24
|
-
1 require 'test/unit'
|
25
|
-
2
|
26
|
-
3 class ExampleTest < Test::Unit::TestCase
|
27
|
-
4 def test_apple
|
28
|
-
5 assert_equal 1, 1
|
29
|
-
6 end
|
30
|
-
7
|
31
|
-
8 def test_banana
|
32
|
-
9 assert_equal 1, 1
|
33
|
-
10 end
|
34
|
-
11 end
|
35
|
-
|
36
|
-
You can run a test by line number, using format `m TEST_FILE:LINE_NUMBER_OF_TEST`:
|
37
|
-
|
38
|
-
$ m test/example_test.rb:4
|
39
|
-
Run options: -n /test_apple/
|
40
|
-
|
41
|
-
# Running tests:
|
42
|
-
|
43
|
-
.
|
44
|
-
|
45
|
-
Finished tests in 0.000525s, 1904.7619 tests/s, 1904.7619 assertions/s.
|
46
|
-
|
47
|
-
1 tests, 1 assertions, 0 failures, 0 errors, 0 skips
|
48
|
-
|
49
|
-
Hit the wrong line number? No problem, `m` helps you out:
|
50
|
-
|
51
|
-
$ m test/example_test.rb:2
|
52
|
-
No tests found on line 2. Valid tests to run:
|
53
|
-
|
54
|
-
test_apple: m test/examples/test_unit_example_test.rb:4
|
55
|
-
test_banana: m test/examples/test_unit_example_test.rb:8
|
56
|
-
|
57
|
-
Want to run the whole test? Just leave off the line number.
|
58
|
-
|
59
|
-
$ m test/example_test.rb
|
60
|
-
Run options:
|
61
|
-
|
62
|
-
# Running tests:
|
63
|
-
|
64
|
-
..
|
65
|
-
|
66
|
-
Finished tests in 0.001293s, 1546.7904 tests/s, 3093.5808 assertions/s.
|
67
|
-
|
68
|
-
1 tests, 2 assertions, 0 failures, 0 errors, 0 skips
|
69
|
-
|
70
|
-
`m` also works with `ActiveSupport::TestCase` as well, so it will work great with your Rails test suites.
|
71
|
-
|
72
|
-
## License
|
73
|
-
|
74
|
-
This gem is MIT licensed, please see `LICENSE` for more information.
|
data/lib/m/runner.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
module M
|
2
|
-
class Runner
|
3
|
-
def initialize(argv)
|
4
|
-
@file, line = argv.first.split(':')
|
5
|
-
@line = line.to_i
|
6
|
-
end
|
7
|
-
|
8
|
-
def run
|
9
|
-
tests_to_run = tests.within(@line)
|
10
|
-
|
11
|
-
if tests_to_run.size > 0
|
12
|
-
test_names = tests_to_run.map(&:name).join('|')
|
13
|
-
exit Test::Unit::AutoRunner.run(false, nil, ["-n", "/(#{test_names})/"])
|
14
|
-
else
|
15
|
-
message = "No tests found on line #{@line}. Valid tests to run:\n\n"
|
16
|
-
tests.by_line_number do |test|
|
17
|
-
message << "#{sprintf("%0#{tests.column_size}s", test.name)}: m #{@file}:#{test.start_line}\n"
|
18
|
-
end
|
19
|
-
abort message
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
|
25
|
-
def suites
|
26
|
-
$:.unshift "./test"
|
27
|
-
load @file
|
28
|
-
Test::Unit::TestCase.test_suites.inject({}) do |suites, suite_class|
|
29
|
-
suites[suite_class] = suite_class.test_methods unless suite_class.test_methods.empty?
|
30
|
-
suites
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
def tests
|
35
|
-
@tests ||= begin
|
36
|
-
collection = TestCollection.new
|
37
|
-
suites.each do |suite_class, test_methods|
|
38
|
-
test_methods.each do |test_method|
|
39
|
-
collection << TestMethod.create(suite_class, test_method)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
collection
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
data/lib/m/version.rb
DELETED