mrspec 0.0.1 → 0.1.0
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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/Readme.md +36 -27
- data/bin/mrspec +5 -0
- data/features/mrspec.feature +19 -0
- data/lib/mrspec.rb +1 -0
- data/lib/mrspec/configuration.rb +1 -1
- data/lib/mrspec/declare_minitests.rb +18 -13
- data/lib/mrspec/option_parser.rb +16 -1
- data/lib/mrspec/version.rb +1 -1
- data/test/support/helper.rb +6 -0
- data/test/support/mock.rb +65 -0
- data/test/test_mrspec.rb +172 -0
- data/test/test_parser_monkey_patches.rb +93 -0
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c9b7422e1ee184d93d1efcb320e1d66d95261d72
|
4
|
+
data.tar.gz: 2cb80072ccc287fce0ae9deeeaf5e4cf7714f755
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a4f44abb23f546d633264ad6d0f91d769cb8e56afc3c92051c4371bc2c5ae582f80aef74dae65ca1349d839775316fe0bc9311501c26e1019e02d7ee54ddc3f5
|
7
|
+
data.tar.gz: 5d7e7dc0778e64e6d6269caf5b03930a5d09d24f0fc6844fabfecad914dd53edc9c07ce98863f18fe29890a399a83de7f1f0b2c55d44c201538daad5333c21cd
|
data/.travis.yml
CHANGED
data/Readme.md
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
mrspec
|
4
4
|
======
|
5
5
|
|
6
|
-
Minitest and RSpec, sitting in a tree
|
6
|
+
Minitest and RSpec, sitting in a tree, T. E. S. T. I. N. G!
|
7
7
|
|
8
8
|
Runs Minitest tests using RSpec's runner.
|
9
9
|
Also runs RSpec's tests, so if you want to use them side-by-side,
|
@@ -138,6 +138,13 @@ end
|
|
138
138
|

|
139
139
|
|
140
140
|
|
141
|
+
Default configuration
|
142
|
+
---------------------
|
143
|
+
|
144
|
+
You can place a file named `.rspec` in your home directory with command-line arguments in it.
|
145
|
+
These will be used as defaults when you run `mrspec` or `rspec`.
|
146
|
+
[Here](https://github.com/JoshCheek/dotfiles/blob/5948132cd2367ef3b86fd2ce5351948a65d7aec7/rspec) is mine.
|
147
|
+
|
141
148
|
|
142
149
|
Why?
|
143
150
|
----
|
@@ -147,37 +154,27 @@ And if you have multiple suites, that can be nice,
|
|
147
154
|
or if you already use Rake, then it's not adding a new dependency.
|
148
155
|
But here are some frustrations I have with it as a test runner:
|
149
156
|
|
150
|
-
1.
|
151
|
-
1.
|
152
|
-
1. The
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
1. It makes it
|
157
|
+
1. I don't want to add a dependency on Rake, unless I need it.
|
158
|
+
1. The `Rake::TestTask` is difficult to make sense of.
|
159
|
+
1. The Rake tasks ultimately just shell out ([RSpec's](https://github.com/rspec/rspec-core/blob/3145e2544e1825bc754d0986e893664afe19abf5/lib/rspec/core/rake_task.rb#L70),
|
160
|
+
[Minitest's](https://github.com/ruby/rake/blob/e644af3a09659c7e04245186607091324d8816e9/lib/rake/testtask.rb#L104)).
|
161
|
+
So I don't see what they offer over invoking the program directly (usually I know what I want to pass the program,
|
162
|
+
and I am trying to figure out how to configure the test task to do that).
|
163
|
+
The overhead of running additional processes can also be high:
|
164
|
+
think how long Rails takes to start up, now imagine paying that twice every time you want to run your tests!
|
165
|
+
1. It makes it difficult to dynamically alter my test invoation.
|
159
166
|
With Minitest, you can pass `-n test_something` and it will only run the test named `test_something`,
|
160
|
-
but now I have to edit code tomake that happen
|
161
|
-
environment variables, which is better, but still cumbersome,
|
162
|
-
and doesn't fail noisily if I mistype it)
|
167
|
+
but now I have to edit code tomake that happen.
|
163
168
|
|
164
169
|
Furthermore, if someone doesn't know about the test task, or it seems formidable, as it often does to new students
|
165
170
|
(I'm a [teacher](http://turing.io/team)), then they won't use it. They instead run files one at a time.
|
166
|
-
When I go to run the tests,
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
```sh
|
171
|
-
$ ff test '\.rb' | prepend -r | xargs ruby -e ''
|
172
|
-
```
|
173
|
-
|
174
|
-
Oftentimes, this is the first time they've all been run together, and we find out they haven't run a test in a long time,
|
175
|
-
because it's too cumbersome for them (they're not good with their tools yet), it's failing or worse, syntactically invalid.
|
176
|
-
Maybe they even know it, but they run them one at a time, so it hasn't been a problem for them yet.
|
171
|
+
When I go to run the tests, they don't have a way to run all of them.
|
172
|
+
This overhead, in turn, disinclines them to run the tests,
|
173
|
+
such that they may be failing and not realize it.
|
177
174
|
|
178
175
|
Anyway, all of this is to say that Minitest needs a runner.
|
179
176
|
I hear Rails is working on one, but I don't know when that'll be available,
|
180
|
-
|
177
|
+
or if it will be written in a way that it can be used outside of Rails.
|
181
178
|
|
182
179
|
But the RSpec runner is very nice, it has a lot of features that I use frequently.
|
183
180
|
Someone suggested running Minitest with the RSpec runner (see attribution section),
|
@@ -193,6 +190,9 @@ Changes the default pattern to look for any files suffixed with `_test.rb` or `_
|
|
193
190
|
Changes the default search directories to be `test` and `spec`
|
194
191
|
(RSpec, by itself, only looks in `spec`).
|
195
192
|
|
193
|
+
Adds `test` to the `$LOAD_PATH`, if it exists.
|
194
|
+
(RSpec, by itself, only adds `spec`).
|
195
|
+
|
196
196
|
Turns off monkey patching, so you cannot use RSPec's toplevel describe, or `should`.
|
197
197
|
There are 2 reasons for this:
|
198
198
|
|
@@ -203,9 +203,10 @@ There are 2 reasons for this:
|
|
203
203
|
which means that even if you don't use it, it will still interfere with `Minitest::Spec`
|
204
204
|
(removing methods allows method lookup to find superclass definitions,
|
205
205
|
but undefining them ends method lookup.)
|
206
|
-
2. You should
|
206
|
+
2. You should avoid things like this, in general. Monkey patching is a bad plan, all around,
|
207
207
|
just use the namespaced methods, or create your own methods to wrap the assertion syntax.
|
208
|
-
|
208
|
+
|
209
|
+
Only expected to support Rubies in the [.travis.yml](https://github.com/JoshCheek/mrspec/blob/fa1945d3d4941a90a3272020b51468dfb42f8212/.travis.yml).
|
209
210
|
|
210
211
|
|
211
212
|
Running the tests
|
@@ -213,6 +214,7 @@ Running the tests
|
|
213
214
|
|
214
215
|
```sh
|
215
216
|
$ bundle
|
217
|
+
$ bundle exec bin/mrspec
|
216
218
|
$ bundle exec cucumber
|
217
219
|
```
|
218
220
|
|
@@ -222,6 +224,13 @@ which I mostly test with Cucumber and [Haiti](https://github.com/JoshCheek/haiti
|
|
222
224
|
as they are usually heavily oriented towards integration,
|
223
225
|
and often not written in Ruby.
|
224
226
|
|
227
|
+
What about the `test` directory?
|
228
|
+
I decided to describe all the behaviour that can be unit tested,
|
229
|
+
but haven't taken the time to implement most of them yet,
|
230
|
+
because I don't currently have any features I'm trying to add.
|
231
|
+
As I maintain this, though, I'll begin implementing them,
|
232
|
+
as it will be easier in the end :)
|
233
|
+
|
225
234
|
|
226
235
|
Attribution
|
227
236
|
-----------
|
data/bin/mrspec
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
# Load our lib
|
3
4
|
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
|
4
5
|
require 'mrspec'
|
5
6
|
|
7
|
+
# Put ./test in the load path
|
8
|
+
test_dir = File.expand_path('test', Dir.pwd)
|
9
|
+
$LOAD_PATH.unshift test_dir if Dir.exist? test_dir
|
10
|
+
|
6
11
|
# All your config are belong to us
|
7
12
|
RSpec.configuration = MRspec::Configuration.new
|
8
13
|
|
data/features/mrspec.feature
CHANGED
@@ -469,7 +469,26 @@ Feature: mrspec
|
|
469
469
|
And stdout includes "NO ERROR"
|
470
470
|
And stdout includes "NO UNEXPECTED DEPS"
|
471
471
|
|
472
|
+
|
472
473
|
Scenario: The help screen is custom to mrspec
|
473
474
|
When I run "mrspec -h"
|
474
475
|
Then stdout includes "Usage: mrspec"
|
475
476
|
# Probably add more later
|
477
|
+
|
478
|
+
|
479
|
+
# Only specifying the major version, so I get enough to be confident
|
480
|
+
# but not enough to be too volatile
|
481
|
+
Scenario: Prints mrspec, rspec, and minitest versions for --version
|
482
|
+
When I run "mrspec --version"
|
483
|
+
Then the program ran successfully
|
484
|
+
And stdout includes "mrspec 0."
|
485
|
+
And stdout includes "rspec-core 3."
|
486
|
+
And stdout includes "minitest 5."
|
487
|
+
|
488
|
+
|
489
|
+
Scenario: Adds absolute path to `./test` to the $LOAD_PATH, if it exists
|
490
|
+
Given the file "test/my_helper.rb" "puts 'I got loaded!'"
|
491
|
+
And the file "test/some_test.rb" "Dir.chdir('/') { require 'my_helper' }"
|
492
|
+
When I run "mrspec"
|
493
|
+
Then the program ran successfully
|
494
|
+
And stdout includes "I got loaded!"
|
data/lib/mrspec.rb
CHANGED
data/lib/mrspec/configuration.rb
CHANGED
@@ -5,13 +5,18 @@ module MRspec
|
|
5
5
|
module DeclareMinitests
|
6
6
|
extend self
|
7
7
|
|
8
|
-
def self.call
|
9
|
-
init_minitest
|
10
|
-
wrap_classes
|
8
|
+
def self.call(rspec, minitest, klasses)
|
9
|
+
init_minitest minitest
|
10
|
+
wrap_classes rspec, klasses
|
11
11
|
end
|
12
12
|
|
13
13
|
def group_name(klass)
|
14
|
-
klass.name
|
14
|
+
if klass.name
|
15
|
+
klass.name.to_s.sub(/^Test/, '').sub(/Test$/, '')
|
16
|
+
else
|
17
|
+
inspection = Kernel.instance_method(:inspect).bind(klass).call
|
18
|
+
"Anonymous Minitest for class #{inspection}"
|
19
|
+
end
|
15
20
|
end
|
16
21
|
|
17
22
|
def example_name(method_name)
|
@@ -19,21 +24,21 @@ module MRspec
|
|
19
24
|
# https://github.com/seattlerb/minitest/blob/f1081566ec6e9e391628bde3a26fb057ad2576a8/lib/minitest/test.rb#L62
|
20
25
|
# remove test_0001_, where the number increments
|
21
26
|
# https://github.com/seattlerb/minitest/blob/f1081566ec6e9e391628bde3a26fb057ad2576a8/lib/minitest/spec.rb#L218-222
|
22
|
-
method_name.sub(/^test_(?:\d{4}_)?/, '').tr('_', ' ')
|
27
|
+
method_name.to_s.sub(/^test_(?:\d{4}_)?/, '').tr('_', ' ')
|
23
28
|
end
|
24
29
|
|
25
|
-
def init_minitest
|
26
|
-
|
27
|
-
|
28
|
-
|
30
|
+
def init_minitest(minitest)
|
31
|
+
minitest.reporter = minitest::CompositeReporter.new # we're not using the reporter, but some plugins, (eg minitest/pride) expect it to be there
|
32
|
+
minitest.load_plugins
|
33
|
+
minitest.init_plugins minitest.process_args([])
|
29
34
|
end
|
30
35
|
|
31
|
-
def wrap_classes(klasses)
|
32
|
-
klasses.each { |klass| wrap_class klass }
|
36
|
+
def wrap_classes(rspec, klasses)
|
37
|
+
klasses.each { |klass| wrap_class rspec, klass }
|
33
38
|
end
|
34
39
|
|
35
|
-
def wrap_class(klass)
|
36
|
-
example_group =
|
40
|
+
def wrap_class(rspec, klass)
|
41
|
+
example_group = rspec.describe group_name(klass), klass.class_metadata
|
37
42
|
klass.runnable_methods.each do |method_name|
|
38
43
|
wrap_test example_group, klass, method_name
|
39
44
|
end
|
data/lib/mrspec/option_parser.rb
CHANGED
@@ -13,7 +13,22 @@ class RSpec::Core::Parser
|
|
13
13
|
|
14
14
|
# Ours calls RSpec's, then modifies values on the returned parser
|
15
15
|
def mrspec_parser(*args, &b)
|
16
|
-
rspec_parser(*args, &b)
|
16
|
+
option_parser = rspec_parser(*args, &b)
|
17
|
+
|
18
|
+
# update the program name
|
19
|
+
option_parser.banner.gsub! /\brspec\b/, 'mrspec'
|
20
|
+
|
21
|
+
# print mrspec version, and dependency versions.
|
22
|
+
# calling exit and toplevel puts, b/c that's what RSpec's does https://github.com/rspec/rspec-core/blob/c7c1154934c42b5f6905bb7bd22025fe6c8a816c/lib/rspec/core/option_parser.rb#L290
|
23
|
+
# and I don't feel like figuring out how to work around it.
|
24
|
+
option_parser.on('-v', '--version', 'Display the version.') do
|
25
|
+
puts "mrspec #{MRspec::VERSION}\n"\
|
26
|
+
"rspec-core #{RSpec::Core::Version::STRING}\n"\
|
27
|
+
"minitest #{Minitest::VERSION}\n"
|
28
|
+
exit
|
29
|
+
end
|
30
|
+
|
31
|
+
option_parser
|
17
32
|
end
|
18
33
|
|
19
34
|
# A place to store which method `parser` actually resolves to
|
data/lib/mrspec/version.rb
CHANGED
@@ -0,0 +1,65 @@
|
|
1
|
+
module Mock
|
2
|
+
def mock_rspec
|
3
|
+
@mock_rspec ||= Mock::RSpec.new
|
4
|
+
end
|
5
|
+
|
6
|
+
def mock_minitest
|
7
|
+
@mock_minitest ||= Mock::Minitest.new
|
8
|
+
end
|
9
|
+
|
10
|
+
# This name can't match /^test_/, or https://github.com/seattlerb/minitest/blob/f1081566ec6e9e391628bde3a26fb057ad2576a8/lib/minitest/spec.rb#L167-171
|
11
|
+
# ...legit thought I'd forgotten the object model for a moment there O.o
|
12
|
+
def a_test_named(name, &block)
|
13
|
+
Class.new(Mock::MinitestTest, &block).tap do |klass|
|
14
|
+
klass.define_singleton_method(:name) { name }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def a_spec_named(name)
|
19
|
+
skip 'Not worth figuring this out right now'
|
20
|
+
Class.new Mock::MinitestSpec do
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class Mock::MinitestTest < ::Minitest::Test
|
26
|
+
# noop, just preventing our testing from globally registering tests
|
27
|
+
def self.inherited(*)
|
28
|
+
end
|
29
|
+
|
30
|
+
# And unregister this mock class
|
31
|
+
Minitest::Runnable.runnables.delete self
|
32
|
+
end
|
33
|
+
|
34
|
+
class Mock::RSpec
|
35
|
+
def groups
|
36
|
+
@groups ||= []
|
37
|
+
end
|
38
|
+
|
39
|
+
def group_names
|
40
|
+
groups.map &:name
|
41
|
+
end
|
42
|
+
|
43
|
+
def examples
|
44
|
+
groups.flat_map &:examples
|
45
|
+
end
|
46
|
+
|
47
|
+
def describe(name, metadata, &block)
|
48
|
+
group = ExampleGroup.new name, metadata
|
49
|
+
groups << group
|
50
|
+
group.module_exec(&block) if block # https://github.com/rspec/rspec-core/blob/c7c1154934c42b5f6905bb7bd22025fe6c8a816c/lib/rspec/core/example_group.rb#L363
|
51
|
+
group
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
Mock::RSpec::Example = Struct.new :name, :metadata, :block
|
56
|
+
|
57
|
+
Mock::RSpec::ExampleGroup = Struct.new :name, :metadata do
|
58
|
+
def examples
|
59
|
+
@examples ||= []
|
60
|
+
end
|
61
|
+
|
62
|
+
def example(name, metadata, &block)
|
63
|
+
Example.new name, metadata, block
|
64
|
+
end
|
65
|
+
end
|
data/test/test_mrspec.rb
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'minitest/spec'
|
2
|
+
require 'support/helper'
|
3
|
+
require 'support/mock'
|
4
|
+
|
5
|
+
|
6
|
+
# Just wrote down the behaviour,
|
7
|
+
# but as of right now, it's not worth the effort of writing all of them,
|
8
|
+
# the cukes test all this behaviour, already
|
9
|
+
|
10
|
+
class TestMRspec < Minitest::Spec
|
11
|
+
include ::Mock
|
12
|
+
|
13
|
+
describe 'default files and patterns' do
|
14
|
+
it 'looks in the test and spec directories'
|
15
|
+
it 'finds files that end in _spec.rb, recursively'
|
16
|
+
it 'finds files that end in _test.rb, recursively'
|
17
|
+
it 'finds files that begin with test_ and end with .rb, recursively'
|
18
|
+
end
|
19
|
+
|
20
|
+
describe 'registering tests' do
|
21
|
+
it 'registers Minitest::Test tests with RSpec, using the class name' do
|
22
|
+
test1 = a_test_named 'First'
|
23
|
+
test2 = a_test_named 'Second'
|
24
|
+
MRspec::DeclareMinitests.wrap_classes mock_rspec, [test1, test2]
|
25
|
+
assert_equal ['First', 'Second'], mock_rspec.group_names
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'registers Minitest::Spec tests with RSpec, using the spec description' do
|
29
|
+
spec1 = a_spec_named 'spec 1'
|
30
|
+
spec2 = a_spec_named 'spec 2'
|
31
|
+
MRspec::DeclareMinitests.wrap_classes mock_rspec, [test1, test2]
|
32
|
+
assert_equal ['spec 1', 'spec 2'], mock_rspec.group_names
|
33
|
+
end
|
34
|
+
|
35
|
+
describe 'descriptions' do
|
36
|
+
def description_for(class_name)
|
37
|
+
MRspec::DeclareMinitests.group_name a_test_named(class_name)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'removes leading `Test` in the class name, from the description' do
|
41
|
+
assert_equal 'ClassName', description_for('ClassName')
|
42
|
+
assert_equal 'ClassName', description_for('TestClassName')
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'removes trailing `Test` in the class name, from the description' do
|
46
|
+
assert_equal 'ClassName', description_for('ClassName')
|
47
|
+
assert_equal 'ClassName', description_for('ClassNameTest')
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'can deals with anonymous classes (nil class name) by using their to_s' do
|
51
|
+
klass1 = a_test_named nil
|
52
|
+
description1 = MRspec::DeclareMinitests.group_name klass1
|
53
|
+
|
54
|
+
klass2 = a_test_named nil
|
55
|
+
description2 = MRspec::DeclareMinitests.group_name klass2
|
56
|
+
|
57
|
+
assert_match /^Anonymous Minitest for class #<Class:0x/, description1
|
58
|
+
|
59
|
+
# Just double checking it's bypassing this code that makes them all have the same name:
|
60
|
+
# https://github.com/seattlerb/minitest/blob/f1081566ec6e9e391628bde3a26fb057ad2576a8/lib/minitest/assertions.rb#L118
|
61
|
+
refute_equal description1, description2
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'can deal with symol or string names' do
|
65
|
+
assert_equal 'ClassName', description_for('ClassName')
|
66
|
+
assert_equal 'ClassName', description_for(:ClassName)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe 'example names' do
|
71
|
+
def example_name_for(method_name)
|
72
|
+
MRspec::DeclareMinitests.example_name method_name
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'removes leading `test_` in the method name, from the test name' do
|
76
|
+
assert_equal 'methodname', example_name_for('methodname')
|
77
|
+
assert_equal 'methodname', example_name_for('test_methodname')
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'removes leading `test_nnnn_` in the method name, from the test name' do
|
81
|
+
assert_equal 'methodname', example_name_for('methodname')
|
82
|
+
assert_equal 'methodname', example_name_for('test_0000_methodname')
|
83
|
+
assert_equal '000 methodname', example_name_for('test_000_methodname')
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'translates underscores to spaces' do
|
87
|
+
assert_equal 'a method name', example_name_for('a_method_name')
|
88
|
+
end
|
89
|
+
|
90
|
+
it 'can deal with string or symbol names' do
|
91
|
+
assert_equal 'methodname', example_name_for('methodname')
|
92
|
+
assert_equal 'methodname', example_name_for(:methodname)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe 'metadata' do
|
97
|
+
it 'aggregates metadata on the class with classmeta' do
|
98
|
+
klass = a_test_named('a') { classmeta a: true }
|
99
|
+
assert_equal({a: true}, klass.class_metadata)
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'allows for multiple metadata keys to be provided in one classmeta call' do
|
103
|
+
klass = a_test_named('a') { classmeta a: true, b: true }
|
104
|
+
assert_equal({a: true, b: true}, klass.class_metadata)
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'aggregates multiple calls to classmeta' do
|
108
|
+
klass = a_test_named 'a' do
|
109
|
+
classmeta a: true
|
110
|
+
classmeta b: true
|
111
|
+
end
|
112
|
+
assert_equal({a: true, b: true}, klass.class_metadata)
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'aggregates metadata on the next test to be defined, with meta' do
|
116
|
+
klass = a_test_named 'a' do
|
117
|
+
meta a: true
|
118
|
+
def test_a; end
|
119
|
+
|
120
|
+
def test_b; end
|
121
|
+
|
122
|
+
meta c: true
|
123
|
+
def test_c; end
|
124
|
+
end
|
125
|
+
|
126
|
+
assert_equal({a: true}, klass.example_metadata[:test_a])
|
127
|
+
assert_equal({}, klass.example_metadata[:test_b])
|
128
|
+
assert_equal({c: true}, klass.example_metadata[:test_c])
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'allows for multiple metadata keys to be provided in one meta call' do
|
132
|
+
klass = a_test_named 'a' do
|
133
|
+
meta a: true, b: true
|
134
|
+
def test_a; end
|
135
|
+
end
|
136
|
+
assert_equal({a: true, b: true}, klass.example_metadata[:test_a])
|
137
|
+
end
|
138
|
+
|
139
|
+
it 'aggregates multiple calls to meta' do
|
140
|
+
klass = a_test_named 'a' do
|
141
|
+
meta a: true
|
142
|
+
meta b: true
|
143
|
+
def test_a; end
|
144
|
+
end
|
145
|
+
assert_equal({a: true, b: true}, klass.example_metadata[:test_a])
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe 'recording tests' do
|
151
|
+
it 'records minitest errors as failures, and displays the message and the class'
|
152
|
+
it 'records minitest failed assertions as failures, and displays the message, but not the class'
|
153
|
+
it 'records rspec errors as failures, and displays the message, and the class'
|
154
|
+
it 'records rspec failed assertions as failures, and displays the message and the class'
|
155
|
+
it 'omits minitest code from the backtrace'
|
156
|
+
it 'omits rspec code from the backtrace'
|
157
|
+
it 'omits mrspec code from the backtrace'
|
158
|
+
end
|
159
|
+
|
160
|
+
describe 'identifying which test to run' do
|
161
|
+
it 'matches the -e flag against Minitest tests'
|
162
|
+
it 'overrides the default filenames, when one is provided'
|
163
|
+
end
|
164
|
+
|
165
|
+
describe 'toplevel `describe`' do
|
166
|
+
it 'comes from Minitest::Spec' do
|
167
|
+
filename, _linenum = TOPLEVEL_BINDING.method(:describe).source_location
|
168
|
+
assert_match /minitest/, filename
|
169
|
+
refute_match /rspec/, filename
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'minitest/spec'
|
2
|
+
require 'support/helper'
|
3
|
+
|
4
|
+
class TestParserMonkeyPatches < Minitest::Spec
|
5
|
+
Parser = RSpec::Core::Parser
|
6
|
+
|
7
|
+
def rspec_parser
|
8
|
+
Parser.instance_method :rspec_parser
|
9
|
+
end
|
10
|
+
|
11
|
+
def mrspec_parser
|
12
|
+
Parser.instance_method :mrspec_parser
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'can get the original rspec parser with #rspec_parser' do
|
16
|
+
filename, _linenum = rspec_parser.source_location
|
17
|
+
assert_includes filename, '/lib/rspec/core/'
|
18
|
+
refute_includes filename, '/lib/mrspec/'
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'has an overridden parser with #mrspec_parser' do
|
22
|
+
mrspec_parser = Parser.instance_method :mrspec_parser
|
23
|
+
filename, _linenum = mrspec_parser.source_location
|
24
|
+
refute_includes filename, '/lib/rspec/core/'
|
25
|
+
assert_includes filename, '/lib/mrspec/'
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#mrspec_parser' do
|
29
|
+
def record_hostile_parsing(option_parser, flag)
|
30
|
+
stdout, stderr, *rest = capture_io do
|
31
|
+
begin option_parser.parse([flag])
|
32
|
+
rescue SystemExit
|
33
|
+
end
|
34
|
+
end
|
35
|
+
assert_empty rest
|
36
|
+
assert_empty stderr
|
37
|
+
stdout
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'returns the original #rspec_parser' do
|
41
|
+
# just showing that it does RSpec parsery things
|
42
|
+
options = {}
|
43
|
+
Parser.new.mrspec_parser(options).parse(['-I', 'somepath'])
|
44
|
+
assert_equal options[:libs], ['somepath']
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'modifies the description to replace uses of rspec with uses of mrpspec' do
|
48
|
+
assert_match /\bmrspec\b/, Parser.new.mrspec_parser({}).banner
|
49
|
+
refute_match /\brspec\b/, Parser.new.mrspec_parser({}).banner
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'overrides -v and --version includes the Mrspec version, the RSpec::Core version, and the Minitest version' do
|
53
|
+
rspec_version = record_hostile_parsing Parser.new.rspec_parser({}), '--version'
|
54
|
+
rspec_v = record_hostile_parsing Parser.new.rspec_parser({}), '-v'
|
55
|
+
mrspec_version = record_hostile_parsing Parser.new.mrspec_parser({}), '--version'
|
56
|
+
mrspec_v = record_hostile_parsing Parser.new.mrspec_parser({}), '-v'
|
57
|
+
|
58
|
+
# RSpec version parser defines both of these flags to return its version
|
59
|
+
assert_equal rspec_version, rspec_v
|
60
|
+
assert_equal RSpec::Core::Version::STRING, rspec_version.chomp
|
61
|
+
|
62
|
+
# MRspec overrides both of these flags to print versions of all relevant libs
|
63
|
+
expected = "mrspec #{MRspec::VERSION}\n"\
|
64
|
+
"rspec-core #{RSpec::Core::Version::STRING}\n"\
|
65
|
+
"minitest #{Minitest::VERSION}\n"
|
66
|
+
assert_equal mrspec_version, mrspec_v
|
67
|
+
assert_equal expected, mrspec_version
|
68
|
+
end
|
69
|
+
|
70
|
+
# Giving up on making sure these are equivalent, it's not the end of the world if they aren't
|
71
|
+
# I'm basically at a point where I think that no one should use OptionParser
|
72
|
+
it 'sets the correct description for the versions'
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'stores the current parser in .parser_method' do
|
76
|
+
Parser.parser_method = rspec_parser
|
77
|
+
assert_equal Parser.parser_method, rspec_parser
|
78
|
+
refute_equal Parser.parser_method, mrspec_parser
|
79
|
+
|
80
|
+
Parser.parser_method = mrspec_parser
|
81
|
+
refute_equal Parser.parser_method, rspec_parser
|
82
|
+
assert_equal Parser.parser_method, mrspec_parser
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'redefines #parser to use the parser in .parser_method' do
|
86
|
+
# have to do it a bit roundabout, b/c OptionParser does not override #==, so it uses object equality
|
87
|
+
Parser.parser_method = rspec_parser
|
88
|
+
assert_match /\brspec\b/, Parser.new.parser({}).banner
|
89
|
+
|
90
|
+
Parser.parser_method = mrspec_parser
|
91
|
+
assert_match /\bmrspec\b/, Parser.new.parser({}).banner
|
92
|
+
end
|
93
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mrspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josh Cheek
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
11
|
+
date: 2015-05-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec-core
|
@@ -99,6 +99,10 @@ files:
|
|
99
99
|
- lib/mrspec/runner.rb
|
100
100
|
- lib/mrspec/version.rb
|
101
101
|
- mrspec.gemspec
|
102
|
+
- test/support/helper.rb
|
103
|
+
- test/support/mock.rb
|
104
|
+
- test/test_mrspec.rb
|
105
|
+
- test/test_parser_monkey_patches.rb
|
102
106
|
homepage: https://github.com/JoshCheek/mrspec
|
103
107
|
licenses:
|
104
108
|
- MIT
|
@@ -126,4 +130,8 @@ summary: Minitest tests + RSpec's test runner
|
|
126
130
|
test_files:
|
127
131
|
- features/mrspec.feature
|
128
132
|
- features/support/env.rb
|
133
|
+
- test/support/helper.rb
|
134
|
+
- test/support/mock.rb
|
135
|
+
- test/test_mrspec.rb
|
136
|
+
- test/test_parser_monkey_patches.rb
|
129
137
|
has_rdoc:
|