minitest_to_rspec 0.10.2 → 0.11.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/.rubocop.yml +11 -2
- data/CHANGELOG.md +17 -0
- data/README.md +13 -0
- data/Rakefile +1 -1
- data/bin/console +4 -4
- data/bin/mt2rspec +1 -1
- data/doc/mocha/mocha_test.rb +50 -0
- data/lib/minitest_to_rspec/cli.rb +19 -19
- data/lib/minitest_to_rspec/converter.rb +4 -4
- data/lib/minitest_to_rspec/expression_builders/stub.rb +62 -0
- data/lib/minitest_to_rspec/model/base.rb +1 -1
- data/lib/minitest_to_rspec/model/call.rb +17 -27
- data/lib/minitest_to_rspec/model/calls/once.rb +2 -2
- data/lib/minitest_to_rspec/model/calls/twice.rb +2 -2
- data/lib/minitest_to_rspec/model/defn.rb +1 -1
- data/lib/minitest_to_rspec/model/iter.rb +1 -1
- data/lib/minitest_to_rspec/model/klass.rb +5 -5
- data/lib/minitest_to_rspec/processor.rb +6 -6
- data/lib/minitest_to_rspec/subprocessors/base.rb +1 -1
- data/lib/minitest_to_rspec/subprocessors/call.rb +68 -36
- data/lib/minitest_to_rspec/subprocessors/defn.rb +2 -2
- data/lib/minitest_to_rspec/subprocessors/iter.rb +2 -2
- data/lib/minitest_to_rspec/subprocessors/klass.rb +4 -4
- data/lib/minitest_to_rspec/type.rb +33 -0
- data/lib/minitest_to_rspec/version.rb +1 -1
- data/lib/minitest_to_rspec.rb +2 -2
- data/minitest_to_rspec.gemspec +16 -16
- metadata +5 -4
- data/.rubocop_todo.yml +0 -57
- data/lib/minitest_to_rspec/model/calls/returns.rb +0 -87
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: be2fe63a020fb7a38b10551341162eb978a0b84c
|
4
|
+
data.tar.gz: '0696d05d0c95b8cb6afbe1865ae224b2e8066e86'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1f44130fe3b150666829ff09abd348e92dffa6104f70678412ea1ef9e9e7cb363280549930796062d4c346590f634584cab18cd9db92f1c16f5a876b3ae88833
|
7
|
+
data.tar.gz: ef3a2361df027ddb59c33f858c49641f295298fa60d6a140bc63b60408e9706c2ec4d57cba346ed964d1eb7de5aa017b016b1bf151f403dfac5046f618b49c5b
|
data/.rubocop.yml
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
inherit_from: .rubocop_todo.yml
|
2
|
-
|
3
1
|
AllCops:
|
4
2
|
Exclude:
|
5
3
|
- spec/fixtures/**/*
|
@@ -40,6 +38,9 @@ Metrics/MethodLength:
|
|
40
38
|
Metrics/ModuleLength:
|
41
39
|
Enabled: false
|
42
40
|
|
41
|
+
Metrics/ParameterLists:
|
42
|
+
Max: 6
|
43
|
+
|
43
44
|
# EOS is a well-known delimiter and thus satisfactory.
|
44
45
|
Naming/HeredocDelimiterNaming:
|
45
46
|
Enabled: false
|
@@ -52,6 +53,14 @@ Style/Documentation:
|
|
52
53
|
Exclude:
|
53
54
|
- 'spec/**/*'
|
54
55
|
|
56
|
+
# Too subtle to lint. Avoid postfix operators unless line is very simple.
|
57
|
+
Style/IfUnlessModifier:
|
58
|
+
Enabled: false
|
59
|
+
|
55
60
|
# Guard clauses are great, but this is too subtle to lint.
|
56
61
|
Style/GuardClause:
|
57
62
|
Enabled: false
|
63
|
+
|
64
|
+
# Too subtle to lint. Avoid postfix operators unless line is very simple.
|
65
|
+
Style/WhileUntilModifier:
|
66
|
+
Enabled: false
|
data/CHANGELOG.md
CHANGED
@@ -17,6 +17,23 @@ of [keepachangelog.com][2].
|
|
17
17
|
|
18
18
|
- None
|
19
19
|
|
20
|
+
## 0.11.0 (2017-11-10)
|
21
|
+
|
22
|
+
### Breaking Changes
|
23
|
+
|
24
|
+
- None
|
25
|
+
|
26
|
+
### Added
|
27
|
+
|
28
|
+
- [#15](https://github.com/jaredbeck/minitest_to_rspec/pull/15) -
|
29
|
+
Support mocha stubs without returns
|
30
|
+
- [#16](https://github.com/jaredbeck/minitest_to_rspec/pull/16) -
|
31
|
+
Convert `should` to `it`
|
32
|
+
|
33
|
+
### Fixed
|
34
|
+
|
35
|
+
- None
|
36
|
+
|
20
37
|
## 0.10.2 (2017-11-09)
|
21
38
|
|
22
39
|
### Breaking Changes
|
data/README.md
CHANGED
@@ -8,6 +8,7 @@ Converts [minitest][8] files to [rspec][9].
|
|
8
8
|
and [ActiveSupport][27] are converted to [rspec-expectations][25].
|
9
9
|
- Selected methods from [mocha][28] are converted to [rspec-mocks][24].
|
10
10
|
(Experimental)
|
11
|
+
- Selected methods from [shoulda-context][36]
|
11
12
|
|
12
13
|
## Example
|
13
14
|
|
@@ -111,6 +112,14 @@ Mocha | Arity | Block | Notes
|
|
111
112
|
|
112
113
|
To do: [at_least, never, raises, etc.][30]
|
113
114
|
|
115
|
+
## Supported shoulda-context methods
|
116
|
+
|
117
|
+
Mocha | Arity | Block | Notes
|
118
|
+
--------------------- | ----- | ----- | -------
|
119
|
+
[context][36] | 1 | yes |
|
120
|
+
[setup][37] | 1,2 | no |
|
121
|
+
[should][38] | 1,2 | yes |
|
122
|
+
|
114
123
|
## Acknowledgements
|
115
124
|
|
116
125
|
This project would not be possible without [ruby_parser][14],
|
@@ -147,3 +156,7 @@ This project would not be possible without [ruby_parser][14],
|
|
147
156
|
[32]: http://www.rubydoc.info/github/floehopper/mocha/Mocha/Expectation#twice-instance_method
|
148
157
|
[34]: https://github.com/bbatsov/ruby-style-guide
|
149
158
|
[35]: https://github.com/bbatsov/rubocop
|
159
|
+
[35]: https://github.com/thoughtbot/shoulda-context
|
160
|
+
[36]: http://www.rubydoc.info/github/thoughtbot/shoulda-context/master/Shoulda/Context/ClassMethods#context-instance_method
|
161
|
+
[37]: http://www.rubydoc.info/github/thoughtbot/shoulda-context/master/Shoulda/Context/Context#setup-instance_method
|
162
|
+
[38]: http://www.rubydoc.info/github/thoughtbot/shoulda-context/master/Shoulda/Context/ClassMethods#should-instance_method
|
data/Rakefile
CHANGED
data/bin/console
CHANGED
data/bin/mt2rspec
CHANGED
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
gem 'mocha'
|
5
|
+
require 'minitest/unit'
|
6
|
+
require 'mocha/mini_test'
|
7
|
+
require 'minitest/autorun'
|
8
|
+
|
9
|
+
# Reverse engineering mocha, to clarify some things missing in the mocha docs.
|
10
|
+
class TestDerp < Minitest::Test
|
11
|
+
def test_expects_return_value
|
12
|
+
x = Object.new
|
13
|
+
x.define_singleton_method(:y) { :z } # this won't get called
|
14
|
+
x.expects(:y)
|
15
|
+
assert_nil x.y
|
16
|
+
# passes
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_stubs_only
|
20
|
+
x = Object.new
|
21
|
+
x.stubs(:y)
|
22
|
+
# passes
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_stubs_returns
|
26
|
+
x = Object.new
|
27
|
+
x.stubs(:y).returns(:z)
|
28
|
+
# passes
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_stubs_once
|
32
|
+
x = Object.new
|
33
|
+
x.stubs(:y).once
|
34
|
+
# fails: expected exactly once, not yet invoked
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_stubs_twice
|
38
|
+
x = Object.new
|
39
|
+
x.stubs(:y).twice
|
40
|
+
# fails: expected exactly twice, not yet invoked
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_stubs_return_value
|
44
|
+
x = Object.new
|
45
|
+
x.define_singleton_method(:y) { :z } # this won't get called
|
46
|
+
x.stubs(:y)
|
47
|
+
assert_nil x.y
|
48
|
+
# passes
|
49
|
+
end
|
50
|
+
end
|
@@ -1,19 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
3
|
+
require 'fileutils'
|
4
|
+
require 'minitest_to_rspec'
|
5
|
+
require 'trollop'
|
6
6
|
|
7
7
|
module MinitestToRspec
|
8
8
|
# Command-Line Interface (CLI) instantiated by `bin/mt2rspec`
|
9
9
|
class CLI
|
10
|
-
E_USAGE = 1
|
11
|
-
E_FILE_NOT_FOUND = 2
|
12
|
-
E_FILE_ALREADY_EXISTS = 3
|
13
|
-
E_CONVERT_FAIL = 4
|
14
|
-
E_CANNOT_CREATE_TARGET_DIR = 5
|
10
|
+
E_USAGE = 1
|
11
|
+
E_FILE_NOT_FOUND = 2
|
12
|
+
E_FILE_ALREADY_EXISTS = 3
|
13
|
+
E_CONVERT_FAIL = 4
|
14
|
+
E_CANNOT_CREATE_TARGET_DIR = 5
|
15
15
|
|
16
|
-
BANNER = <<~EOS
|
16
|
+
BANNER = <<~EOS
|
17
17
|
Usage: mt2rspec [--rails] [--mocha] source_file [target_file]
|
18
18
|
|
19
19
|
Reads source_file, writes target_file. If target_file is omitted,
|
@@ -23,8 +23,8 @@ module MinitestToRspec
|
|
23
23
|
|
24
24
|
Options:
|
25
25
|
EOS
|
26
|
-
OPT_MOCHA =
|
27
|
-
OPT_RAILS = <<~EOS.tr("\n",
|
26
|
+
OPT_MOCHA = 'Convert mocha to rspec-mocks. (Experimental)'
|
27
|
+
OPT_RAILS = <<~EOS.tr("\n", ' ').freeze
|
28
28
|
Requires rails_helper instead of spec_helper.
|
29
29
|
Passes :type metadatum to RSpec.describe.
|
30
30
|
EOS
|
@@ -48,7 +48,7 @@ module MinitestToRspec
|
|
48
48
|
@source = args[0]
|
49
49
|
@target = infer_target_from @source
|
50
50
|
else
|
51
|
-
warn
|
51
|
+
warn 'Please specify source file'
|
52
52
|
exit E_USAGE
|
53
53
|
end
|
54
54
|
end
|
@@ -59,7 +59,7 @@ module MinitestToRspec
|
|
59
59
|
ensure_target_directory(target)
|
60
60
|
write_target(converter.convert(read_source, source))
|
61
61
|
rescue Error => e
|
62
|
-
|
62
|
+
warn "Failed to convert: #{e}"
|
63
63
|
exit E_CONVERT_FAIL
|
64
64
|
end
|
65
65
|
|
@@ -67,14 +67,14 @@ module MinitestToRspec
|
|
67
67
|
|
68
68
|
def assert_file_exists(file)
|
69
69
|
unless File.exist?(file)
|
70
|
-
|
70
|
+
warn "File not found: #{file}"
|
71
71
|
exit(E_FILE_NOT_FOUND)
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
75
75
|
def assert_file_does_not_exist(file)
|
76
76
|
if File.exist?(file)
|
77
|
-
|
77
|
+
warn "File already exists: #{file}"
|
78
78
|
exit(E_FILE_ALREADY_EXISTS)
|
79
79
|
end
|
80
80
|
end
|
@@ -89,16 +89,16 @@ module MinitestToRspec
|
|
89
89
|
begin
|
90
90
|
FileUtils.mkdir_p(dir)
|
91
91
|
rescue SystemCallError => e
|
92
|
-
|
93
|
-
|
92
|
+
warn "Cannot create target dir: #{dir}"
|
93
|
+
warn e.message
|
94
94
|
exit E_CANNOT_CREATE_TARGET_DIR
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
98
98
|
def infer_target_from(source)
|
99
99
|
source
|
100
|
-
.gsub(/\Atest/,
|
101
|
-
.gsub(/_test.rb\Z/,
|
100
|
+
.gsub(/\Atest/, 'spec')
|
101
|
+
.gsub(/_test.rb\Z/, '_spec.rb')
|
102
102
|
end
|
103
103
|
|
104
104
|
def read_source
|
@@ -1,9 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require_relative
|
6
|
-
require_relative
|
3
|
+
require 'ruby_parser'
|
4
|
+
require 'ruby2ruby'
|
5
|
+
require_relative 'processor'
|
6
|
+
require_relative 'errors'
|
7
7
|
|
8
8
|
module MinitestToRspec
|
9
9
|
# Converts strings of minitest code. Does not read or write files.
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'minitest_to_rspec/type'
|
4
|
+
|
5
|
+
module MinitestToRspec
|
6
|
+
module ExpressionBuilders
|
7
|
+
# Represents an `expects` or a `stubs`
|
8
|
+
class Stub
|
9
|
+
def initialize(receiver, any_instance, message, with, returns, count)
|
10
|
+
Type.assert(Sexp, receiver)
|
11
|
+
Type.bool(any_instance)
|
12
|
+
Type.assert(Sexp, message)
|
13
|
+
Type.assert([NilClass, Sexp], with)
|
14
|
+
Type.assert([NilClass, Sexp], returns)
|
15
|
+
Type.assert([NilClass, Integer], count)
|
16
|
+
@receiver = receiver
|
17
|
+
@any_instance = any_instance
|
18
|
+
@message = message
|
19
|
+
@with = with
|
20
|
+
@returns = returns
|
21
|
+
@count = count
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns a Sexp representing an RSpec stub (allow) or message
|
25
|
+
# expectation (expect)
|
26
|
+
def to_rspec_exp
|
27
|
+
stub_chain = s(:call, nil, :receive, @message)
|
28
|
+
unless @with.nil?
|
29
|
+
stub_chain = s(:call, stub_chain, :with, @with)
|
30
|
+
end
|
31
|
+
unless @returns.nil?
|
32
|
+
stub_chain = s(:call, stub_chain, :and_return, @returns)
|
33
|
+
end
|
34
|
+
unless @count.nil?
|
35
|
+
stub_chain = s(:call, stub_chain, receive_count_method)
|
36
|
+
end
|
37
|
+
expect_allow = s(:call, nil, rspec_mocks_method, @receiver.dup)
|
38
|
+
s(:call, expect_allow, :to, stub_chain)
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def receive_count_method
|
44
|
+
case @count
|
45
|
+
when 1
|
46
|
+
:once
|
47
|
+
when 2
|
48
|
+
:twice
|
49
|
+
else
|
50
|
+
raise "Unsupported message receive count: #{@count}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Returns :expect or :allow
|
55
|
+
def rspec_mocks_method
|
56
|
+
prefix = @count.nil? ? 'allow' : 'expect'
|
57
|
+
suffix = @any_instance ? '_any_instance_of' : ''
|
58
|
+
(prefix + suffix).to_sym
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative 'base'
|
4
4
|
|
5
5
|
module MinitestToRspec
|
6
6
|
module Model
|
@@ -50,7 +50,7 @@ module MinitestToRspec
|
|
50
50
|
|
51
51
|
def assert_difference?
|
52
52
|
return false unless method_name == :assert_difference
|
53
|
-
[[:str], [
|
53
|
+
[[:str], %i[str lit]].include?(argument_types)
|
54
54
|
end
|
55
55
|
|
56
56
|
def assert_no_difference?
|
@@ -72,10 +72,15 @@ module MinitestToRspec
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def calls_in_receiver_chain
|
75
|
-
receiver_chain
|
76
|
-
|
77
|
-
|
78
|
-
|
75
|
+
receiver_chain.each_with_object([]) do |e, a|
|
76
|
+
next unless sexp_type?(:call, e)
|
77
|
+
a << self.class.new(e)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def find_call_in_receiver_chain(method_names)
|
82
|
+
name_array = [method_names].flatten
|
83
|
+
calls_in_receiver_chain.find { |i| name_array.include?(i.method_name) }
|
79
84
|
end
|
80
85
|
|
81
86
|
def method_name
|
@@ -95,30 +100,13 @@ module MinitestToRspec
|
|
95
100
|
# assertion failure message, which will be discarded later.
|
96
101
|
def raise_error_args?
|
97
102
|
arg_types = arguments.map(&:sexp_type)
|
98
|
-
[[], [:str], [:const], [
|
103
|
+
[[], [:str], [:const], %i[const str]].include?(arg_types)
|
99
104
|
end
|
100
105
|
|
101
106
|
def receiver
|
102
107
|
@exp[1]
|
103
108
|
end
|
104
109
|
|
105
|
-
# While `#receiver` returns a `Sexp`, `#receiver_call`
|
106
|
-
# returns a `Model::Call`.
|
107
|
-
def receiver_call
|
108
|
-
if sexp_type?(:call, receiver)
|
109
|
-
rvc = Model::Call.new(receiver)
|
110
|
-
|
111
|
-
# TODO: Seems like a factory pattern
|
112
|
-
if rvc.method_name == :returns
|
113
|
-
Model::Calls::Returns.new(receiver)
|
114
|
-
else
|
115
|
-
rvc
|
116
|
-
end
|
117
|
-
else
|
118
|
-
raise TypeError
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
110
|
# Consider the following chain of method calls:
|
123
111
|
#
|
124
112
|
# @a.b.c
|
@@ -152,17 +140,19 @@ module MinitestToRspec
|
|
152
140
|
end
|
153
141
|
|
154
142
|
def receiver_chain_include?(method_name)
|
155
|
-
receiver_chain.compact.any? { |r|
|
143
|
+
receiver_chain.compact.any? { |r|
|
144
|
+
self.class.method_name?(r, method_name)
|
145
|
+
}
|
156
146
|
end
|
157
147
|
|
158
148
|
def require_test_helper?
|
159
149
|
method_name == :require &&
|
160
150
|
one_string_argument? &&
|
161
|
-
arguments[0][1] ==
|
151
|
+
arguments[0][1] == 'test_helper'
|
162
152
|
end
|
163
153
|
|
164
154
|
def question_mark_method?
|
165
|
-
method_name.to_s.end_with?(
|
155
|
+
method_name.to_s.end_with?('?')
|
166
156
|
end
|
167
157
|
|
168
158
|
private
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
3
|
+
require_relative 'base'
|
4
4
|
|
5
5
|
module MinitestToRspec
|
6
6
|
module Model
|
@@ -13,15 +13,15 @@ module MinitestToRspec
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def action_controller_test_case?
|
16
|
-
lineage?(parent, [
|
16
|
+
lineage?(parent, %i[ActionController TestCase])
|
17
17
|
end
|
18
18
|
|
19
19
|
def action_mailer_test_case?
|
20
|
-
lineage?(parent, [
|
20
|
+
lineage?(parent, %i[ActionMailer TestCase])
|
21
21
|
end
|
22
22
|
|
23
23
|
def active_support_test_case?
|
24
|
-
lineage?(parent, [
|
24
|
+
lineage?(parent, %i[ActiveSupport TestCase])
|
25
25
|
end
|
26
26
|
|
27
27
|
# Raise an error if we don't know now to process the name
|
@@ -45,7 +45,7 @@ module MinitestToRspec
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def draper_test_case?
|
48
|
-
lineage?(parent, [
|
48
|
+
lineage?(parent, %i[Draper TestCase])
|
49
49
|
end
|
50
50
|
|
51
51
|
# Returns the name of the class. Examples:
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require_relative
|
6
|
-
require_relative
|
7
|
-
require_relative
|
8
|
-
require_relative
|
3
|
+
require 'ruby_parser'
|
4
|
+
require 'sexp_processor'
|
5
|
+
require_relative 'subprocessors/call'
|
6
|
+
require_relative 'subprocessors/defn'
|
7
|
+
require_relative 'subprocessors/klass'
|
8
|
+
require_relative 'subprocessors/iter'
|
9
9
|
|
10
10
|
module MinitestToRspec
|
11
11
|
# Consumes a `String` of minitest code and returns an S-expression
|
@@ -1,9 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
require_relative
|
6
|
-
require_relative
|
3
|
+
require 'minitest_to_rspec/type'
|
4
|
+
require 'minitest_to_rspec/expression_builders/stub'
|
5
|
+
require_relative '../model/call'
|
6
|
+
require_relative '../model/hash_exp'
|
7
|
+
require_relative 'base'
|
7
8
|
|
8
9
|
module MinitestToRspec
|
9
10
|
module Subprocessors
|
@@ -166,9 +167,21 @@ module MinitestToRspec
|
|
166
167
|
expect_to_not(eq(unexpected), calculated, true)
|
167
168
|
end
|
168
169
|
|
170
|
+
# Processes an entire line of code that ends in `.returns`
|
169
171
|
def method_returns
|
170
|
-
|
171
|
-
|
172
|
+
receiver = mocha_stub_receiver(@exp)
|
173
|
+
any_instance = rspec_any_instance?(@exp)
|
174
|
+
message_call = mocha_stub_expects(@exp)
|
175
|
+
message = message_call.arguments.first
|
176
|
+
with = mocha_stub_with(@exp)
|
177
|
+
returns = @exp.arguments.first
|
178
|
+
count = message_call.method_name == :expects ? 1 : nil
|
179
|
+
ExpressionBuilders::Stub.new(
|
180
|
+
receiver, any_instance, message, with, returns, count
|
181
|
+
).to_rspec_exp
|
182
|
+
rescue StandardError
|
183
|
+
# TODO: We used to have an `UnknownVariant` error.
|
184
|
+
# That was nice and specific.
|
172
185
|
@exp.original
|
173
186
|
end
|
174
187
|
|
@@ -180,6 +193,10 @@ module MinitestToRspec
|
|
180
193
|
end
|
181
194
|
end
|
182
195
|
|
196
|
+
def method_should
|
197
|
+
s(:call, nil, :it, *@exp.arguments)
|
198
|
+
end
|
199
|
+
|
183
200
|
# Happily, the no-block signatures of [stub][3] are the
|
184
201
|
# same as [double][2].
|
185
202
|
#
|
@@ -200,7 +217,7 @@ module MinitestToRspec
|
|
200
217
|
def method_stub_everything
|
201
218
|
if @exp.receiver.nil?
|
202
219
|
d = s(:call, nil, :double, *@exp.arguments)
|
203
|
-
s(:call, d, :as_null_object
|
220
|
+
s(:call, d, :as_null_object)
|
204
221
|
else
|
205
222
|
@exp.original
|
206
223
|
end
|
@@ -236,35 +253,50 @@ module MinitestToRspec
|
|
236
253
|
expect_to(receive_and_call_original(lit_sexp), exp.receiver, true)
|
237
254
|
end
|
238
255
|
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
256
|
+
# TODO: add support for
|
257
|
+
# - at_least
|
258
|
+
# - at_least_once
|
259
|
+
# - at_most
|
260
|
+
# - at_most_once
|
261
|
+
# - never
|
262
|
+
def mocha_expectation_count(exp, count)
|
263
|
+
Type.assert(Model::Call, exp)
|
264
|
+
Type.assert(Integer, count)
|
265
|
+
receiver = mocha_stub_receiver(exp)
|
266
|
+
any_instance = rspec_any_instance?(exp)
|
267
|
+
message = mocha_stub_expects(exp).arguments.first
|
268
|
+
with = mocha_stub_with(exp)
|
269
|
+
returns = exp.find_call_in_receiver_chain(:returns)&.arguments&.first
|
270
|
+
ExpressionBuilders::Stub.new(
|
271
|
+
receiver, any_instance, message, with, returns, count
|
272
|
+
).to_rspec_exp
|
273
|
+
end
|
274
|
+
|
275
|
+
# Given a mocha stub, e.g. `X.any_instance.expects(:y)`, returns `X`.
|
276
|
+
def mocha_stub_receiver(exp)
|
277
|
+
chain = exp.receiver_chain
|
278
|
+
last = chain[-1]
|
279
|
+
last.nil? ? chain[-2] : last
|
280
|
+
end
|
281
|
+
|
282
|
+
# Given an `exp` representing a chain of calls, like
|
283
|
+
# `stubs(x).returns(y).once`, finds the call to `stubs` or `expects`.
|
284
|
+
def mocha_stub_expects(exp)
|
285
|
+
exp.find_call_in_receiver_chain(%i[stubs expects])
|
286
|
+
end
|
287
|
+
|
288
|
+
def mocha_stub_with(exp)
|
289
|
+
exp.find_call_in_receiver_chain(:with)&.arguments&.first
|
290
|
+
end
|
291
|
+
|
292
|
+
def rspec_any_instance?(exp)
|
293
|
+
exp.calls_in_receiver_chain.any? { |i|
|
294
|
+
i.method_name.to_s.include?('any_instance')
|
295
|
+
}
|
250
296
|
end
|
251
297
|
|
252
298
|
def mocha_once(exp)
|
253
|
-
mocha_expectation_count(exp,
|
254
|
-
end
|
255
|
-
|
256
|
-
# Given `r`, a `Model::Calls::Returns`, return a `Sexp` representing
|
257
|
-
# the equivalent stub or message expectation in RSpec.
|
258
|
-
def mocha_returns(r)
|
259
|
-
raise ArgumentError unless r.is_a?(Model::Calls::Returns)
|
260
|
-
subprocessor_method = "#{r.rspec_mocks_method}_receive_and_return"
|
261
|
-
send(subprocessor_method,
|
262
|
-
r.rspec_msg_recipient,
|
263
|
-
r.message,
|
264
|
-
r.values,
|
265
|
-
r.any_instance?,
|
266
|
-
r.with
|
267
|
-
)
|
299
|
+
mocha_expectation_count(exp, 1)
|
268
300
|
end
|
269
301
|
|
270
302
|
def mocha_stub(exp)
|
@@ -277,7 +309,7 @@ module MinitestToRspec
|
|
277
309
|
end
|
278
310
|
|
279
311
|
def mocha_twice(exp)
|
280
|
-
mocha_expectation_count(exp,
|
312
|
+
mocha_expectation_count(exp, 2)
|
281
313
|
end
|
282
314
|
|
283
315
|
def name_of_processing_method
|
@@ -307,7 +339,7 @@ module MinitestToRspec
|
|
307
339
|
s(:call, nil, :lambda),
|
308
340
|
0,
|
309
341
|
s(:block,
|
310
|
-
s(:str,
|
342
|
+
s(:str, 'Sorry for the pointless lambda here.'),
|
311
343
|
*array_of_calls
|
312
344
|
)
|
313
345
|
),
|
@@ -341,7 +373,7 @@ module MinitestToRspec
|
|
341
373
|
end
|
342
374
|
|
343
375
|
def require_spec_helper
|
344
|
-
prefix = @rails ?
|
376
|
+
prefix = @rails ? 'rails' : 'spec'
|
345
377
|
s(:call, nil, :require, s(:str, "#{prefix}_helper"))
|
346
378
|
end
|
347
379
|
|
@@ -1,8 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative
|
3
|
+
require_relative '../errors'
|
4
|
+
require_relative '../model/klass'
|
5
|
+
require_relative 'base'
|
6
6
|
|
7
7
|
module MinitestToRspec
|
8
8
|
module Subprocessors
|
@@ -39,7 +39,7 @@ module MinitestToRspec
|
|
39
39
|
# Given a `test_class_name` like `BananaTest`, returns the
|
40
40
|
# described class, like `Banana`.
|
41
41
|
def described_class(test_class_name)
|
42
|
-
test_class_name.to_s.gsub(/Test\Z/,
|
42
|
+
test_class_name.to_s.gsub(/Test\Z/, '').to_sym
|
43
43
|
end
|
44
44
|
|
45
45
|
# Returns the head of the output Sexp. If it's a test case,
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module MinitestToRspec
|
4
|
+
# Runtime type assertion function.
|
5
|
+
module Type
|
6
|
+
class << self
|
7
|
+
def assert(types, value)
|
8
|
+
unless array_wrap(types).any? { |t| value.is_a?(t) }
|
9
|
+
raise TypeError, "Expected #{types}, got #{value}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def bool(value)
|
14
|
+
unless [false, true].include?(value)
|
15
|
+
raise TypeError, "Expected Boolean, got #{value}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# Implementation copied from Array.wrap in ActiveSupport 5
|
22
|
+
def array_wrap(object)
|
23
|
+
if object.nil?
|
24
|
+
[]
|
25
|
+
elsif object.respond_to?(:to_ary)
|
26
|
+
object.to_ary || [object]
|
27
|
+
else
|
28
|
+
[object]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/minitest_to_rspec.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require 'minitest_to_rspec/version'
|
4
|
+
require 'minitest_to_rspec/converter'
|
5
5
|
|
6
6
|
# A command-line tool for converting minitest files to rspec.
|
7
7
|
module MinitestToRspec
|
data/minitest_to_rspec.gemspec
CHANGED
@@ -5,32 +5,32 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
5
|
require 'minitest_to_rspec/version'
|
6
6
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
|
-
spec.name =
|
8
|
+
spec.name = 'minitest_to_rspec'
|
9
9
|
spec.version = MinitestToRspec::VERSION
|
10
10
|
spec.executables << 'mt2rspec'
|
11
|
-
spec.authors = [
|
12
|
-
spec.email = [
|
11
|
+
spec.authors = ['Jared Beck']
|
12
|
+
spec.email = ['jared@jaredbeck.com']
|
13
13
|
|
14
|
-
spec.summary =
|
14
|
+
spec.summary = 'Converts minitest files to rspec'
|
15
15
|
spec.description = <<~EOS
|
16
16
|
A command-line tool for converting minitest files to rspec.
|
17
17
|
EOS
|
18
|
-
spec.homepage =
|
19
|
-
spec.license =
|
18
|
+
spec.homepage = 'https://github.com/jaredbeck/minitest_to_rspec'
|
19
|
+
spec.license = 'MIT'
|
20
20
|
|
21
21
|
spec.files = `git ls-files -z`.split("\x0").reject { |f|
|
22
22
|
f.match(%r{^(test|spec|features)/})
|
23
23
|
}
|
24
|
-
spec.require_paths = [
|
25
|
-
spec.required_ruby_version =
|
24
|
+
spec.require_paths = ['lib']
|
25
|
+
spec.required_ruby_version = '>= 2.3.0'
|
26
26
|
|
27
|
-
spec.add_runtime_dependency
|
28
|
-
spec.add_runtime_dependency
|
29
|
-
spec.add_runtime_dependency
|
27
|
+
spec.add_runtime_dependency 'ruby2ruby', '~> 2.3'
|
28
|
+
spec.add_runtime_dependency 'ruby_parser', '~> 3.8'
|
29
|
+
spec.add_runtime_dependency 'trollop', '~> 2.1'
|
30
30
|
|
31
|
-
spec.add_development_dependency
|
32
|
-
spec.add_development_dependency
|
33
|
-
spec.add_development_dependency
|
34
|
-
spec.add_development_dependency
|
35
|
-
spec.add_development_dependency
|
31
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
32
|
+
spec.add_development_dependency 'byebug', '~> 9.1'
|
33
|
+
spec.add_development_dependency 'rake', '~> 12.1'
|
34
|
+
spec.add_development_dependency 'rspec', '~> 3.5'
|
35
|
+
spec.add_development_dependency 'rubocop', '~> 0.51.0'
|
36
36
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: minitest_to_rspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jared Beck
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-11-
|
11
|
+
date: 2017-11-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ruby2ruby
|
@@ -134,7 +134,6 @@ extra_rdoc_files: []
|
|
134
134
|
files:
|
135
135
|
- ".gitignore"
|
136
136
|
- ".rubocop.yml"
|
137
|
-
- ".rubocop_todo.yml"
|
138
137
|
- ".travis.yml"
|
139
138
|
- CHANGELOG.md
|
140
139
|
- CODE_OF_CONDUCT.md
|
@@ -145,16 +144,17 @@ files:
|
|
145
144
|
- bin/console
|
146
145
|
- bin/mt2rspec
|
147
146
|
- doc/minitest.md
|
147
|
+
- doc/mocha/mocha_test.rb
|
148
148
|
- doc/rspec.md
|
149
149
|
- doc/supported_assertions.md
|
150
150
|
- lib/minitest_to_rspec.rb
|
151
151
|
- lib/minitest_to_rspec/cli.rb
|
152
152
|
- lib/minitest_to_rspec/converter.rb
|
153
153
|
- lib/minitest_to_rspec/errors.rb
|
154
|
+
- lib/minitest_to_rspec/expression_builders/stub.rb
|
154
155
|
- lib/minitest_to_rspec/model/base.rb
|
155
156
|
- lib/minitest_to_rspec/model/call.rb
|
156
157
|
- lib/minitest_to_rspec/model/calls/once.rb
|
157
|
-
- lib/minitest_to_rspec/model/calls/returns.rb
|
158
158
|
- lib/minitest_to_rspec/model/calls/twice.rb
|
159
159
|
- lib/minitest_to_rspec/model/defn.rb
|
160
160
|
- lib/minitest_to_rspec/model/hash_exp.rb
|
@@ -167,6 +167,7 @@ files:
|
|
167
167
|
- lib/minitest_to_rspec/subprocessors/defn.rb
|
168
168
|
- lib/minitest_to_rspec/subprocessors/iter.rb
|
169
169
|
- lib/minitest_to_rspec/subprocessors/klass.rb
|
170
|
+
- lib/minitest_to_rspec/type.rb
|
170
171
|
- lib/minitest_to_rspec/version.rb
|
171
172
|
- minitest_to_rspec.gemspec
|
172
173
|
homepage: https://github.com/jaredbeck/minitest_to_rspec
|
data/.rubocop_todo.yml
DELETED
@@ -1,57 +0,0 @@
|
|
1
|
-
# This configuration was generated by
|
2
|
-
# `rubocop --auto-gen-config`
|
3
|
-
# on 2017-11-01 23:47:55 -0400 using RuboCop version 0.51.0.
|
4
|
-
# The point is for the user to remove these configuration records
|
5
|
-
# one by one as the offenses are removed from the code base.
|
6
|
-
# Note that changes in the inspected code, or installation of new
|
7
|
-
# versions of RuboCop, may require this file to be generated again.
|
8
|
-
|
9
|
-
# Offense count: 5
|
10
|
-
# Cop supports --auto-correct.
|
11
|
-
Style/RedundantFreeze:
|
12
|
-
Exclude:
|
13
|
-
- 'lib/minitest_to_rspec/cli.rb'
|
14
|
-
|
15
|
-
# Offense count: 1
|
16
|
-
# Cop supports --auto-correct.
|
17
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
18
|
-
# SupportedStyles: only_raise, only_fail, semantic
|
19
|
-
Style/SignalException:
|
20
|
-
Exclude:
|
21
|
-
- 'spec/lib/cli_spec.rb'
|
22
|
-
|
23
|
-
# Offense count: 5
|
24
|
-
# Cop supports --auto-correct.
|
25
|
-
Style/StderrPuts:
|
26
|
-
Exclude:
|
27
|
-
- 'lib/minitest_to_rspec/cli.rb'
|
28
|
-
|
29
|
-
# Offense count: 340
|
30
|
-
# Cop supports --auto-correct.
|
31
|
-
# Configuration parameters: EnforcedStyle, SupportedStyles, ConsistentQuotesInMultiline.
|
32
|
-
# SupportedStyles: single_quotes, double_quotes
|
33
|
-
Style/StringLiterals:
|
34
|
-
Enabled: false
|
35
|
-
|
36
|
-
# Offense count: 8
|
37
|
-
# Cop supports --auto-correct.
|
38
|
-
# Configuration parameters: SupportedStyles.
|
39
|
-
# SupportedStyles: percent, brackets
|
40
|
-
Style/SymbolArray:
|
41
|
-
EnforcedStyle: percent
|
42
|
-
MinSize: 3
|
43
|
-
|
44
|
-
# Offense count: 1
|
45
|
-
# Cop supports --auto-correct.
|
46
|
-
# Configuration parameters: EnforcedStyleForMultiline, SupportedStylesForMultiline.
|
47
|
-
# SupportedStylesForMultiline: comma, consistent_comma, no_comma
|
48
|
-
Style/TrailingCommaInArguments:
|
49
|
-
Exclude:
|
50
|
-
- 'lib/minitest_to_rspec/subprocessors/call.rb'
|
51
|
-
|
52
|
-
# Offense count: 1
|
53
|
-
# Cop supports --auto-correct.
|
54
|
-
# Configuration parameters: MaxLineLength.
|
55
|
-
Style/WhileUntilModifier:
|
56
|
-
Exclude:
|
57
|
-
- 'lib/minitest_to_rspec/subprocessors/iter.rb'
|
@@ -1,87 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative "../call"
|
4
|
-
require_relative "../../errors"
|
5
|
-
|
6
|
-
module MinitestToRspec
|
7
|
-
module Model
|
8
|
-
module Calls
|
9
|
-
# Represents a call to `returns`, the stubbing method
|
10
|
-
# from `mocha`.
|
11
|
-
class Returns < Call
|
12
|
-
KNOWN_RECEIVERS = %i[stubs expects with].freeze
|
13
|
-
|
14
|
-
def initialize(exp)
|
15
|
-
@exp = exp
|
16
|
-
raise UnknownVariant unless known_variant?
|
17
|
-
end
|
18
|
-
|
19
|
-
def stub?
|
20
|
-
receiver_chain_include?(:stubs)
|
21
|
-
end
|
22
|
-
|
23
|
-
def any_instance?
|
24
|
-
receiver_chain_include?(:any_instance)
|
25
|
-
end
|
26
|
-
|
27
|
-
def expectation?
|
28
|
-
receiver_chain_include?(:expects)
|
29
|
-
end
|
30
|
-
|
31
|
-
def known_variant?
|
32
|
-
r = receiver
|
33
|
-
!r.nil? &&
|
34
|
-
r.sexp_type == :call &&
|
35
|
-
KNOWN_RECEIVERS.include?(Call.new(r).method_name) &&
|
36
|
-
!values.empty? &&
|
37
|
-
message.sexp_type == :lit
|
38
|
-
end
|
39
|
-
|
40
|
-
def message
|
41
|
-
calls_in_receiver_chain
|
42
|
-
.find { |c| [:stubs, :expects].include? c.method_name }
|
43
|
-
.arguments[0]
|
44
|
-
end
|
45
|
-
|
46
|
-
# To avoid a `ProcessingError` please check `known_variant?`
|
47
|
-
# before calling `rspec_mocks_method`.
|
48
|
-
def rspec_mocks_method
|
49
|
-
s = stub?
|
50
|
-
e = expectation?
|
51
|
-
if s && e
|
52
|
-
raise ProcessingError, "Method chain contains stubs and expects"
|
53
|
-
elsif s
|
54
|
-
:allow
|
55
|
-
elsif e
|
56
|
-
:expect
|
57
|
-
else
|
58
|
-
raise ProcessingError, "Found returns without stubs or expects"
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
# Returns `Sexp` representing the object that will receive
|
63
|
-
# the stubbed message. Examples:
|
64
|
-
#
|
65
|
-
# banana.stubs(:delicious?).returns(true)
|
66
|
-
# Kiwi.any_instance.stubs(:delicious?).returns(false)
|
67
|
-
#
|
68
|
-
# On the first line, the `rspec_msg_recipient` is `banana`. On the
|
69
|
-
# second, `Kiwi`.
|
70
|
-
#
|
71
|
-
def rspec_msg_recipient
|
72
|
-
receiver_chain.compact.last
|
73
|
-
end
|
74
|
-
|
75
|
-
# The return values
|
76
|
-
def values
|
77
|
-
arguments
|
78
|
-
end
|
79
|
-
|
80
|
-
def with
|
81
|
-
w = calls_in_receiver_chain.find { |c| c.method_name == :with }
|
82
|
-
w.nil? ? [] : w.arguments
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
end
|