mrspec 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6cbbcda0055d2073b1bc987184afd21145c4a527
4
- data.tar.gz: 6131f41d4ffd68a89a00b1ba92f70f1e6b87bccb
3
+ metadata.gz: c9b7422e1ee184d93d1efcb320e1d66d95261d72
4
+ data.tar.gz: 2cb80072ccc287fce0ae9deeeaf5e4cf7714f755
5
5
  SHA512:
6
- metadata.gz: 4f1e700ae9c81848aede3a469920d55685152b22e2d68bc65b9c65592a97f99c229af26c3d1adaa5035e7577cc8073696d0997fe42bca983f271c3d2b49ea283
7
- data.tar.gz: b9cd655c7c06136b3abd010c66a4b70e2525a21f458971e2d5b6b6c2f3a9938ef39b02892b185217809d733edbd90ec762eb2f00b1d13dcc2c9e0dd56fa56253
6
+ metadata.gz: a4f44abb23f546d633264ad6d0f91d769cb8e56afc3c92051c4371bc2c5ae582f80aef74dae65ca1349d839775316fe0bc9311501c26e1019e02d7ee54ddc3f5
7
+ data.tar.gz: 5d7e7dc0778e64e6d6269caf5b03930a5d09d24f0fc6844fabfecad914dd53edc9c07ce98863f18fe29890a399a83de7f1f0b2c55d44c201538daad5333c21cd
data/.travis.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  language: ruby
2
- script: cucumber
2
+ script: bin/mrspec --colour --format documentation && cucumber
3
3
  rvm:
4
4
  - 1.9.3
5
5
  - 2.0.0
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
  ![Examples of Tagging](https://s3.amazonaws.com/josh.cheek/mrspec/tagging.png)
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. It's not a test runner, it's a build tool. As such, it's not well suited to this task.
151
- 1. I shouldn't have to add a dependency on Rake just to run my tests.
152
- 1. The `Rake::TestTask` is confoundingly opaque (I rant about it [here](https://github.com/stripe/stripe-ruby/pull/144#issuecomment-48810307))
153
- 1. It ultimately just [shells out](https://github.com/rspec/rspec-core/blob/3145e2544e1825bc754d0986e893664afe19abf5/lib/rspec/core/rake_task.rb#L70)
154
- (as does the [RSpec one](https://github.com/ruby/rake/blob/e644af3a09659c7e04245186607091324d8816e9/lib/rake/testtask.rb#L104),
155
- so why do I need layers of translation and abstraction between me and a command-line invocation?
156
- And what's the value of adding an entire process between me and my tests?
157
- Think how long Rails takes to start up, now imagine paying that twice every time you want to run your tests!
158
- 1. It makes it incredibly difficult to dynamically alter my test invoation.
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 (or write code to uese
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, there's just no way built in to run them all. I wind up having to craft clever command-line invocations
167
- using custom tools ([1](https://github.com/JoshCheek/dotfiles/blob/master/bin/ff),
168
- [2](https://github.com/JoshCheek/dotfiles/blob/master/bin/prepend)).
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
- and who knows if they'll write it well enough to be used outside of Rails.
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 just not do that in general. Monkey patching is a bad plan, all around,
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
- I'm looking forward to when this feature is removed altogether.
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
 
@@ -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
@@ -1,3 +1,4 @@
1
+ require 'mrspec/version'
1
2
  require 'mrspec/minitest_metadata'
2
3
  require 'mrspec/runner'
3
4
  require 'mrspec/configuration'
@@ -12,7 +12,7 @@ module MRspec
12
12
 
13
13
  def load_spec_files(*)
14
14
  super
15
- MRspec::DeclareMinitests.call
15
+ MRspec::DeclareMinitests.call(RSpec, Minitest, Minitest::Runnable.runnables)
16
16
  end
17
17
  end
18
18
  end
@@ -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 Minitest::Runnable.runnables
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.sub(/^Test/, '').sub(/Test$/, '')
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
- Minitest.reporter = Minitest::CompositeReporter.new # we're not using the reporter, but some plugins, (eg minitest/pride) expect it to be there
27
- Minitest.load_plugins
28
- Minitest.init_plugins Minitest.process_args([])
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 = RSpec.describe group_name(klass), klass.class_metadata
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
@@ -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).tap { |parser| parser.banner.gsub! /\brspec\b/, 'mrspec' }
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
@@ -1,3 +1,3 @@
1
1
  module MRspec
2
- VERSION = '0.0.1'
2
+ VERSION = '0.1.0'
3
3
  end
@@ -0,0 +1,6 @@
1
+ # Don't filter mrspec out of the backtrace when testing itslef!
2
+ RSpec.configure do |config|
3
+ config.backtrace_formatter.exclusion_patterns.reject! do |pattern|
4
+ pattern =~ "/mrspec/"
5
+ end
6
+ end
@@ -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
@@ -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.1
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-20 00:00:00.000000000 Z
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: