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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a26f82f0b35b670823cd1027ac1ac80246a6f8c0
4
- data.tar.gz: 87a546ab111b4ce7828d965e191adf172694c25f
3
+ metadata.gz: dfbca8efedaf7c52597ad002776c9a91913ef953
4
+ data.tar.gz: f0338aab60ec0ed5c47a73b4da8efe10d219a7b7
5
5
  SHA512:
6
- metadata.gz: 0d3cc07d13814998342715165ae6d440b3afc1ebbfcb7ae47c4a080b3ffe04064ba40e22f33549e3670f846a0782d6f3ea5e7e47e176af2e0fc87ec2ec0cd309
7
- data.tar.gz: b92b4a90f78b704aa546c8ac8a9ce99fff05206fe9e41cd46896e0347390aee43771c4efc53208464001e8d51f9bc9b6b8734b59de2d609b76d5efc624516a7e
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
- Road Map
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
- More assertions. Contributions welcome.
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
- assert_difference | 2
64
- assert_equal |
65
- assert_match |
66
- assert_nil |
67
- assert_no_difference |
68
- [assert_nothing_raised][10] |
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
@@ -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
- @source = args[0]
14
- @target = args[1]
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 == 2
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
- @processor = Processor.new
9
- @ruby2ruby = Ruby2Ruby.new
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
- @ruby2ruby.process(exp)
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 NotImplemented < StandardError; end
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
@@ -0,0 +1,12 @@
1
+ require_relative "../sexp_assertions"
2
+
3
+ module MinitestToRspec
4
+ module Exp
5
+
6
+ # Classes inheriting `Base` are simple data objects
7
+ # representing the S-expressions they are named after.
8
+ class Base
9
+ include SexpAssertions
10
+ end
11
+ end
12
+ 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
- unless exp.sexp_type == :call
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
- unless exp.sexp_type == :iter
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