minitest_to_rspec 0.11.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +3 -2
  3. data/CHANGELOG.md +19 -0
  4. data/README.md +3 -0
  5. data/lib/minitest_to_rspec/converter.rb +2 -2
  6. data/lib/minitest_to_rspec/input/model/base.rb +15 -0
  7. data/lib/minitest_to_rspec/input/model/call.rb +185 -0
  8. data/lib/minitest_to_rspec/input/model/defn.rb +37 -0
  9. data/lib/minitest_to_rspec/input/model/hash_exp.rb +24 -0
  10. data/lib/minitest_to_rspec/input/model/iter.rb +89 -0
  11. data/lib/minitest_to_rspec/input/model/klass.rb +102 -0
  12. data/lib/minitest_to_rspec/input/processor.rb +40 -0
  13. data/lib/minitest_to_rspec/input/subprocessors/base.rb +91 -0
  14. data/lib/minitest_to_rspec/input/subprocessors/call.rb +279 -0
  15. data/lib/minitest_to_rspec/input/subprocessors/defn.rb +64 -0
  16. data/lib/minitest_to_rspec/input/subprocessors/iter.rb +148 -0
  17. data/lib/minitest_to_rspec/input/subprocessors/klass.rb +101 -0
  18. data/lib/minitest_to_rspec/minitest/stub.rb +85 -0
  19. data/lib/minitest_to_rspec/{expression_builders → rspec}/stub.rb +3 -2
  20. data/lib/minitest_to_rspec/type.rb +1 -1
  21. data/lib/minitest_to_rspec/version.rb +1 -1
  22. metadata +17 -18
  23. data/lib/minitest_to_rspec/model/base.rb +0 -13
  24. data/lib/minitest_to_rspec/model/call.rb +0 -165
  25. data/lib/minitest_to_rspec/model/calls/once.rb +0 -13
  26. data/lib/minitest_to_rspec/model/calls/twice.rb +0 -13
  27. data/lib/minitest_to_rspec/model/defn.rb +0 -27
  28. data/lib/minitest_to_rspec/model/hash_exp.rb +0 -20
  29. data/lib/minitest_to_rspec/model/iter.rb +0 -79
  30. data/lib/minitest_to_rspec/model/klass.rb +0 -100
  31. data/lib/minitest_to_rspec/processor.rb +0 -38
  32. data/lib/minitest_to_rspec/subprocessors/base.rb +0 -89
  33. data/lib/minitest_to_rspec/subprocessors/call.rb +0 -391
  34. data/lib/minitest_to_rspec/subprocessors/defn.rb +0 -49
  35. data/lib/minitest_to_rspec/subprocessors/iter.rb +0 -138
  36. data/lib/minitest_to_rspec/subprocessors/klass.rb +0 -99
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: be2fe63a020fb7a38b10551341162eb978a0b84c
4
- data.tar.gz: '0696d05d0c95b8cb6afbe1865ae224b2e8066e86'
2
+ SHA256:
3
+ metadata.gz: e8f9207756131c32b3622da37695b0da546d38749df1d22ae1f7d1daa1f1f1a5
4
+ data.tar.gz: dfb8bb34cd541ed7172822c98ce84db91bb7b99af0bd3f01d907da50a0472af1
5
5
  SHA512:
6
- metadata.gz: 1f44130fe3b150666829ff09abd348e92dffa6104f70678412ea1ef9e9e7cb363280549930796062d4c346590f634584cab18cd9db92f1c16f5a876b3ae88833
7
- data.tar.gz: ef3a2361df027ddb59c33f858c49641f295298fa60d6a140bc63b60408e9706c2ec4d57cba346ed964d1eb7de5aa017b016b1bf151f403dfac5046f618b49c5b
6
+ metadata.gz: 45025ed9cdf045697a49d0571811fa14919ba91868044630de17f4436a0f1ffa32c6f172a9b8518eb7139dadce949798caa6a37828101303892d1055c3522001
7
+ data.tar.gz: 3ea95cd4da9200505c5c23bf072d084aa37d4994add74f8689e9766061046aa8a68ce6f66adb5c10d325143b3e73a878a86bafc5693088e5016fc4a4d01c7385
@@ -1,7 +1,8 @@
1
1
  language: ruby
2
2
  rvm:
3
- - "2.3.5"
4
- - "2.4.2"
3
+ - "2.3.6"
4
+ - "2.4.3"
5
+ - "2.5.0"
5
6
  script: bundle exec rake
6
7
  sudo: false
7
8
  notifications:
@@ -17,6 +17,25 @@ of [keepachangelog.com][2].
17
17
 
18
18
  - None
19
19
 
20
+ ## 0.12.0 (2018-03-11)
21
+
22
+ ### Breaking Changes
23
+
24
+ - None
25
+
26
+ ### Added
27
+
28
+ - [#21](https://github.com/jaredbeck/minitest_to_rspec/pull/21) -
29
+ convert `setup`/`teardown` methods to `before`/`after` blocks
30
+ - [#20](https://github.com/jaredbeck/minitest_to_rspec/pull/20) -
31
+ Support `refute_raise[s]`
32
+ - [#18](https://github.com/jaredbeck/minitest_to_rspec/pull/18) -
33
+ Support namespaced exceptions for assert_raise[s]
34
+
35
+ ### Fixed
36
+
37
+ - None
38
+
20
39
  ## 0.11.0 (2017-11-10)
21
40
 
22
41
  ### Breaking Changes
data/README.md CHANGED
@@ -97,6 +97,8 @@ assert_not_nil | |
97
97
  [assert_raises][13] | 0..2 | Minitest
98
98
  refute | |
99
99
  refute_equal | |
100
+ [refute_raise][39] | |
101
+ [refute_raises][39] | |
100
102
 
101
103
  ## Supported Mocha
102
104
 
@@ -160,3 +162,4 @@ This project would not be possible without [ruby_parser][14],
160
162
  [36]: http://www.rubydoc.info/github/thoughtbot/shoulda-context/master/Shoulda/Context/ClassMethods#context-instance_method
161
163
  [37]: http://www.rubydoc.info/github/thoughtbot/shoulda-context/master/Shoulda/Context/Context#setup-instance_method
162
164
  [38]: http://www.rubydoc.info/github/thoughtbot/shoulda-context/master/Shoulda/Context/ClassMethods#should-instance_method
165
+ [39]: https://github.com/jaredbeck/minitest_to_rspec/pull/20
@@ -2,14 +2,14 @@
2
2
 
3
3
  require 'ruby_parser'
4
4
  require 'ruby2ruby'
5
- require_relative 'processor'
5
+ require 'minitest_to_rspec/input/processor'
6
6
  require_relative 'errors'
7
7
 
8
8
  module MinitestToRspec
9
9
  # Converts strings of minitest code. Does not read or write files.
10
10
  class Converter
11
11
  def initialize(rails: false, mocha: false)
12
- @processor = Processor.new(rails, mocha)
12
+ @processor = Input::Processor.new(rails, mocha)
13
13
  end
14
14
 
15
15
  # - `input` - Contents of a ruby file.
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest_to_rspec/sexp_assertions'
4
+
5
+ module MinitestToRspec
6
+ module Input
7
+ module Model
8
+ # Input models are simple data objects
9
+ # representing the S-expressions they are named after.
10
+ class Base
11
+ include SexpAssertions
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,185 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest_to_rspec/input/model/base'
4
+
5
+ module MinitestToRspec
6
+ module Input
7
+ module Model
8
+ # Data object. Represents a `:call` s-expression.
9
+ class Call < Base
10
+ attr_reader :original
11
+
12
+ def initialize(exp)
13
+ assert_sexp_type(:call, exp)
14
+ @exp = exp.dup
15
+ @original = exp.dup
16
+ end
17
+
18
+ class << self
19
+ def assert_difference?(exp)
20
+ exp.sexp_type == :call && new(exp).assert_difference?
21
+ end
22
+
23
+ def assert_no_difference?(exp)
24
+ exp.sexp_type == :call && new(exp).assert_no_difference?
25
+ end
26
+
27
+ def assert_nothing_raised?(exp)
28
+ exp.sexp_type == :call && new(exp).assert_nothing_raised?
29
+ end
30
+
31
+ def assert_raise?(exp)
32
+ exp.sexp_type == :call && new(exp).assert_raise?
33
+ end
34
+
35
+ def assert_raises?(exp)
36
+ exp.sexp_type == :call && new(exp).assert_raises?
37
+ end
38
+
39
+ def refute_raise?(exp)
40
+ exp.sexp_type == :call && new(exp).refute_raise?
41
+ end
42
+
43
+ def refute_raises?(exp)
44
+ exp.sexp_type == :call && new(exp).refute_raises?
45
+ end
46
+
47
+ def method_name?(exp, name)
48
+ exp.sexp_type == :call && new(exp).method_name.to_s == name.to_s
49
+ end
50
+ end
51
+
52
+ def arguments
53
+ @exp[3..-1] || []
54
+ end
55
+
56
+ def argument_types
57
+ arguments.map(&:sexp_type)
58
+ end
59
+
60
+ def assert_difference?
61
+ return false unless method_name == :assert_difference
62
+ [[:str], %i[str lit]].include?(argument_types)
63
+ end
64
+
65
+ def assert_no_difference?
66
+ method_name == :assert_no_difference &&
67
+ arguments.length == 1 &&
68
+ arguments[0].sexp_type == :str
69
+ end
70
+
71
+ def assert_nothing_raised?
72
+ method_name == :assert_nothing_raised && arguments.empty?
73
+ end
74
+
75
+ def assert_raise?
76
+ method_name == :assert_raise && raise_error_args?
77
+ end
78
+
79
+ def assert_raises?
80
+ method_name == :assert_raises && raise_error_args?
81
+ end
82
+
83
+ def refute_raise?
84
+ method_name == :refute_raise && raise_error_args?
85
+ end
86
+
87
+ def refute_raises?
88
+ method_name == :refute_raises && raise_error_args?
89
+ end
90
+
91
+ def calls_in_receiver_chain
92
+ receiver_chain.each_with_object([]) do |e, a|
93
+ next unless sexp_type?(:call, e)
94
+ a << self.class.new(e)
95
+ end
96
+ end
97
+
98
+ def find_call_in_receiver_chain(method_names)
99
+ name_array = [method_names].flatten
100
+ calls_in_receiver_chain.find { |i|
101
+ name_array.include?(i.method_name)
102
+ }
103
+ end
104
+
105
+ def method_name
106
+ @exp[2]
107
+ end
108
+
109
+ def num_arguments
110
+ arguments.length
111
+ end
112
+
113
+ def one_string_argument?
114
+ arguments.length == 1 && string?(arguments[0])
115
+ end
116
+
117
+ # Returns true if arguments can be processed into RSpec's `raise_error`
118
+ # matcher. When the last argument is a string, it represents the
119
+ # assertion failure message, which will be discarded later.
120
+ def raise_error_args?
121
+ arg_types = arguments.map(&:sexp_type)
122
+ [[], [:str], [:const], %i[const str], [:colon2]].include?(arg_types)
123
+ end
124
+
125
+ def receiver
126
+ @exp[1]
127
+ end
128
+
129
+ # Consider the following chain of method calls:
130
+ #
131
+ # @a.b.c
132
+ #
133
+ # whose S-expression is
134
+ #
135
+ # s(:call, s(:call, s(:call, nil, :a), :b), :c)
136
+ #
137
+ # the "receiver chain" is
138
+ #
139
+ # [
140
+ # s(:call, s(:call, nil, :a), :b),
141
+ # s(:call, nil, :a),
142
+ # nil
143
+ # ]
144
+ #
145
+ # The order of the returned array matches the order in which
146
+ # messages are received, i.e. the order of execution.
147
+ #
148
+ # Note that the final receiver `nil` is included. This `nil`
149
+ # represents the implicit receiver, e.g. `self` or `main`.
150
+ #
151
+ def receiver_chain
152
+ receivers = []
153
+ ptr = @exp
154
+ while sexp_type?(:call, ptr)
155
+ receivers << ptr[1]
156
+ ptr = ptr[1]
157
+ end
158
+ receivers
159
+ end
160
+
161
+ def receiver_chain_include?(method_name)
162
+ receiver_chain.compact.any? { |r|
163
+ self.class.method_name?(r, method_name)
164
+ }
165
+ end
166
+
167
+ def require_test_helper?
168
+ method_name == :require &&
169
+ one_string_argument? &&
170
+ arguments[0][1] == 'test_helper'
171
+ end
172
+
173
+ def question_mark_method?
174
+ method_name.to_s.end_with?('?')
175
+ end
176
+
177
+ private
178
+
179
+ def string?(exp)
180
+ exp.sexp_type == :str
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest_to_rspec/input/model/base'
4
+
5
+ module MinitestToRspec
6
+ module Input
7
+ module Model
8
+ # Data object. Represents a `:defn` s-expression.
9
+ class Defn < Base
10
+ def initialize(exp)
11
+ assert_sexp_type(:defn, exp)
12
+ @exp = exp.dup
13
+ end
14
+
15
+ def body
16
+ @exp[3..-1]
17
+ end
18
+
19
+ def method_name
20
+ @exp[1].to_s
21
+ end
22
+
23
+ def test_method?
24
+ method_name.start_with?('test_')
25
+ end
26
+
27
+ def setup?
28
+ method_name == 'setup'
29
+ end
30
+
31
+ def teardown?
32
+ method_name == 'teardown'
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest_to_rspec/input/model/base'
4
+
5
+ module MinitestToRspec
6
+ module Input
7
+ module Model
8
+ # Data object. Represents a `:hash` S-expression.
9
+ class HashExp < Base
10
+ def initialize(sexp)
11
+ assert_sexp_type(:hash, sexp)
12
+ @exp = sexp.dup
13
+ end
14
+
15
+ # A slightly nicer implementation would be:
16
+ # `@exp[1..-1].each_slice(2).to_h`
17
+ # but that would require ruby >= 2.1
18
+ def to_h
19
+ Hash[@exp[1..-1].each_slice(2).to_a]
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest_to_rspec/input/model/base'
4
+
5
+ module MinitestToRspec
6
+ module Input
7
+ module Model
8
+ # Data object. Represents an `:iter` s-expression.
9
+ class Iter < Base
10
+ def initialize(exp)
11
+ assert_sexp_type(:iter, exp)
12
+ @exp = exp.dup
13
+ end
14
+
15
+ def [](*args)
16
+ @exp[*args]
17
+ end
18
+
19
+ def assert_difference?
20
+ !empty? && Model::Call.assert_difference?(@exp[1])
21
+ end
22
+
23
+ def assert_no_difference?
24
+ !empty? && Model::Call.assert_no_difference?(@exp[1])
25
+ end
26
+
27
+ def assert_nothing_raised?
28
+ !empty? && Model::Call.assert_nothing_raised?(@exp[1])
29
+ end
30
+
31
+ def assert_raise?
32
+ !empty? && Model::Call.assert_raise?(@exp[1])
33
+ end
34
+
35
+ def assert_raises?
36
+ !empty? && Model::Call.assert_raises?(@exp[1])
37
+ end
38
+
39
+ def refute_raise?
40
+ !empty? && Model::Call.refute_raise?(@exp[1])
41
+ end
42
+
43
+ def refute_raises?
44
+ !empty? && Model::Call.refute_raises?(@exp[1])
45
+ end
46
+
47
+ def block
48
+ @exp[3]
49
+ end
50
+
51
+ def call
52
+ @exp[1]
53
+ end
54
+
55
+ # Not to be confused with block arguments.
56
+ def call_arguments
57
+ call_obj.arguments
58
+ end
59
+
60
+ def call_obj
61
+ Model::Call.new(call)
62
+ end
63
+
64
+ # Enumerates children, skipping the base `call` and
65
+ # starting with the block arguments, then each `:call` in
66
+ # the block.
67
+ def each
68
+ @exp[2..-1].each do |e| yield(e) end
69
+ end
70
+
71
+ def empty?
72
+ @exp.length == 1 # just the sexp_type
73
+ end
74
+
75
+ def setup?
76
+ !empty? && Model::Call.method_name?(@exp[1], :setup)
77
+ end
78
+
79
+ def teardown?
80
+ !empty? && Model::Call.method_name?(@exp[1], :teardown)
81
+ end
82
+
83
+ def sexp
84
+ @exp
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'minitest_to_rspec/input/model/base'
4
+
5
+ module MinitestToRspec
6
+ module Input
7
+ module Model
8
+ # Data object. Represents a `:class` S-expression.
9
+ class Klass < Base
10
+ def initialize(exp)
11
+ assert_sexp_type(:class, exp)
12
+ @exp = exp.dup
13
+ assert_valid_name
14
+ end
15
+
16
+ def action_controller_test_case?
17
+ lineage?(parent, %i[ActionController TestCase])
18
+ end
19
+
20
+ def action_mailer_test_case?
21
+ lineage?(parent, %i[ActionMailer TestCase])
22
+ end
23
+
24
+ def active_support_test_case?
25
+ lineage?(parent, %i[ActiveSupport TestCase])
26
+ end
27
+
28
+ # Raise an error if we don't know now to process the name
29
+ # of this class. Specifically, classes with module-shorthand.
30
+ def assert_valid_name
31
+ if name.is_a?(Symbol)
32
+ # Valid
33
+ elsif name.respond_to?(:sexp_type) && name.sexp_type == :colon2
34
+ raise ModuleShorthandError
35
+ else
36
+ raise ProcessingError, "Unexpected class expression: #{name}"
37
+ end
38
+ end
39
+
40
+ def block?
41
+ !block.empty?
42
+ end
43
+
44
+ def block
45
+ @_block ||= @exp[3..-1] || []
46
+ end
47
+
48
+ def draper_test_case?
49
+ lineage?(parent, %i[Draper TestCase])
50
+ end
51
+
52
+ # Returns the name of the class. Examples:
53
+ #
54
+ # - Banana #=> :Banana
55
+ # - Fruit::Banana #=> s(:colon2, s(:const, :Fruit), :Banana)
56
+ #
57
+ # Note that the latter (module shorthand) is not supported
58
+ # by MinitestToRspec. See `#assert_valid_name`.
59
+ #
60
+ def name
61
+ @exp[1]
62
+ end
63
+
64
+ # Returns the "inheritance". Examples:
65
+ #
66
+ # - Inherit nothing #=> nil
67
+ # - Inherit Foo #=> s(:const, :Foo)
68
+ # - Inherit Bar::Foo #=> s(:colon2, s(:const, :Bar), :Foo)
69
+ #
70
+ def parent
71
+ @_parent ||= @exp[2]
72
+ end
73
+
74
+ # Returns true if `@exp` inherits from, e.g. ActiveSupport::TestCase.
75
+ # TODO: Other test case parent classes.
76
+ def test_case?
77
+ return false unless sexp_type?(:colon2, parent)
78
+ active_support_test_case? ||
79
+ action_controller_test_case? ||
80
+ action_mailer_test_case? ||
81
+ draper_test_case?
82
+ end
83
+
84
+ private
85
+
86
+ def ancestor_name(exp, index)
87
+ assert_sexp_type(:colon2, exp)
88
+ ancestor = exp[index + 1]
89
+ sexp_type?(:const, ancestor) ? ancestor[1] : ancestor
90
+ end
91
+
92
+ def lineage?(exp, names)
93
+ assert_sexp_type(:colon2, exp)
94
+ exp.length == names.length + 1 &&
95
+ names.each_with_index.all? { |name, ix|
96
+ name.to_sym == ancestor_name(exp, ix).to_sym
97
+ }
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end