minitest_to_rspec 0.2.1 → 0.3.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 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