brutal 0.1.0 → 0.4.1
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 +4 -4
- data/LICENSE.md +1 -1
- data/README.md +122 -58
- data/bin/brutal +24 -17
- data/lib/brutal.rb +4 -1
- data/lib/brutal/scaffold_generator/base.rb +30 -0
- data/lib/brutal/scaffold_generator/por.rb +58 -0
- data/lib/brutal/scaffold_generator/rspec.rb +55 -0
- metadata +33 -22
- data/bin/console +0 -7
- data/bin/setup +0 -7
- data/lib/brutal/framework/base.rb +0 -17
- data/lib/brutal/framework/poro.rb +0 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 491dc26f34135ff61ceb54bc64b4dc5793e8b2610d545b3025b8c7aaf53b3064
|
4
|
+
data.tar.gz: e7c379c45ce23f0886041ec8a4b6ab4c493a91e450230b64968e45a92214a62e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8791614f90a92630a28aa3fb8b6d2a9d1921404b1cc614302bfeb8a87970186c33b935d81db81b7c1d8751475a59d5f32c17ea80627d32755daece880b93ace4
|
7
|
+
data.tar.gz: 19cf4fcbe94766983442f0f47b2651b5b675d5ade1c9b306e4213421d21253035545a23f8e6c988a8967db182b4de59a4158a545278684b4104039729963574c
|
data/LICENSE.md
CHANGED
data/README.md
CHANGED
@@ -1,14 +1,37 @@
|
|
1
|
-
# Brutal
|
1
|
+
# Brutal 💎🔨
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-

|
6
|
-
|
7
|
-
[][travis]
|
3
|
+
[][workflow_rubocop]
|
4
|
+
[][travis]
|
8
5
|
[][gem]
|
9
|
-
[][inchpages]
|
10
7
|
[][rubydoc]
|
11
8
|
|
9
|
+
> A _code-first_ approach to automate the writing of unit tests.
|
10
|
+
|
11
|
+
## Why
|
12
|
+
|
13
|
+
[](https://www.youtube.com/embed/cmOt9HhszCI?start=1732&end=1736 "I don't like tests. It's not DRY.")
|
14
|
+
|
15
|
+
> I don't like tests. It's not DRY.<br/>
|
16
|
+
> -- [Matz](https://github.com/matz)
|
17
|
+
|
18
|
+
## Purpose
|
19
|
+
|
20
|
+
Let __Brutal__ shape for you the actual behavior of your code against as many combinations of challenges as needed.
|
21
|
+
|
22
|
+
Without giving the power to test everything, it makes it easy to generate in no time a set of tests for all relevant contexts.
|
23
|
+
|
24
|
+
By delegating to __Brutal__ this repetitive (and redundant) job of writing tests, you'll be able to focus on your core business: writing code.
|
25
|
+
|
26
|
+
## Warning
|
27
|
+
|
28
|
+
__Brutal__ does not prevent from bugs.
|
29
|
+
As a picture of the behavior of the code, generated tests would be wrong if the code is wrong.
|
30
|
+
|
31
|
+
This is why it is important to carefully read a generated test suite, to ensure that it describes the behavior of the code as it is expected to behave.
|
32
|
+
|
33
|
+
This is the cost to enter the _Brutal-Driven Development_ with confidence.
|
34
|
+
|
12
35
|
## Installation
|
13
36
|
|
14
37
|
Add this line to your application's Gemfile:
|
@@ -25,81 +48,123 @@ Or install it yourself as:
|
|
25
48
|
|
26
49
|
$ gem install brutal
|
27
50
|
|
28
|
-
##
|
51
|
+
## Quick Start
|
29
52
|
|
30
53
|
Just type `brutal` in a Ruby project's folder and watch the magic happen.
|
31
54
|
|
32
55
|
## Usage
|
33
56
|
|
34
|
-
|
57
|
+
__Brutal__'s configuration file is `.brutal.yml`, which acts like a meta-spec.
|
58
|
+
This YAML file can contains the following keys:
|
35
59
|
|
36
60
|
* `header` (optional): Some code to execute before the test suite.
|
37
|
-
* `
|
38
|
-
* `
|
39
|
-
* `
|
61
|
+
* `front_object` (required): The front object of the test suite.
|
62
|
+
* `subject` (required): The object of each context.
|
63
|
+
* `variables` (required): A hash to generate the subject of each context.
|
64
|
+
* `actual_values` (required): A list of tests to challenge the subject.
|
65
|
+
|
66
|
+
### Behavioral integrity
|
67
|
+
|
68
|
+
In versioned projects,
|
69
|
+
the integrity of the behavior of the code could easily be compared by executing `brutal` after changes.
|
70
|
+
|
71
|
+
Assuming a project is versioned with git,
|
72
|
+
if something goes wrong, the `git diff test.rb` command should instantly show changes between the behavior of the previous code and the behavior of the new one.
|
73
|
+
|
74
|
+
Example of regression from [The Greeter class](https://github.com/fixrb/brutal/raw/master/examples/the_greeter_class/):
|
75
|
+
|
76
|
+
```diff
|
77
|
+
require './greeter'
|
78
|
+
|
79
|
+
# ------------------------------------------------------------------------------
|
80
|
+
|
81
|
+
front_object = Greeter
|
82
|
+
|
83
|
+
# ------------------------------------------------------------------------------
|
84
|
+
|
85
|
+
actual = front_object.new('world')
|
86
|
+
|
87
|
+
- raise unless actual.salute == "Hello World!"
|
88
|
+
+ raise unless actual.salute == "Hello !"
|
89
|
+
```
|
90
|
+
|
91
|
+
### Optional parameters
|
92
|
+
|
93
|
+
It would also be possible to ask for an RSpec template by passing "`rspec`" argument:
|
94
|
+
|
95
|
+
```sh
|
96
|
+
brutal rspec
|
97
|
+
```
|
40
98
|
|
41
99
|
## Example
|
42
100
|
|
43
|
-
Given this
|
101
|
+
Given this config file:
|
44
102
|
|
45
103
|
```yaml
|
46
|
-
|
47
|
-
|
104
|
+
---
|
105
|
+
front_object: |
|
106
|
+
"Hello "
|
48
107
|
|
49
108
|
subject: |
|
50
|
-
|
109
|
+
%{front_object} + %{string}
|
51
110
|
|
52
111
|
variables:
|
53
|
-
:
|
54
|
-
-
|
55
|
-
- "
|
112
|
+
string:
|
113
|
+
- "'Alice'"
|
114
|
+
- "'Bob'"
|
56
115
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
challenges:
|
62
|
-
- .to_s
|
63
|
-
- .length
|
116
|
+
actual_values:
|
117
|
+
- "%{subject}.to_s"
|
118
|
+
- "%{subject}.length"
|
64
119
|
```
|
65
120
|
|
66
|
-
The `brutal` command would generate the following
|
121
|
+
The `brutal` command would generate and write in to a `test.rb` file the following "Plain Old Ruby":
|
67
122
|
|
68
123
|
```ruby
|
69
|
-
|
124
|
+
front_object = "Hello "
|
70
125
|
|
71
126
|
# ------------------------------------------------------------------------------
|
72
127
|
|
73
|
-
|
128
|
+
actual = front_object + 'Alice'
|
74
129
|
|
75
|
-
raise unless
|
76
|
-
raise unless
|
130
|
+
raise unless actual.to_s == "Hello Alice"
|
131
|
+
raise unless actual.length == 11
|
77
132
|
|
78
133
|
# ------------------------------------------------------------------------------
|
79
134
|
|
80
|
-
|
135
|
+
actual = front_object + 'Bob'
|
81
136
|
|
82
|
-
raise unless
|
83
|
-
raise unless
|
137
|
+
raise unless actual.to_s == "Hello Bob"
|
138
|
+
raise unless actual.length == 9
|
139
|
+
```
|
84
140
|
|
85
|
-
|
141
|
+
And the `brutal rspec` command would generate and write in to a `test_spec.rb` file the following spec:
|
86
142
|
|
87
|
-
|
143
|
+
```ruby
|
144
|
+
RSpec.describe do
|
145
|
+
let(:front_object) { "Hello " }
|
88
146
|
|
89
|
-
|
90
|
-
|
147
|
+
context do
|
148
|
+
let(:actual) { front_object + 'Alice' }
|
91
149
|
|
92
|
-
|
150
|
+
it { expect(actual.to_s).to eq("Hello Alice") }
|
151
|
+
it { expect(actual.length).to eq(11) }
|
152
|
+
end
|
93
153
|
|
94
|
-
|
154
|
+
context do
|
155
|
+
let(:actual) { front_object + 'Bob' }
|
95
156
|
|
96
|
-
|
97
|
-
|
157
|
+
it { expect(actual.to_s).to eq("Hello Bob") }
|
158
|
+
it { expect(actual.length).to eq(9) }
|
159
|
+
end
|
160
|
+
end
|
98
161
|
```
|
99
162
|
|
100
|
-
|
163
|
+
More examples are available [here](https://github.com/fixrb/brutal/raw/master/examples/).
|
164
|
+
|
165
|
+
## Rake integration example
|
101
166
|
|
102
|
-
|
167
|
+
A generated `test.rb` file could be matched as follows:
|
103
168
|
|
104
169
|
```ruby
|
105
170
|
Rake::TestTask.new do |t|
|
@@ -109,28 +174,27 @@ end
|
|
109
174
|
|
110
175
|
## Contact
|
111
176
|
|
112
|
-
*
|
113
|
-
* Bugs/issues: https://github.com/cyril/brutal.rb/issues
|
114
|
-
|
115
|
-
## Rubies
|
116
|
-
|
117
|
-
* [MRI](https://www.ruby-lang.org/)
|
118
|
-
* [Rubinius](https://rubinius.com/)
|
119
|
-
* [JRuby](https://www.jruby.org/)
|
177
|
+
* Source code: https://github.com/fixrb/brutal
|
120
178
|
|
121
|
-
##
|
179
|
+
## Versioning
|
122
180
|
|
123
|
-
|
181
|
+
__Brutal__ follows [Semantic Versioning 2.0](https://semver.org/).
|
124
182
|
|
125
183
|
## License
|
126
184
|
|
127
185
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
128
186
|
|
129
|
-
|
187
|
+
***
|
130
188
|
|
131
|
-
|
189
|
+
<p>
|
190
|
+
This project is sponsored by:<br />
|
191
|
+
<a href="https://sashite.com/"><img
|
192
|
+
src="https://github.com/fixrb/brutal/raw/master/img/sashite.png"
|
193
|
+
alt="Sashite" /></a>
|
194
|
+
</p>
|
132
195
|
|
196
|
+
[workflow_rubocop]: https://github.com/fixrb/brutal/actions?query=workflow%3ARuboCop
|
133
197
|
[gem]: https://rubygems.org/gems/brutal
|
134
|
-
[travis]: https://travis-ci.org/
|
135
|
-
[inchpages]: https://inch-ci.org/github/
|
198
|
+
[travis]: https://travis-ci.org/fixrb/brutal
|
199
|
+
[inchpages]: https://inch-ci.org/github/fixrb/brutal
|
136
200
|
[rubydoc]: https://rubydoc.info/gems/brutal/frames
|
data/bin/brutal
CHANGED
@@ -10,29 +10,36 @@ abort "File #{CONF_PATH} not found!" unless ::File.exist?(CONF_PATH)
|
|
10
10
|
|
11
11
|
conf = ::YAML.load_file(CONF_PATH)
|
12
12
|
|
13
|
-
header
|
14
|
-
|
15
|
-
|
16
|
-
variables
|
13
|
+
header = conf.fetch('header', '').to_s.chomp
|
14
|
+
front_object = conf.fetch('front_object')
|
15
|
+
subject = conf.fetch('subject')
|
16
|
+
variables = conf.fetch('variables', {})
|
17
|
+
actual_values = conf.fetch('actual_values')
|
17
18
|
|
18
|
-
raise ::TypeError unless
|
19
|
-
raise ::TypeError unless challenges.is_a?(::Array)
|
19
|
+
raise ::TypeError unless subject.is_a?(::String)
|
20
20
|
raise ::TypeError unless variables.is_a?(::Hash)
|
21
|
+
raise ::TypeError unless actual_values.is_a?(::Array)
|
22
|
+
|
23
|
+
front_object = front_object.chomp if front_object.is_a?(::String)
|
21
24
|
|
22
25
|
require_relative ::File.join('..', 'lib', 'brutal')
|
23
26
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
30
35
|
|
31
|
-
eval(header)
|
36
|
+
eval(header) # rubocop:disable Security/Eval
|
32
37
|
|
33
|
-
|
34
|
-
|
38
|
+
doc = [
|
39
|
+
header,
|
40
|
+
scaffold.new(front_object, subject, *actual_values, **variables).to_s
|
41
|
+
].reject(&:empty?).join("\n\n")
|
35
42
|
|
36
|
-
file = ::File.open(
|
37
|
-
file.write(
|
43
|
+
file = ::File.open(file_name, 'w')
|
44
|
+
file.write(doc)
|
38
45
|
file.close
|
data/lib/brutal.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# Main namespace
|
4
|
+
#
|
5
|
+
# @api public
|
3
6
|
module Brutal
|
4
7
|
end
|
5
8
|
|
6
|
-
Dir[File.join File.dirname(__FILE__), 'brutal', '
|
9
|
+
Dir[File.join File.dirname(__FILE__), 'brutal', 'scaffold_generator', '*.rb'].each do |fname|
|
7
10
|
require_relative fname
|
8
11
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Brutal
|
4
|
+
module ScaffoldGenerator
|
5
|
+
# Base class
|
6
|
+
class Base
|
7
|
+
# @api private
|
8
|
+
attr_reader :front_object_str, :front_object, :subject, :actual_values, :variables
|
9
|
+
|
10
|
+
# Initialize a new scaffold generator
|
11
|
+
def initialize(front_object, subject, *actual_values, **variables)
|
12
|
+
raise 'Empty actual values!' if actual_values.empty?
|
13
|
+
raise 'Empty variables!' if variables.empty?
|
14
|
+
|
15
|
+
@front_object_str = inspect(front_object)
|
16
|
+
@front_object = eval(@front_object_str) # rubocop:disable Security/Eval
|
17
|
+
@subject = subject
|
18
|
+
@actual_values = actual_values
|
19
|
+
@variables = variables
|
20
|
+
end
|
21
|
+
|
22
|
+
# Return a Ruby string that can be evaluated.
|
23
|
+
def inspect(object)
|
24
|
+
return object.to_s unless object.is_a?(::String)
|
25
|
+
|
26
|
+
object.strip
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,58 @@
|
|
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 Por < 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
|
+
blank_line.gsub(/\A\n/, '') +
|
24
|
+
"front_object = #{front_object_str}\n" +
|
25
|
+
blank_line +
|
26
|
+
test_params.map do |values|
|
27
|
+
attributes = names.each_with_index.inject(front_object: 'front_object') do |h, (name, i)|
|
28
|
+
h.merge(name.to_sym => inspect(values.fetch(i)))
|
29
|
+
end
|
30
|
+
|
31
|
+
actual_str = format(inspect(subject), **attributes)
|
32
|
+
|
33
|
+
string = <<~CODE
|
34
|
+
actual = begin
|
35
|
+
#{actual_str.gsub(/^/, ' ')}
|
36
|
+
end
|
37
|
+
|
38
|
+
CODE
|
39
|
+
|
40
|
+
actual = eval(actual_str) # rubocop:disable Security/Eval, Lint/UselessAssignment
|
41
|
+
|
42
|
+
actual_values.each do |actual_value|
|
43
|
+
result_str = format(actual_value, subject: 'actual')
|
44
|
+
string += "raise unless #{result_str} == #{eval(result_str).inspect}\n" # rubocop:disable Security/Eval
|
45
|
+
end
|
46
|
+
|
47
|
+
string
|
48
|
+
end.join(blank_line)
|
49
|
+
end
|
50
|
+
|
51
|
+
def blank_line
|
52
|
+
"\n" \
|
53
|
+
"# #{('-' * 78)}\n" \
|
54
|
+
"\n"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -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.1
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cyril Kato
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-01-23 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.
|
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.
|
26
|
+
version: '2.1'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -42,30 +42,30 @@ dependencies:
|
|
42
42
|
name: rubocop
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
47
|
+
version: '0.79'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
54
|
+
version: '0.79'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rubocop-performance
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '1.5'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '1.5'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: simplecov
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0.17'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: spectus
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '3.1'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '3.1'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: yard
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,24 +108,21 @@ dependencies:
|
|
94
108
|
- - "~>"
|
95
109
|
- !ruby/object:Gem::Version
|
96
110
|
version: '0.9'
|
97
|
-
description:
|
111
|
+
description: A code-first approach to automate the writing of unit tests.
|
98
112
|
email: contact@cyril.email
|
99
113
|
executables:
|
100
114
|
- brutal
|
101
|
-
- console
|
102
|
-
- setup
|
103
115
|
extensions: []
|
104
116
|
extra_rdoc_files: []
|
105
117
|
files:
|
106
118
|
- LICENSE.md
|
107
119
|
- README.md
|
108
120
|
- bin/brutal
|
109
|
-
- bin/console
|
110
|
-
- bin/setup
|
111
121
|
- lib/brutal.rb
|
112
|
-
- lib/brutal/
|
113
|
-
- lib/brutal/
|
114
|
-
|
122
|
+
- lib/brutal/scaffold_generator/base.rb
|
123
|
+
- lib/brutal/scaffold_generator/por.rb
|
124
|
+
- lib/brutal/scaffold_generator/rspec.rb
|
125
|
+
homepage: https://github.com/fixrb/brutal
|
115
126
|
licenses:
|
116
127
|
- MIT
|
117
128
|
metadata: {}
|
@@ -130,8 +141,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
130
141
|
- !ruby/object:Gem::Version
|
131
142
|
version: '0'
|
132
143
|
requirements: []
|
133
|
-
rubygems_version: 3.
|
144
|
+
rubygems_version: 3.1.2
|
134
145
|
signing_key:
|
135
146
|
specification_version: 4
|
136
|
-
summary:
|
147
|
+
summary: A code-first approach to automate the writing of unit tests.
|
137
148
|
test_files: []
|
data/bin/console
DELETED
data/bin/setup
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
module Brutal
|
2
|
-
module Framework
|
3
|
-
class Base
|
4
|
-
attr_reader :subject, :challenges, :variables
|
5
|
-
|
6
|
-
def initialize(subject, *challenges, **variables)
|
7
|
-
@subject = subject
|
8
|
-
@challenges = challenges
|
9
|
-
@variables = variables
|
10
|
-
end
|
11
|
-
|
12
|
-
def to_s
|
13
|
-
raise ::NotImplementedError
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
require_relative 'base'
|
2
|
-
|
3
|
-
module Brutal
|
4
|
-
module Framework
|
5
|
-
class Poro < Base
|
6
|
-
def to_s
|
7
|
-
names = variables.keys.sort
|
8
|
-
values_arr = names.map { |name| variables.fetch(name) }
|
9
|
-
test_params = Array(values_arr[0]).product(*Array(values_arr[1..-1]))
|
10
|
-
|
11
|
-
test_params.inject('') do |scaffold, values|
|
12
|
-
attributes = names.each_with_index.inject({}) do |h, (name, i)|
|
13
|
-
h.merge(name.to_sym => values.fetch(i))
|
14
|
-
end
|
15
|
-
|
16
|
-
populated_subject = subject % attributes
|
17
|
-
result = eval(populated_subject)
|
18
|
-
|
19
|
-
scaffold += "\n# " + ('-' * 78) + "\n\nresult = #{populated_subject}\n"
|
20
|
-
|
21
|
-
challenges.each do |challenge|
|
22
|
-
value = "result#{challenge}"
|
23
|
-
scaffold += "raise unless #{value} == #{eval(value).inspect}\n"
|
24
|
-
end
|
25
|
-
|
26
|
-
scaffold
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|