brutal 1.2.0 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE.md +2 -2
- data/README.md +47 -70
- data/bin/brutal +1 -1
- data/lib/brutal/configuration.rb +10 -5
- data/lib/brutal/file/read.rb +1 -6
- data/lib/brutal/file/write.rb +1 -6
- data/lib/brutal/file.rb +37 -0
- data/lib/brutal/scaffold.rb +46 -24
- data/lib/brutal/yaml.rb +10 -0
- data/lib/brutal.rb +26 -7
- metadata +20 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31ea2d6a9b38faaa03aaed25dfc8b18158a8d243b9aed42e0f4a3a488c8386a3
|
4
|
+
data.tar.gz: f73e4a2798de7a55deb006898919498a9d6344fcd3ec94728a379bf723370ae2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f5a9b52b8608bdf327bb14ad782cde378901285a3d9de0b28d273184480586f868da0b10bf32ac47980bfbc0b637b6bc058de2c42bdb600b4add7bb1865207e0
|
7
|
+
data.tar.gz: 302e2bf37546bc813caa05eedb38f2ad496123e6ba37b186d449ea2e5782945ef5d652d8cdc05a25c08045a472144ad6efa30f4316c23f5e3ca9ecdbdd8c8818
|
data/LICENSE.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
The MIT License
|
1
|
+
# The MIT License
|
2
2
|
|
3
|
-
Copyright (c) 2020-
|
3
|
+
Copyright (c) 2020-2022 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,10 +1,10 @@
|
|
1
1
|
# Brutal 💎🔨
|
2
2
|
|
3
|
-
[![
|
4
|
-
[![
|
5
|
-
[![
|
6
|
-
[![
|
7
|
-
[![
|
3
|
+
[![Version](https://img.shields.io/github/v/tag/fixrb/brutal?label=Version&logo=github)](https://github.com/fixrb/brutal/tags)
|
4
|
+
[![Yard documentation](https://img.shields.io/badge/Yard-documentation-blue.svg?logo=github)](https://rubydoc.info/github/fixrb/brutal/main)
|
5
|
+
[![Ruby](https://github.com/fixrb/brutal/workflows/Ruby/badge.svg?branch=main)](https://github.com/fixrb/brutal/actions?query=workflow%3Aruby+branch%3Amain)
|
6
|
+
[![RuboCop](https://github.com/fixrb/brutal/workflows/RuboCop/badge.svg?branch=main)](https://github.com/fixrb/brutal/actions?query=workflow%3Arubocop+branch%3Amain)
|
7
|
+
[![License](https://img.shields.io/github/license/fixrb/brutal?label=License&logo=github)](https://github.com/fixrb/brutal/raw/main/LICENSE.md)
|
8
8
|
|
9
9
|
> A _code-first_ approach to automate the writing of unit tests.
|
10
10
|
|
@@ -12,26 +12,26 @@
|
|
12
12
|
|
13
13
|
[![I Hate Tests](https://github.com/fixrb/brutal/raw/main/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
14
|
|
15
|
-
> I don't like tests. It's not DRY
|
15
|
+
> I don't like tests. It's not DRY.
|
16
16
|
> -- [Matz](https://github.com/matz)
|
17
17
|
|
18
18
|
## Overview
|
19
19
|
|
20
|
-
Let __Brutal__
|
20
|
+
Let __Brutal__ craft for you in no time a (potentially huge) framework-less vanilla Ruby file describing the actual behavior of your code across as many context combinations as necessary.
|
21
21
|
|
22
|
-
By delegating to __Brutal__ the repetitive (and redundant) task of writing tests, you
|
22
|
+
By delegating to __Brutal__ the repetitive (and redundant) task of writing tests, you will be able to focus on your core business: the code itself.
|
23
|
+
|
24
|
+
![Brutal-Driven Development](https://github.com/fixrb/brutal/raw/main/img/brutal-driven-development.jpg)
|
23
25
|
|
24
26
|
## Warning
|
25
27
|
|
26
|
-
|
28
|
+
The _Brutal-Driven Development_ process does not prevent bugs from appearing in the code.
|
29
|
+
|
30
|
+
A generated test suite acts as a _picture of the code's behavior_. Therefore, if the code is wrong, the picture of the code's behavior will also be wrong.
|
27
31
|
|
28
|
-
|
29
|
-
a generated test suite is wrong as long as the code is wrong,
|
30
|
-
regardless of whether all true expectations.
|
32
|
+
The mere fact that all expectations are true does not mean that the code behaves as it should.
|
31
33
|
|
32
|
-
|
33
|
-
It is therefore important to read it well.
|
34
|
-
This is the price for _Brutal-Driven Development_.
|
34
|
+
It is therefore the responsibility of the developer to analyze the generated behavioral pictures to ensure that the code reacts as it is supposed to according to the contexts in which it is evaluated.
|
35
35
|
|
36
36
|
## Installation
|
37
37
|
|
@@ -43,11 +43,15 @@ gem "brutal"
|
|
43
43
|
|
44
44
|
And then execute:
|
45
45
|
|
46
|
-
|
46
|
+
```sh
|
47
|
+
bundle install
|
48
|
+
```
|
47
49
|
|
48
50
|
Or install it yourself as:
|
49
51
|
|
50
|
-
|
52
|
+
```sh
|
53
|
+
gem install brutal
|
54
|
+
```
|
51
55
|
|
52
56
|
## Quick Start
|
53
57
|
|
@@ -55,63 +59,40 @@ Just type `brutal` in a Ruby project's folder and watch the magic happen.
|
|
55
59
|
|
56
60
|
## Usage
|
57
61
|
|
58
|
-
|
59
|
-
|
62
|
+
__Brutal__ needs a configuration file to know how to write your tests.
|
63
|
+
Currently, only the YAML format is supported.
|
64
|
+
This file is composed of 4 top-level sections:
|
60
65
|
|
61
66
|
* `header` - Specifies the code to execute before generating the test suite.
|
62
67
|
* `subject` - Specifies the template of the code to be declined across contexts.
|
63
68
|
* `contexts` - Specifies a list of variables to populate the subject's template.
|
64
69
|
* `actuals` - Specifies templates to challenge evaluated subjects & get results.
|
65
70
|
|
66
|
-
|
67
|
-
|
68
|
-
1. Create a `brutal.yml` file in your application's root directory.
|
69
|
-
The following example `brutal.yml` defines the shape of a Hello test suite:
|
71
|
+
This file is by default called `.brutal.yml`, but it would be possible to name it differently by passing it as an argument to the brutal command such as:
|
70
72
|
|
71
|
-
```
|
72
|
-
|
73
|
-
subject: |
|
74
|
-
"Hello " + "%{string}"
|
75
|
-
|
76
|
-
contexts:
|
77
|
-
string:
|
78
|
-
- Alice
|
79
|
-
- Bob
|
80
|
-
|
81
|
-
actuals:
|
82
|
-
- "%{subject}.to_s"
|
83
|
-
- "%{subject}.length"
|
73
|
+
```sh
|
74
|
+
brutal test_hello_world.yml
|
84
75
|
```
|
85
76
|
|
86
|
-
|
87
|
-
|
88
|
-
3. Read the generated `test.rb` file in the same directory:
|
89
|
-
|
90
|
-
```ruby
|
91
|
-
# Brutal test suite
|
92
|
-
|
93
|
-
# ------------------------------------------------------------------------------
|
77
|
+
This would create a `test_hello_world.rb` file containing the test suite.
|
94
78
|
|
95
|
-
|
96
|
-
"Hello " + "Alice"
|
97
|
-
end
|
79
|
+
To avoid accidentally overwriting a file, the `--no-force` option can be used:
|
98
80
|
|
99
|
-
|
100
|
-
|
81
|
+
```sh
|
82
|
+
brutal test_hello_world.yml --no-force
|
83
|
+
```
|
101
84
|
|
102
|
-
|
85
|
+
> A test_hello_world.rb file already exists!
|
103
86
|
|
104
|
-
|
105
|
-
"Hello " + "Bob"
|
106
|
-
end
|
87
|
+
### Getting started
|
107
88
|
|
108
|
-
|
109
|
-
|
110
|
-
|
89
|
+
1. Create a `.brutal.yml` file in your application's root directory. For example: <https://github.com/fixrb/brutal/blob/v1.4.0/examples/hello_world_v1/.brutal.yml>
|
90
|
+
2. Run the `brutal` command from the same directory.
|
91
|
+
3. Read the generated `test.rb` file in the same directory: <https://github.com/fixrb/brutal/blob/v1.4.0/examples/hello_world_v1/test.rb>
|
111
92
|
|
112
93
|
### More examples
|
113
94
|
|
114
|
-
https://github.com/fixrb/brutal/
|
95
|
+
<https://github.com/fixrb/brutal/blob/v1.4.0/examples/>
|
115
96
|
|
116
97
|
## Rake integration example
|
117
98
|
|
@@ -123,6 +104,10 @@ Rake::TestTask.new do |t|
|
|
123
104
|
end
|
124
105
|
```
|
125
106
|
|
107
|
+
## Test suite
|
108
|
+
|
109
|
+
__Brutal__'s test set is brutally self-generated here: [./test.rb](https://github.com/fixrb/brutal/blob/main/test.rb)
|
110
|
+
|
126
111
|
## Contact
|
127
112
|
|
128
113
|
* Source code: https://github.com/fixrb/brutal
|
@@ -133,19 +118,11 @@ __Brutal__ follows [Semantic Versioning 2.0](https://semver.org/).
|
|
133
118
|
|
134
119
|
## License
|
135
120
|
|
136
|
-
The [gem](https://rubygems.org/gems/brutal) is available as open source under the terms of the [MIT License](https://
|
121
|
+
The [gem](https://rubygems.org/gems/brutal) is available as open source under the terms of the [MIT License](https://github.com/fixrb/brutal/raw/main/LICENSE.md).
|
137
122
|
|
138
123
|
***
|
139
124
|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
alt="Sashite" /></a>
|
145
|
-
</p>
|
146
|
-
|
147
|
-
[workflow_rubocop]: https://github.com/fixrb/brutal/actions?query=workflow%3ARuboCop
|
148
|
-
[gem]: https://rubygems.org/gems/brutal
|
149
|
-
[travis]: https://travis-ci.org/fixrb/brutal
|
150
|
-
[inchpages]: https://inch-ci.org/github/fixrb/brutal
|
151
|
-
[rubydoc]: https://rubydoc.info/gems/brutal/frames
|
125
|
+
This project is sponsored by [Sashité](https://github.com/sashite/):
|
126
|
+
|
127
|
+
![Sashité logo](https://github.com/fixrb/brutal/raw/main/img/sponsor/dark/en/sashite.png#gh-dark-mode-only "Sashité")
|
128
|
+
![Sashité logo](https://github.com/fixrb/brutal/raw/main/img/sponsor/light/en/sashite.png#gh-light-mode-only "Sashité")
|
data/bin/brutal
CHANGED
data/lib/brutal/configuration.rb
CHANGED
@@ -5,9 +5,14 @@ module Brutal
|
|
5
5
|
#
|
6
6
|
# @since 1.0.0
|
7
7
|
class Configuration
|
8
|
+
ACTUALS_KEY = "actuals"
|
9
|
+
CONTEXTS_KEY = "contexts"
|
10
|
+
HEADER_KEY = "header"
|
11
|
+
SUBJECT_KEY = "subject"
|
12
|
+
|
8
13
|
DEFAULT_ACTUALS = [].freeze
|
9
14
|
DEFAULT_CONTEXTS = {}.freeze
|
10
|
-
|
15
|
+
DEFAULT_HEADER = "# Brutal test suite"
|
11
16
|
DEFAULT_SUBJECT = ""
|
12
17
|
|
13
18
|
# Load the configuration parameters.
|
@@ -15,10 +20,10 @@ module Brutal
|
|
15
20
|
# @param params [Hash] Receive the 4 top-level section parameters.
|
16
21
|
def self.load(params)
|
17
22
|
new(
|
18
|
-
actuals: params.fetch(
|
19
|
-
contexts: params.fetch(
|
20
|
-
header: params.fetch(
|
21
|
-
subject: params.fetch(
|
23
|
+
actuals: params.fetch(ACTUALS_KEY, DEFAULT_ACTUALS),
|
24
|
+
contexts: params.fetch(CONTEXTS_KEY, DEFAULT_CONTEXTS),
|
25
|
+
header: params.fetch(HEADER_KEY, DEFAULT_HEADER),
|
26
|
+
subject: params.fetch(SUBJECT_KEY, DEFAULT_SUBJECT)
|
22
27
|
)
|
23
28
|
end
|
24
29
|
|
data/lib/brutal/file/read.rb
CHANGED
@@ -1,19 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Brutal
|
4
|
-
# Brutal::File
|
5
|
-
#
|
6
|
-
# @since 1.1.0
|
7
4
|
module File
|
8
5
|
# Brutal::File::Read
|
9
6
|
#
|
10
7
|
# @since 1.1.0
|
11
8
|
class Read
|
12
|
-
NAME = ".brutal.yml"
|
13
|
-
|
14
9
|
attr_reader :name
|
15
10
|
|
16
|
-
def initialize(name
|
11
|
+
def initialize(name)
|
17
12
|
@name = name
|
18
13
|
end
|
19
14
|
|
data/lib/brutal/file/write.rb
CHANGED
@@ -1,19 +1,14 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Brutal
|
4
|
-
# Brutal::File
|
5
|
-
#
|
6
|
-
# @since 1.1.0
|
7
4
|
module File
|
8
5
|
# Brutal::File::Write
|
9
6
|
#
|
10
7
|
# @since 1.1.0
|
11
8
|
class Write
|
12
|
-
NAME = "test.rb"
|
13
|
-
|
14
9
|
attr_reader :name
|
15
10
|
|
16
|
-
def initialize(name
|
11
|
+
def initialize(name)
|
17
12
|
@name = name
|
18
13
|
end
|
19
14
|
|
data/lib/brutal/file.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
%w[
|
4
|
+
read
|
5
|
+
write
|
6
|
+
].each { |filename| require_relative(File.join("file", filename)) }
|
7
|
+
|
8
|
+
module Brutal
|
9
|
+
# Brutal::File
|
10
|
+
module File
|
11
|
+
DEFAULT_CONFIG_FILENAME = ".brutal.yml"
|
12
|
+
DEFAULT_GENERATED_FILENAME = "test.rb"
|
13
|
+
|
14
|
+
def self.generated_pathname(pathname)
|
15
|
+
filename = pathname.split(separator).fetch(-1)
|
16
|
+
|
17
|
+
if filename == DEFAULT_CONFIG_FILENAME
|
18
|
+
directory_parts = pathname.split(separator)[..-2]
|
19
|
+
path_parts = directory_parts + [DEFAULT_GENERATED_FILENAME]
|
20
|
+
return path_parts.join(separator)
|
21
|
+
end
|
22
|
+
|
23
|
+
pathname.gsub(/.[^.]+\z/, ".rb")
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.override_protection(pathname)
|
27
|
+
return true unless ::File.exist?(pathname)
|
28
|
+
|
29
|
+
abort "A #{pathname} file already exists!"
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.separator
|
33
|
+
::File::SEPARATOR
|
34
|
+
end
|
35
|
+
private_class_method :separator
|
36
|
+
end
|
37
|
+
end
|
data/lib/brutal/scaffold.rb
CHANGED
@@ -41,23 +41,36 @@ module Brutal
|
|
41
41
|
# Return a string representation.
|
42
42
|
#
|
43
43
|
# @return [String]
|
44
|
-
#
|
45
|
-
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
46
44
|
def to_s
|
47
|
-
|
48
|
-
|
49
|
-
h.merge(name.to_sym => inspect(values.fetch(i)))
|
50
|
-
end
|
45
|
+
ruby_lines.join(separator_ruby_code)
|
46
|
+
end
|
51
47
|
|
52
|
-
|
48
|
+
def attributes(*values)
|
49
|
+
context_names.each_with_index.inject({}) do |h, (name, i)|
|
50
|
+
h.merge(name.to_sym => inspect(values.fetch(i)))
|
51
|
+
end
|
52
|
+
end
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
end
|
54
|
+
def context_names
|
55
|
+
contexts.keys.sort
|
56
|
+
end
|
58
57
|
|
59
|
-
|
58
|
+
def contexts_values
|
59
|
+
context_names.map { |context_name| contexts.fetch(context_name) }
|
60
|
+
end
|
60
61
|
|
62
|
+
def combinations_values
|
63
|
+
Array(contexts_values[0]).product(*Array(contexts_values[1..]))
|
64
|
+
end
|
65
|
+
|
66
|
+
def ruby_lines
|
67
|
+
[header_ruby_code] + actual_ruby_codes
|
68
|
+
end
|
69
|
+
|
70
|
+
def actual_ruby_codes
|
71
|
+
combinations_values.map do |values|
|
72
|
+
actual_str = format(inspect(subject), **attributes(*values))
|
73
|
+
string = actual_ruby_code(actual_str)
|
61
74
|
actual = eval(actual_str) # rubocop:disable Security/Eval, Lint/UselessAssignment
|
62
75
|
|
63
76
|
actuals.each do |actual_value|
|
@@ -66,26 +79,35 @@ module Brutal
|
|
66
79
|
end
|
67
80
|
|
68
81
|
string
|
69
|
-
end
|
82
|
+
end
|
70
83
|
end
|
71
|
-
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
72
84
|
|
73
|
-
def
|
74
|
-
|
75
|
-
|
76
|
-
|
85
|
+
def actual_ruby_code(actual_str)
|
86
|
+
<<~RUBY_CODE
|
87
|
+
actual = begin
|
88
|
+
#{actual_str.gsub(/^/, ' ')}
|
89
|
+
end
|
90
|
+
|
91
|
+
RUBY_CODE
|
77
92
|
end
|
78
93
|
|
79
|
-
def
|
80
|
-
|
94
|
+
def header_ruby_code
|
95
|
+
<<~RUBY_CODE
|
96
|
+
#{header.chomp}
|
97
|
+
RUBY_CODE
|
81
98
|
end
|
82
99
|
|
83
|
-
def
|
84
|
-
|
100
|
+
def separator_ruby_code
|
101
|
+
<<~RUBY_CODE
|
102
|
+
|
103
|
+
#{thematic_break_ruby_code}
|
104
|
+
RUBY_CODE
|
85
105
|
end
|
86
106
|
|
87
|
-
def
|
88
|
-
|
107
|
+
def thematic_break_ruby_code
|
108
|
+
<<~RUBY_CODE
|
109
|
+
# #{'-' * 78}
|
110
|
+
RUBY_CODE
|
89
111
|
end
|
90
112
|
end
|
91
113
|
end
|
data/lib/brutal/yaml.rb
CHANGED
@@ -7,8 +7,18 @@ module Brutal
|
|
7
7
|
#
|
8
8
|
# @since 1.1.0
|
9
9
|
module Yaml
|
10
|
+
FILENAME_EXTENSIONS = %w[
|
11
|
+
yaml
|
12
|
+
yml
|
13
|
+
].freeze
|
14
|
+
|
10
15
|
def self.parse(yaml)
|
11
16
|
::YAML.safe_load(yaml, symbolize_names: false)
|
12
17
|
end
|
18
|
+
|
19
|
+
def self.parse?(pathname)
|
20
|
+
filename_extension = pathname.split(".")[1..][-1]
|
21
|
+
FILENAME_EXTENSIONS.include?(filename_extension)
|
22
|
+
end
|
13
23
|
end
|
14
24
|
end
|
data/lib/brutal.rb
CHANGED
@@ -2,23 +2,42 @@
|
|
2
2
|
|
3
3
|
%w[
|
4
4
|
configuration
|
5
|
-
file
|
6
|
-
file/write
|
5
|
+
file
|
7
6
|
scaffold
|
8
7
|
yaml
|
9
|
-
].each { |
|
8
|
+
].each { |filename| require_relative(File.join("brutal", filename)) }
|
10
9
|
|
11
10
|
# The Brutal namespace.
|
12
11
|
module Brutal
|
13
|
-
def self.generate!
|
14
|
-
|
15
|
-
hash = Yaml.parse(yaml)
|
12
|
+
def self.generate!(pathname, force: true)
|
13
|
+
hash = parse(pathname)
|
16
14
|
conf = Configuration.load(hash)
|
15
|
+
|
17
16
|
ruby = Scaffold.new(conf.header,
|
18
17
|
conf.subject,
|
19
18
|
*conf.actuals,
|
20
19
|
**conf.contexts)
|
21
20
|
|
22
|
-
|
21
|
+
write(pathname, ruby, force: force)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.parse(pathname)
|
25
|
+
return Yaml.parse(read(pathname)) if Yaml.parse?(pathname)
|
26
|
+
|
27
|
+
raise ::ArgumentError, "Unrecognized extension. " \
|
28
|
+
"Impossible to parse #{pathname.inspect}."
|
29
|
+
end
|
30
|
+
private_class_method :parse
|
31
|
+
|
32
|
+
def self.read(pathname)
|
33
|
+
File::Read.new(pathname).call
|
34
|
+
end
|
35
|
+
private_class_method :read
|
36
|
+
|
37
|
+
def self.write(pathname, ruby, force:)
|
38
|
+
new_pathname = File.generated_pathname(pathname)
|
39
|
+
File.override_protection(new_pathname) unless force
|
40
|
+
File::Write.new(new_pathname).call(ruby)
|
23
41
|
end
|
42
|
+
private_class_method :write
|
24
43
|
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: 1.
|
4
|
+
version: 1.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:
|
11
|
+
date: 2022-08-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rubocop-gitlab-security
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rubocop-md
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -134,6 +148,7 @@ files:
|
|
134
148
|
- bin/brutal
|
135
149
|
- lib/brutal.rb
|
136
150
|
- lib/brutal/configuration.rb
|
151
|
+
- lib/brutal/file.rb
|
137
152
|
- lib/brutal/file/read.rb
|
138
153
|
- lib/brutal/file/write.rb
|
139
154
|
- lib/brutal/scaffold.rb
|
@@ -141,7 +156,8 @@ files:
|
|
141
156
|
homepage: https://github.com/fixrb/brutal
|
142
157
|
licenses:
|
143
158
|
- MIT
|
144
|
-
metadata:
|
159
|
+
metadata:
|
160
|
+
rubygems_mfa_required: 'true'
|
145
161
|
post_install_message:
|
146
162
|
rdoc_options: []
|
147
163
|
require_paths:
|
@@ -157,7 +173,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
157
173
|
- !ruby/object:Gem::Version
|
158
174
|
version: '0'
|
159
175
|
requirements: []
|
160
|
-
rubygems_version: 3.1.
|
176
|
+
rubygems_version: 3.1.6
|
161
177
|
signing_key:
|
162
178
|
specification_version: 4
|
163
179
|
summary: A code-first approach to automate the writing of unit tests.
|