minitest_to_rspec 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -3
- data/README.md +42 -14
- data/bin/minitest_to_rspec +23 -5
- data/doc/code_style.md +32 -0
- data/lib/minitest_to_rspec/converter.rb +13 -4
- data/lib/minitest_to_rspec/errors.rb +14 -1
- data/lib/minitest_to_rspec/exp/base.rb +12 -0
- data/lib/minitest_to_rspec/exp/call.rb +30 -8
- data/lib/minitest_to_rspec/exp/calls/returns.rb +47 -0
- data/lib/minitest_to_rspec/exp/iter.rb +40 -5
- data/lib/minitest_to_rspec/exp/klass.rb +53 -0
- data/lib/minitest_to_rspec/processor.rb +7 -6
- data/lib/minitest_to_rspec/sexp_assertions.rb +15 -0
- data/lib/minitest_to_rspec/subprocessors/base.rb +58 -51
- data/lib/minitest_to_rspec/subprocessors/call.rb +119 -75
- data/lib/minitest_to_rspec/subprocessors/iter.rb +108 -81
- data/lib/minitest_to_rspec/subprocessors/klass.rb +123 -0
- data/lib/minitest_to_rspec/version.rb +1 -1
- data/minitest_to_rspec.gemspec +2 -1
- metadata +11 -6
- data/lib/minitest_to_rspec/subprocessors/class.rb +0 -105
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dfbca8efedaf7c52597ad002776c9a91913ef953
|
4
|
+
data.tar.gz: f0338aab60ec0ed5c47a73b4da8efe10d219a7b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c19ee604832c47a8a2b29bf04f80a339e0542fd34d282d2fca7faa571cfdce424d556bc66c607413e9a8b48024b7714561d30b89a4b5f4cc0a4d149615f3a6e
|
7
|
+
data.tar.gz: c84d8763c6788a1e7f781256d7fdd84f673fe995fbd08aad97d26c51f770cce2bd607430c09ade0e9243b01cbe7ff2b3c85b708b3e1d28aa13b4c7a4f35aa93e
|
data/CHANGELOG.md
CHANGED
@@ -4,10 +4,27 @@ Change Log
|
|
4
4
|
This project follows [semver 2.0.0][1] and the recommendations
|
5
5
|
of [keepachangelog.com][2].
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
0.3.0
|
8
|
+
-----
|
9
|
+
|
10
|
+
### Added
|
11
|
+
- Converts
|
12
|
+
- `setup` and `teardown` to `before` and `after`
|
13
|
+
- `assert_raise`, `assert_raises`
|
14
|
+
- CLI option: `--rails`
|
15
|
+
- Prints `rails_helper` instead of `spec_helper`
|
16
|
+
- Adds `:type` metadata, eg. `:type => :controller`
|
17
|
+
- So far, only supports `:model` and `:controller`
|
18
|
+
- Experimental
|
19
|
+
- Limited conversion of mocha to rspec-mocks
|
20
|
+
- returns
|
21
|
+
- stub
|
22
|
+
- stub_everything
|
23
|
+
- stubs
|
24
|
+
- Ruby 1.9 hash syntax (See [ruby2ruby PR 37][3])
|
9
25
|
|
10
|
-
|
26
|
+
### Fixed
|
27
|
+
- Improved error message for class definition using module shorthand
|
11
28
|
|
12
29
|
0.2.1
|
13
30
|
-----
|
@@ -28,3 +45,4 @@ Initial release. 11 assertions are supported.
|
|
28
45
|
|
29
46
|
[1]: http://semver.org/spec/v2.0.0.html
|
30
47
|
[2]: http://keepachangelog.com/
|
48
|
+
[3]: https://github.com/seattlerb/ruby2ruby/pull/37
|
data/README.md
CHANGED
@@ -4,6 +4,9 @@ Converts [minitest][8] files to [rspec][9].
|
|
4
4
|
|
5
5
|
[![Build Status][1]][2] [![Code Climate][3]][4] [![Test Coverage][7]][4]
|
6
6
|
|
7
|
+
Uses [ruby_parser][14], [sexp_processor][15], and [ruby2ruby][16],
|
8
|
+
in that order. Thank you, [Ryan Davis][17]!
|
9
|
+
|
7
10
|
Example
|
8
11
|
-------
|
9
12
|
|
@@ -11,6 +14,8 @@ Input:
|
|
11
14
|
|
12
15
|
```ruby
|
13
16
|
require 'test_helper'
|
17
|
+
|
18
|
+
# This comment will be discarded!
|
14
19
|
class BananaTest < ActiveSupport::TestCase
|
15
20
|
test "is delicious" do
|
16
21
|
assert Banana.new.delicious?
|
@@ -27,6 +32,8 @@ RSpec.describe(Banana) do
|
|
27
32
|
end
|
28
33
|
```
|
29
34
|
|
35
|
+
[RubyParser][14] discards all comments.
|
36
|
+
|
30
37
|
The code style is whatever [ruby2ruby][6] feels like printing,
|
31
38
|
and is not configurable. The goal is not style, but to get to
|
32
39
|
rspec quickly.
|
@@ -38,7 +45,7 @@ Usage
|
|
38
45
|
|
39
46
|
```bash
|
40
47
|
gem install minitest_to_rspec
|
41
|
-
minitest_to_rspec source_file target_file
|
48
|
+
minitest_to_rspec --rails source_file target_file
|
42
49
|
```
|
43
50
|
|
44
51
|
### Ruby
|
@@ -56,19 +63,30 @@ Selected assertions from minitest, Test::Unit, and ActiveSupport.
|
|
56
63
|
See [doc/supported_assertions.md][5] for rationale. Contributions
|
57
64
|
are welcome.
|
58
65
|
|
59
|
-
Assertion | Arity
|
60
|
-
--------------------------- | -----
|
61
|
-
assert |
|
62
|
-
assert_difference | 1
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
[
|
69
|
-
assert_raises
|
70
|
-
refute |
|
71
|
-
refute_equal |
|
66
|
+
Assertion | Arity | Source
|
67
|
+
--------------------------- | ----- | ------
|
68
|
+
assert | |
|
69
|
+
assert_difference | 1,2 |
|
70
|
+
assert_equal | |
|
71
|
+
assert_match | |
|
72
|
+
assert_nil | |
|
73
|
+
[assert_no_difference][12] | | ActiveSupport
|
74
|
+
[assert_nothing_raised][10] | | Test::Unit
|
75
|
+
[assert_raise][11] | 0..2 | Test::Unit
|
76
|
+
[assert_raises][13] | 0..2 | Minitest
|
77
|
+
refute | |
|
78
|
+
refute_equal | |
|
79
|
+
|
80
|
+
Supported Mocha
|
81
|
+
---------------
|
82
|
+
|
83
|
+
Mocha | Arity | Block | Notes
|
84
|
+
--------------------- | ----- | ----- | -------
|
85
|
+
[stub][19] | 0,1,2 | no |
|
86
|
+
[stub_everything][18] | 0,1,2 | no | Uses `as_null_object`, not the same.
|
87
|
+
[stubs][20] | 1 | n/a |
|
88
|
+
|
89
|
+
Notably not yet supported: `expects`, `any_instance`
|
72
90
|
|
73
91
|
[1]: https://travis-ci.org/jaredbeck/minitest_to_rspec.svg
|
74
92
|
[2]: https://travis-ci.org/jaredbeck/minitest_to_rspec
|
@@ -80,3 +98,13 @@ refute_equal |
|
|
80
98
|
[8]: https://github.com/jaredbeck/minitest_to_rspec/blob/master/doc/minitest.md
|
81
99
|
[9]: https://github.com/jaredbeck/minitest_to_rspec/blob/master/doc/rspec.md
|
82
100
|
[10]: http://www.rubydoc.info/gems/test-unit/3.0.9/Test/Unit/Assertions#assert_nothing_raised-instance_method
|
101
|
+
[11]: http://ruby-doc.org/stdlib-2.1.0/libdoc/test/unit/rdoc/Test/Unit/Assertions.html#method-i-assert_raise
|
102
|
+
[12]: http://api.rubyonrails.org/classes/ActiveSupport/Testing/Assertions.html#method-i-assert_no_difference
|
103
|
+
[13]: http://www.rubydoc.info/gems/minitest/5.5.1/Minitest/Assertions#assert_raises-instance_method
|
104
|
+
[14]: https://github.com/seattlerb/ruby_parser
|
105
|
+
[15]: https://github.com/seattlerb/sexp_processor
|
106
|
+
[16]: https://github.com/seattlerb/ruby2ruby
|
107
|
+
[17]: https://github.com/zenspider
|
108
|
+
[18]: http://www.rubydoc.info/github/floehopper/mocha/Mocha/API:stub_everything
|
109
|
+
[19]: http://www.rubydoc.info/github/floehopper/mocha/Mocha/API#stub-instance_method
|
110
|
+
[20]: http://www.rubydoc.info/github/floehopper/mocha/Mocha/ObjectMethods#stubs-instance_method
|
data/bin/minitest_to_rspec
CHANGED
@@ -7,17 +7,23 @@ module MinitestToRspec
|
|
7
7
|
E_USAGE = 1
|
8
8
|
E_FILE_NOT_FOUND = 2
|
9
9
|
E_FILE_ALREADY_EXISTS = 3
|
10
|
+
E_CONVERT_FAIL = 4
|
10
11
|
|
11
12
|
def initialize(args)
|
12
13
|
check_usage(args)
|
13
|
-
@
|
14
|
-
@
|
14
|
+
@target = args.pop
|
15
|
+
@source = args.pop
|
16
|
+
@rails = false
|
17
|
+
parse_options(args)
|
15
18
|
end
|
16
19
|
|
17
20
|
def run
|
18
21
|
assert_file_exists(@source)
|
19
22
|
assert_file_does_not_exist(@target)
|
20
23
|
write_target(converter.convert(read_source))
|
24
|
+
rescue Error => e
|
25
|
+
$stderr.puts "Failed to convert: #{e}"
|
26
|
+
exit E_CONVERT_FAIL
|
21
27
|
end
|
22
28
|
|
23
29
|
private
|
@@ -37,18 +43,30 @@ module MinitestToRspec
|
|
37
43
|
end
|
38
44
|
|
39
45
|
def check_usage(args)
|
40
|
-
unless args.length
|
46
|
+
unless (2..3).cover?(args.length)
|
41
47
|
print_usage
|
42
48
|
exit(E_USAGE)
|
43
49
|
end
|
44
50
|
end
|
45
51
|
|
46
52
|
def converter
|
47
|
-
Converter.new
|
53
|
+
Converter.new(rails: @rails)
|
54
|
+
end
|
55
|
+
|
56
|
+
def parse_options(args)
|
57
|
+
raise ArgumentError unless args.length <= 1
|
58
|
+
args.each do |arg|
|
59
|
+
case arg
|
60
|
+
when "--rails"
|
61
|
+
@rails = true
|
62
|
+
else
|
63
|
+
raise ArgumentError, "Unexpected option: #{arg}"
|
64
|
+
end
|
65
|
+
end
|
48
66
|
end
|
49
67
|
|
50
68
|
def print_usage
|
51
|
-
$stderr.puts "Usage: minitest_to_rspec source_file target_file"
|
69
|
+
$stderr.puts "Usage: minitest_to_rspec --rails source_file target_file"
|
52
70
|
end
|
53
71
|
|
54
72
|
def read_source
|
data/doc/code_style.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
Code Style
|
2
|
+
==========
|
3
|
+
|
4
|
+
The code style is whatever [ruby2ruby][1] feels like printing,
|
5
|
+
and is not configurable. The goal is not style, but to get to
|
6
|
+
rspec quickly.
|
7
|
+
|
8
|
+
To clean up the style a bit afterwards, here are some tips.
|
9
|
+
|
10
|
+
1. Remove parenthesis around `describe` and `it` arguments.
|
11
|
+
|
12
|
+
```
|
13
|
+
Find: (context|describe|it)\((['"])(.*)['"]\) do
|
14
|
+
Replace: $1 $2$3$2 do
|
15
|
+
```
|
16
|
+
|
17
|
+
1. Convert `be_truthy` to [predicate matchers][2].
|
18
|
+
|
19
|
+
```
|
20
|
+
Find: expect\((.*).valid\?\)\.to\(be_truthy\)
|
21
|
+
Replace: expect($1).to be_valid
|
22
|
+
```
|
23
|
+
|
24
|
+
And the negated variant:
|
25
|
+
|
26
|
+
```
|
27
|
+
Find: expect\(\(not (.*).valid\?\)\)\.to\(be_truthy\)
|
28
|
+
Replace: expect($1).to be_invalid
|
29
|
+
```
|
30
|
+
|
31
|
+
[1]: https://github.com/seattlerb/ruby2ruby
|
32
|
+
[2]: https://relishapp.com/rspec/rspec-expectations/v/3-2/docs/built-in-matchers/predicate-matchers
|
@@ -1,12 +1,13 @@
|
|
1
1
|
require "ruby_parser"
|
2
2
|
require "ruby2ruby"
|
3
3
|
require_relative "processor"
|
4
|
+
require_relative "errors"
|
4
5
|
|
5
6
|
module MinitestToRspec
|
6
7
|
class Converter
|
7
|
-
def initialize
|
8
|
-
@
|
9
|
-
@
|
8
|
+
def initialize(options)
|
9
|
+
@options = options
|
10
|
+
@processor = Processor.new(@options[:rails])
|
10
11
|
end
|
11
12
|
|
12
13
|
def convert(input)
|
@@ -51,7 +52,15 @@ module MinitestToRspec
|
|
51
52
|
# Given an AST representing an rspec file, returns a string
|
52
53
|
# of ruby code.
|
53
54
|
def render(exp)
|
54
|
-
|
55
|
+
ruby2ruby.process(exp)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Try to specify ruby 1.9 hash_syntax if ruby2ruby supports it.
|
59
|
+
# https://github.com/seattlerb/ruby2ruby/pull/37
|
60
|
+
def ruby2ruby
|
61
|
+
Ruby2Ruby.new(hash_syntax: :ruby19)
|
62
|
+
rescue ArgumentError
|
63
|
+
Ruby2Ruby.new
|
55
64
|
end
|
56
65
|
end
|
57
66
|
end
|
@@ -1,3 +1,16 @@
|
|
1
1
|
module MinitestToRspec
|
2
|
-
class
|
2
|
+
class Error < StandardError; end
|
3
|
+
class ProcessingError < Error; end
|
4
|
+
class NotImplemented < Error; end
|
5
|
+
|
6
|
+
class ModuleShorthandError < NotImplemented
|
7
|
+
DEFAULT_MESSAGE = <<-EOS
|
8
|
+
Unsupported class definition: Module shorthand (A::B::C) is not supported.
|
9
|
+
Please convert your class definition to use nested modules and try again.
|
10
|
+
EOS
|
11
|
+
|
12
|
+
def initialize(msg = nil)
|
13
|
+
super(msg || DEFAULT_MESSAGE)
|
14
|
+
end
|
15
|
+
end
|
3
16
|
end
|
@@ -1,14 +1,14 @@
|
|
1
|
+
require_relative "base"
|
2
|
+
|
1
3
|
module MinitestToRspec
|
2
4
|
module Exp
|
3
5
|
|
4
6
|
# Data object. Represents a `:call` s-expression.
|
5
|
-
class Call
|
7
|
+
class Call < Base
|
6
8
|
attr_reader :original
|
7
9
|
|
8
10
|
def initialize(exp)
|
9
|
-
|
10
|
-
raise ArgumentError, "Expected call, got #{exp.sexp_type}"
|
11
|
-
end
|
11
|
+
assert_sexp_type(:call, exp)
|
12
12
|
@exp = exp.dup
|
13
13
|
@original = exp.dup
|
14
14
|
end
|
@@ -26,13 +26,21 @@ module MinitestToRspec
|
|
26
26
|
exp.sexp_type == :call && new(exp).assert_nothing_raised?
|
27
27
|
end
|
28
28
|
|
29
|
+
def assert_raise?(exp)
|
30
|
+
exp.sexp_type == :call && new(exp).assert_raise?
|
31
|
+
end
|
32
|
+
|
29
33
|
def assert_raises?(exp)
|
30
34
|
exp.sexp_type == :call && new(exp).assert_raises?
|
31
35
|
end
|
36
|
+
|
37
|
+
def method_name?(exp, name)
|
38
|
+
exp.sexp_type == :call && new(exp).method_name == name
|
39
|
+
end
|
32
40
|
end
|
33
41
|
|
34
42
|
def arguments
|
35
|
-
@exp[3..-1]
|
43
|
+
@exp[3..-1] || []
|
36
44
|
end
|
37
45
|
|
38
46
|
def argument_types
|
@@ -54,10 +62,12 @@ module MinitestToRspec
|
|
54
62
|
method_name == :assert_nothing_raised && arguments.empty?
|
55
63
|
end
|
56
64
|
|
65
|
+
def assert_raise?
|
66
|
+
method_name == :assert_raise && raise_error_args?
|
67
|
+
end
|
68
|
+
|
57
69
|
def assert_raises?
|
58
|
-
method_name == :assert_raises &&
|
59
|
-
arguments.length == 1 &&
|
60
|
-
arguments[0].sexp_type == :const
|
70
|
+
method_name == :assert_raises && raise_error_args?
|
61
71
|
end
|
62
72
|
|
63
73
|
def method_name
|
@@ -68,6 +78,18 @@ module MinitestToRspec
|
|
68
78
|
arguments.length == 1 && string?(arguments[0])
|
69
79
|
end
|
70
80
|
|
81
|
+
# Returns true if arguments can be processed into RSpec's `raise_error`
|
82
|
+
# matcher. When the last argument is a string, it represents the
|
83
|
+
# assertion failure message, which will be discarded later.
|
84
|
+
def raise_error_args?
|
85
|
+
arg_types = arguments.map(&:sexp_type)
|
86
|
+
[[], [:str], [:const], [:const, :str]].include?(arg_types)
|
87
|
+
end
|
88
|
+
|
89
|
+
def receiver
|
90
|
+
@exp[1]
|
91
|
+
end
|
92
|
+
|
71
93
|
def require_test_helper?
|
72
94
|
method_name == :require &&
|
73
95
|
one_string_argument? &&
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module MinitestToRspec
|
2
|
+
module Exp
|
3
|
+
module Calls
|
4
|
+
|
5
|
+
# Represents a call to `returns`, the stubbing method
|
6
|
+
# from `mocha`.
|
7
|
+
class Returns < Call
|
8
|
+
def initialize(exp)
|
9
|
+
@exp = exp
|
10
|
+
end
|
11
|
+
|
12
|
+
# The message recipient
|
13
|
+
def msg_recipient
|
14
|
+
stubs_call.receiver
|
15
|
+
end
|
16
|
+
|
17
|
+
def known_variant?
|
18
|
+
receiver_is_call_to_stubs? &&
|
19
|
+
!values.empty? &&
|
20
|
+
message.sexp_type == :lit
|
21
|
+
end
|
22
|
+
|
23
|
+
def message
|
24
|
+
stubs_call.arguments[0]
|
25
|
+
end
|
26
|
+
|
27
|
+
# The return values
|
28
|
+
def values
|
29
|
+
arguments
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def receiver_is_call_to_stubs?
|
35
|
+
r = receiver
|
36
|
+
!r.nil? &&
|
37
|
+
r.sexp_type == :call &&
|
38
|
+
Call.new(r).method_name == :stubs
|
39
|
+
end
|
40
|
+
|
41
|
+
def stubs_call
|
42
|
+
Call.new(receiver)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -1,13 +1,12 @@
|
|
1
|
+
require_relative "base"
|
2
|
+
|
1
3
|
module MinitestToRspec
|
2
4
|
module Exp
|
3
5
|
|
4
6
|
# Data object. Represents an `:iter` s-expression.
|
5
|
-
class Iter
|
6
|
-
|
7
|
+
class Iter < Base
|
7
8
|
def initialize(exp)
|
8
|
-
|
9
|
-
raise ArgumentError, "Expected iter, got #{exp.sexp_type}"
|
10
|
-
end
|
9
|
+
assert_sexp_type(:iter, exp)
|
11
10
|
@exp = exp.dup
|
12
11
|
end
|
13
12
|
|
@@ -27,14 +26,50 @@ module MinitestToRspec
|
|
27
26
|
!empty? && Exp::Call.assert_nothing_raised?(@exp[1])
|
28
27
|
end
|
29
28
|
|
29
|
+
def assert_raise?
|
30
|
+
!empty? && Exp::Call.assert_raise?(@exp[1])
|
31
|
+
end
|
32
|
+
|
30
33
|
def assert_raises?
|
31
34
|
!empty? && Exp::Call.assert_raises?(@exp[1])
|
32
35
|
end
|
33
36
|
|
37
|
+
def block
|
38
|
+
@exp[3]
|
39
|
+
end
|
40
|
+
|
41
|
+
def call
|
42
|
+
@exp[1]
|
43
|
+
end
|
44
|
+
|
45
|
+
# Not to be confused with block arguments.
|
46
|
+
def call_arguments
|
47
|
+
call_obj.arguments
|
48
|
+
end
|
49
|
+
|
50
|
+
def call_obj
|
51
|
+
Exp::Call.new(call)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Enumerates children, skipping the base `call` and
|
55
|
+
# starting with the block arguments, then each `:call` in
|
56
|
+
# the block.
|
57
|
+
def each
|
58
|
+
@exp[2..-1].each do |e| yield(e) end
|
59
|
+
end
|
60
|
+
|
34
61
|
def empty?
|
35
62
|
@exp.length == 1 # just the sexp_type
|
36
63
|
end
|
37
64
|
|
65
|
+
def setup?
|
66
|
+
!empty? && Exp::Call.method_name?(@exp[1], :setup)
|
67
|
+
end
|
68
|
+
|
69
|
+
def teardown?
|
70
|
+
!empty? && Exp::Call.method_name?(@exp[1], :teardown)
|
71
|
+
end
|
72
|
+
|
38
73
|
def sexp
|
39
74
|
@exp
|
40
75
|
end
|