brutal 0.3.0 → 0.4.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
  SHA256:
3
- metadata.gz: 8e7af479b185bf19e8cb7050360c79d216af2916668e76efb0d7c550e553af4b
4
- data.tar.gz: e917683e2edd247429cb9776444e6a97c10b9930265459a10ac8a3b4dbcf2cf6
3
+ metadata.gz: 4b21dc72c3687aa3893272f404e01d0329a528a61caa2b6f5ec251b5de66a3a4
4
+ data.tar.gz: 9aeb0ad4c455bb747700dc3af6bdf8957376e100af6e7b11bc6b377218e12426
5
5
  SHA512:
6
- metadata.gz: ad95d20234be22ed17de738afa0f1f1e0a5518cbf967fe87f9f1932f571e13d683a454354dd792f07d55010033dfd257b888422a880a4bd6c0f04ed19cf284ed
7
- data.tar.gz: c4e82e9a5036e134e83f86c313277573926fe0773ef3e2e43145d30fb725ba6a7a196f881f090f083589ac447889b7aa10d1d7e450ec550f468792991bffb824
6
+ metadata.gz: 7a818e0951d2993387caf80e699a989ffecca901f43ebf00b430b1de2ce330eb8da486c75800fd936a32b6f9b3286703d5ce4e85995b1a652f945ee9261162d3
7
+ data.tar.gz: afeedf7b04fc5be914e400a2b1a2149b0f82fb45f069654f2cc0bcf72e64cc84fc1c906b52c780d5199c2897059e1fc8e6125c6667e32c8a26fd656ae645a0c8
data/README.md CHANGED
@@ -1,22 +1,77 @@
1
- # Brutal 👹
2
-
3
- > I don't like testing because it's redundant. If we are smart enough, we can avoid it. <br/>
4
- > -- Matz
1
+ # Brutal 💎🔨
5
2
 
6
3
  [![Build Status](https://api.travis-ci.org/fixrb/brutal.svg?branch=master)][travis]
7
4
  [![Gem Version](https://badge.fury.io/rb/brutal.svg)][gem]
8
5
  [![Inline docs](https://inch-ci.org/github/fixrb/brutal.svg?branch=master)][inchpages]
9
6
  [![Documentation](http://img.shields.io/:yard-docs-38c800.svg)][rubydoc]
10
7
 
11
- __Brutal__ is a _code-first_ approach that automates the writing of unit tests.
8
+ > A _code-first_ approach to automate the writing of unit tests.
12
9
 
13
- By being able to generate test cases from the code itself, developers can focus on their creation, save time and energy, for more happiness.
10
+ ## Intro
14
11
 
15
- <p>
16
- <img
17
- src="https://github.com/fixrb/brutal/raw/master/img/Ferdinand_Hodler_-_Woodcutter_-_Google_Art_Project.jpg"
18
- alt="A lumberjack brutally cutting a tree" />
19
- </p>
12
+ [![I Hate Tests](https://github.com/fixrb/brutal/raw/master/img/rubyhack-2019-ruby3-what-s-missing-by-yukihiro-matsumoto.jpg)](https://www.youtube.com/embed/cmOt9HhszCI?start=1732&end=1736 "I don't like tests. It's not DRY.")
13
+
14
+ > I don't like tests. It's not DRY.<br/>
15
+ > -- [Matz](https://github.com/matz)
16
+
17
+ ## Purpose
18
+
19
+ Take a break and let __Brutal__ shape for you the actual behavior of your code against as many combinations of challenges as needed.
20
+
21
+ Without giving the power to test everything, it makes it easy to generate in no time a set of tests for all relevant contexts.
22
+
23
+ By delegating to __Brutal__ the repetitive and redundant task of writing tests, you'll be able to focus on your core business: writing code.
24
+
25
+ ## Warning
26
+
27
+ __Brutal__ does not prevent from bugs.
28
+ As a picture of the behavior of the code, its generated tests would be wrong if the code is wrong.
29
+
30
+ This is why it is important to carefully read the generated test suite, to ensure that it describes the behavior of the code as it is supposed to behave.
31
+
32
+ However, when the `brutal` command is executed successfully,
33
+ we can consider that both __Brutal__'s configuration file (`.brutal.yml`) and evaluated code as syntactically correct.
34
+
35
+ In the context of a versioned project, to avoid regressions,
36
+ the integrity of the behavior of the code can easily be checked by re-generating a picture to be compared with the previous one.
37
+ Here is an example with [The Greeter class](https://github.com/fixrb/brutal/raw/master/examples/the_greeter_class/) code:
38
+
39
+ ```sh
40
+ git diff
41
+ ```
42
+
43
+ The code:
44
+
45
+ ```diff
46
+ # The Greeter class
47
+ class Greeter
48
+ def initialize(name)
49
+ - @name = name
50
+ + @name = name.capitalize
51
+ end
52
+
53
+ def salute
54
+ "Hello #{@name}!"
55
+ end
56
+ end
57
+ ```
58
+
59
+ The generated test of the code:
60
+
61
+ ```diff
62
+ require './greeter'
63
+
64
+ # ------------------------------------------------------------------------------
65
+
66
+ front_object = Greeter
67
+
68
+ # ------------------------------------------------------------------------------
69
+
70
+ actual = front_object.new('world')
71
+
72
+ - raise unless actual.salute == "Hello world!"
73
+ + raise unless actual.salute == "Hello World!"
74
+ ```
20
75
 
21
76
  ## Installation
22
77
 
@@ -40,7 +95,8 @@ Just type `brutal` in a Ruby project's folder and watch the magic happen.
40
95
 
41
96
  ## Usage
42
97
 
43
- The Brutal YAML file handles 4 keys:
98
+ __Brutal__'s configuration file is `.brutal.yml`, which acts like a meta-spec.
99
+ This YAML file can contains the following keys:
44
100
 
45
101
  * `header` (optional): Some code to execute before the test suite.
46
102
  * `front_object` (required): The front object of the test suite.
@@ -48,9 +104,15 @@ The Brutal YAML file handles 4 keys:
48
104
  * `variables` (required): A hash to generate the subject of each context.
49
105
  * `actual_values` (required): A list of tests to challenge the subject.
50
106
 
107
+ ### Optional parameters
108
+
109
+ It would also be possible to ask for an RSpec template by passing "`rspec`" argument:
110
+
111
+ > brutal rspec
112
+
51
113
  ## Example
52
114
 
53
- Given this `.brutal.yml` config file:
115
+ Given this config file:
54
116
 
55
117
  ```yaml
56
118
  ---
@@ -70,7 +132,7 @@ actual_values:
70
132
  - "%{subject}.length"
71
133
  ```
72
134
 
73
- The `brutal` command would save this Plain Old Ruby in to a `test.rb` file:
135
+ The `brutal` command would generate and write in to a `test.rb` file the following "Plain Old Ruby":
74
136
 
75
137
  ```ruby
76
138
  front_object = "Hello "
@@ -88,7 +150,29 @@ raise unless actual.to_s == "Hello Bob"
88
150
  raise unless actual.length == 9
89
151
  ```
90
152
 
91
- [More examples](examples/) are available.
153
+ And the `brutal rspec` command would generate and write in to a `test_spec.rb` file the following spec:
154
+
155
+ ```ruby
156
+ RSpec.describe do
157
+ let(:front_object) { "Hello " }
158
+
159
+ context do
160
+ let(:actual) { front_object + 'Alice' }
161
+
162
+ it { expect(actual.to_s).to eq("Hello Alice") }
163
+ it { expect(actual.length).to eq(11) }
164
+ end
165
+
166
+ context do
167
+ let(:actual) { front_object + 'Bob' }
168
+
169
+ it { expect(actual.to_s).to eq("Hello Bob") }
170
+ it { expect(actual.length).to eq(9) }
171
+ end
172
+ end
173
+ ```
174
+
175
+ More examples are available [here](https://github.com/fixrb/brutal/raw/master/examples/).
92
176
 
93
177
  ## Rake integration example
94
178
 
@@ -115,23 +199,10 @@ end
115
199
 
116
200
  __Brutal__ follows [Semantic Versioning 2.0](https://semver.org/).
117
201
 
118
- ## Contributing
119
-
120
- Bug reports and pull requests are welcome on GitHub at https://github.com/fixrb/brutal. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/fixrb/brutal/blob/master/CODE_OF_CONDUCT.md).
121
-
122
202
  ## License
123
203
 
124
204
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
125
205
 
126
- ## Code of Conduct
127
-
128
- Everyone interacting in the GreatGuardian project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/fixrb/brutal/blob/master/CODE_OF_CONDUCT.md).
129
-
130
- [gem]: https://rubygems.org/gems/brutal
131
- [travis]: https://travis-ci.org/fixrb/brutal
132
- [inchpages]: https://inch-ci.org/github/fixrb/brutal
133
- [rubydoc]: https://rubydoc.info/gems/brutal/frames
134
-
135
206
  ***
136
207
 
137
208
  <p>
@@ -140,3 +211,8 @@ Everyone interacting in the GreatGuardian project's codebases, issue trackers, c
140
211
  src="https://github.com/fixrb/brutal/raw/master/img/sashite.png"
141
212
  alt="Sashite" /></a>
142
213
  </p>
214
+
215
+ [gem]: https://rubygems.org/gems/brutal
216
+ [travis]: https://travis-ci.org/fixrb/brutal
217
+ [inchpages]: https://inch-ci.org/github/fixrb/brutal
218
+ [rubydoc]: https://rubydoc.info/gems/brutal/frames
data/bin/brutal CHANGED
@@ -24,20 +24,22 @@ front_object = front_object.chomp if front_object.is_a?(::String)
24
24
 
25
25
  require_relative ::File.join('..', 'lib', 'brutal')
26
26
 
27
- scaffold = case ARGV.fetch(0, nil)
28
- when nil
29
- ::Brutal::ScaffoldGenerator::Por
30
- else
31
- abort "#{ARGV[0].inspect} not (yet) supported!"
32
- end
27
+ scaffold, file_name = case ARGV.fetch(0, nil)
28
+ when nil
29
+ [::Brutal::ScaffoldGenerator::Por, 'test.rb']
30
+ when 'rspec'
31
+ [::Brutal::ScaffoldGenerator::RSpec, 'test_spec.rb']
32
+ else
33
+ abort "#{ARGV[0].inspect} not (yet) supported!"
34
+ end
33
35
 
34
36
  eval(header) # rubocop:disable Security/Eval
35
37
 
36
38
  doc = [
37
39
  header,
38
40
  scaffold.new(front_object, subject, *actual_values, **variables).to_s
39
- ].reject(&:empty?).join("\n")
41
+ ].reject(&:empty?).join("\n\n")
40
42
 
41
- file = ::File.open('test.rb', 'w')
43
+ file = ::File.open(file_name, 'w')
42
44
  file.write(doc)
43
45
  file.close
@@ -20,7 +20,7 @@ module Brutal
20
20
 
21
21
  test_params = Array(values_arr[0]).product(*Array(values_arr[1..-1]))
22
22
 
23
- blank_line +
23
+ blank_line.gsub(/\A\n/, '') +
24
24
  "front_object = #{front_object_str}\n" +
25
25
  blank_line +
26
26
  test_params.map do |values|
@@ -30,7 +30,7 @@ module Brutal
30
30
 
31
31
  actual_str = format(inspect(subject), **attributes)
32
32
 
33
- string = "actual = #{actual_str}\n"
33
+ string = "actual = #{actual_str}\n\n"
34
34
  actual = eval(actual_str) # rubocop:disable Security/Eval, Lint/UselessAssignment
35
35
 
36
36
  actual_values.each do |actual_value|
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'base'
4
+
5
+ module Brutal
6
+ module ScaffoldGenerator
7
+ # Plain Old Ruby.
8
+ #
9
+ # @api private
10
+ #
11
+ class RSpec < Base
12
+ # Return a string representation
13
+ #
14
+ # @return [String]
15
+ #
16
+ # @api public
17
+ def to_s
18
+ names = variables.keys.sort
19
+ values_arr = names.map { |name| variables.fetch(name) }
20
+
21
+ test_params = Array(values_arr[0]).product(*Array(values_arr[1..-1]))
22
+
23
+ "RSpec.describe do\n" \
24
+ " let(:front_object) { #{front_object_str} }\n" \
25
+ "\n" +
26
+ test_params.map do |values|
27
+ string = " context do\n"
28
+
29
+ attributes = names.each_with_index.inject(front_object: 'front_object') do |h, (name, i)|
30
+ h.merge(name.to_sym => inspect(values.fetch(i)))
31
+ end
32
+
33
+ actual_str = format(inspect(subject), **attributes)
34
+
35
+ string += " let(:actual) { #{actual_str} }\n\n"
36
+ actual = eval(actual_str) # rubocop:disable Security/Eval, Lint/UselessAssignment
37
+
38
+ actual_values.each do |actual_value|
39
+ result_str = format(actual_value, subject: 'actual')
40
+ string += " it { expect(#{result_str}).to eq(#{eval(result_str).inspect}) }\n" # rubocop:disable Security/Eval
41
+ end
42
+
43
+ string += " end\n"
44
+
45
+ string
46
+ end.join(blank_line) +
47
+ "end\n"
48
+ end
49
+
50
+ def blank_line
51
+ "\n"
52
+ end
53
+ end
54
+ end
55
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: brutal
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Cyril Kato
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-24 00:00:00.000000000 Z
11
+ date: 2019-12-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.0'
19
+ version: '2.1'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.0'
26
+ version: '2.1'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -94,7 +94,7 @@ dependencies:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0.9'
97
- description: Scaffolds test cases from the code itself.
97
+ description: A code-first approach to automate the writing of unit tests.
98
98
  email: contact@cyril.email
99
99
  executables:
100
100
  - brutal
@@ -107,6 +107,7 @@ files:
107
107
  - lib/brutal.rb
108
108
  - lib/brutal/scaffold_generator/base.rb
109
109
  - lib/brutal/scaffold_generator/por.rb
110
+ - lib/brutal/scaffold_generator/rspec.rb
110
111
  homepage: https://github.com/fixrb/brutal
111
112
  licenses:
112
113
  - MIT
@@ -129,5 +130,5 @@ requirements: []
129
130
  rubygems_version: 3.1.2
130
131
  signing_key:
131
132
  specification_version: 4
132
- summary: Scaffolds test cases from the code itself.
133
+ summary: A code-first approach to automate the writing of unit tests.
133
134
  test_files: []