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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6a587ca80409c91605c6f0045e4f3b8b40f517b755e196748f0fc8dba6bff6e9
4
- data.tar.gz: 722b740531d4046ef5c3a639e93aa0c9edcfa362f63d43dfe77ae37ab9ee9062
3
+ metadata.gz: 491dc26f34135ff61ceb54bc64b4dc5793e8b2610d545b3025b8c7aaf53b3064
4
+ data.tar.gz: e7c379c45ce23f0886041ec8a4b6ab4c493a91e450230b64968e45a92214a62e
5
5
  SHA512:
6
- metadata.gz: e3147d44673898eee50b89db97c2f6ad19a48dd64b1c5df8c023ca64fe554a7d0a787f0f3241eb8e613aec2af59b50cda7331814807c80c1d2fed6ab833fac85
7
- data.tar.gz: 5e5d91e3d1139fae44f148632d6c94c944e407bf75c684db73ebc7cc15fa804855d90f2e6606280cafdf42d0a630a5a48068a0df45c32311ec2f85096345576c
6
+ metadata.gz: 8791614f90a92630a28aa3fb8b6d2a9d1921404b1cc614302bfeb8a87970186c33b935d81db81b7c1d8751475a59d5f32c17ea80627d32755daece880b93ace4
7
+ data.tar.gz: 19cf4fcbe94766983442f0f47b2651b5b675d5ade1c9b306e4213421d21253035545a23f8e6c988a8967db182b4de59a4158a545278684b4104039729963574c
data/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2019 Cyril Kato
3
+ Copyright (c) 2020 Cyril Kato
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,14 +1,37 @@
1
- # Brutal
1
+ # Brutal 💎🔨
2
2
 
3
- > Brutal test suite scaffold generator
4
-
5
- ![A lumberjack brutally cutting a tree.](img/Ferdinand_Hodler_-_Woodcutter_-_Google_Art_Project.jpg)
6
-
7
- [![Build Status](https://api.travis-ci.org/cyril/brutal.rb.svg?branch=master)][travis]
3
+ [![RuboCop Status](https://github.com/fixrb/brutal/workflows/RuboCop/badge.svg)][workflow_rubocop]
4
+ [![Build Status](https://api.travis-ci.org/fixrb/brutal.svg?branch=master)][travis]
8
5
  [![Gem Version](https://badge.fury.io/rb/brutal.svg)][gem]
9
- [![Inline docs](https://inch-ci.org/github/cyril/brutal.rb.svg?branch=master)][inchpages]
6
+ [![Inline docs](https://inch-ci.org/github/fixrb/brutal.svg?branch=master)][inchpages]
10
7
  [![Documentation](http://img.shields.io/:yard-docs-38c800.svg)][rubydoc]
11
8
 
9
+ > A _code-first_ approach to automate the writing of unit tests.
10
+
11
+ ## Why
12
+
13
+ [![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.")
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
- ## QuickStart
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
- The Brutal YAML file handles 4 keys:
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
- * `subject` (required): The front object of the test suite.
38
- * `variables` (required): A hash to decline the subject in to various contexts.
39
- * `challenges` (required): An array of methods to apply to each result.
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 `.brutal.yml` config file:
101
+ Given this config file:
44
102
 
45
103
  ```yaml
46
- header: |
47
- # Some string concatenation unit tests
104
+ ---
105
+ front_object: |
106
+ "Hello "
48
107
 
49
108
  subject: |
50
- "Hello" + "%{hello_target}%{punctuation_mark}"
109
+ %{front_object} + %{string}
51
110
 
52
111
  variables:
53
- :hello_target:
54
- -
55
- - ", Bob"
112
+ string:
113
+ - "'Alice'"
114
+ - "'Bob'"
56
115
 
57
- :punctuation_mark:
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 file:
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
- # Some string concatenation unit tests
124
+ front_object = "Hello "
70
125
 
71
126
  # ------------------------------------------------------------------------------
72
127
 
73
- result = "Hello" + "!"
128
+ actual = front_object + 'Alice'
74
129
 
75
- raise unless result.to_s == "Hello!"
76
- raise unless result.length == 6
130
+ raise unless actual.to_s == "Hello Alice"
131
+ raise unless actual.length == 11
77
132
 
78
133
  # ------------------------------------------------------------------------------
79
134
 
80
- result = "Hello" + "..."
135
+ actual = front_object + 'Bob'
81
136
 
82
- raise unless result.to_s == "Hello..."
83
- raise unless result.length == 8
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
- result = "Hello" + ", Bob!"
143
+ ```ruby
144
+ RSpec.describe do
145
+ let(:front_object) { "Hello " }
88
146
 
89
- raise unless result.to_s == "Hello, Bob!"
90
- raise unless result.length == 11
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
- result = "Hello" + ", Bob..."
154
+ context do
155
+ let(:actual) { front_object + 'Bob' }
95
156
 
96
- raise unless result.to_s == "Hello, Bob..."
97
- raise unless result.length == 13
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
- ## Integration with Rake
163
+ More examples are available [here](https://github.com/fixrb/brutal/raw/master/examples/).
164
+
165
+ ## Rake integration example
101
166
 
102
- The generated brutal test suite `test.rb` file can be declared as follows:
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
- * Home page: https://github.com/cyril/brutal.rb
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
- ## Contributing
179
+ ## Versioning
122
180
 
123
- Bug reports and pull requests are welcome on GitHub at https://github.com/cyril/brutal.rb. 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/cyril/brutal.rb/blob/master/CODE_OF_CONDUCT.md).
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
- ## Code of Conduct
187
+ ***
130
188
 
131
- 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/cyril/brutal.rb/blob/master/CODE_OF_CONDUCT.md).
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/cyril/brutal.rb
135
- [inchpages]: https://inch-ci.org/github/cyril/brutal.rb
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 = conf.fetch('header', '')
14
- subject = conf.fetch('subject')
15
- challenges = conf.fetch('challenges')
16
- variables = conf.fetch('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 header.is_a?(::String)
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
- brutal_scaffold = case ARGV.fetch(0, nil)
25
- when nil
26
- ::Brutal::Framework::Poro
27
- else
28
- abort "Framework #{ARGV[0].inspect} not (yet) supported!"
29
- 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
30
35
 
31
- eval(header)
36
+ eval(header) # rubocop:disable Security/Eval
32
37
 
33
- brutal_specs = header + brutal_scaffold.new(subject, *challenges, **variables)
34
- .to_s
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('test.rb', 'w')
37
- file.write(brutal_specs)
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', 'framework', '*.rb'].each do |fname|
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.0
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: 2019-12-15 00:00:00.000000000 Z
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.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
@@ -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: '0'
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: '0'
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: Brutal test suite scaffold generator
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/framework/base.rb
113
- - lib/brutal/framework/poro.rb
114
- homepage: https://github.com/cyril/brutal.rb
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.0.6
144
+ rubygems_version: 3.1.2
134
145
  signing_key:
135
146
  specification_version: 4
136
- summary: Brutal test suite scaffold generator
147
+ summary: A code-first approach to automate the writing of unit tests.
137
148
  test_files: []
data/bin/console DELETED
@@ -1,7 +0,0 @@
1
- #!/usr/bin/env ruby
2
- # frozen_string_literal: true
3
-
4
- require_relative ::File.join('..', 'lib', 'brutal')
5
-
6
- require 'irb'
7
- IRB.start(__FILE__)
data/bin/setup DELETED
@@ -1,7 +0,0 @@
1
- #!/usr/bin/env bash
2
-
3
- set -euo pipefail
4
- IFS=$'\n\t'
5
- set -vx
6
-
7
- bundle install
@@ -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