m 0.0.1 → 1.0.0.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
#[](http://travis-ci.org/qrush/m)
|
5
|
+
#
|
6
|
+
#
|
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 [](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
|
-

|
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