brutal 1.3.0 → 1.4.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
  SHA256:
3
- metadata.gz: 7f98c650c2e97438b0cedcebdb5b01da84af29f7cbc0c324a4b3416b3da68114
4
- data.tar.gz: 696e8e96639a62e046f138c10f3d5181a3265c90bb10306481bc0d2b2fd9d3d0
3
+ metadata.gz: 31ea2d6a9b38faaa03aaed25dfc8b18158a8d243b9aed42e0f4a3a488c8386a3
4
+ data.tar.gz: f73e4a2798de7a55deb006898919498a9d6344fcd3ec94728a379bf723370ae2
5
5
  SHA512:
6
- metadata.gz: b6279a503eba6120d29cd8855fab48c725f46671bd8efa7d6fd73158e68d0cf6de9fed01e4f5ae83cf04417b0551ab9598d6c615d25b164fbefec1d3b7ce262f
7
- data.tar.gz: 8aebd74fd0a2c9bda6b418980dd627645f9b1c85f3e92e753ba2c03bd642d0dd63393dfd8923ef25e470269e3b6645fa3428a54cd7b2128ca53ee2b5c9e5de63
6
+ metadata.gz: f5a9b52b8608bdf327bb14ad782cde378901285a3d9de0b28d273184480586f868da0b10bf32ac47980bfbc0b637b6bc058de2c42bdb600b4add7bb1865207e0
7
+ data.tar.gz: 302e2bf37546bc813caa05eedb38f2ad496123e6ba37b186d449ea2e5782945ef5d652d8cdc05a25c08045a472144ad6efa30f4316c23f5e3ca9ecdbdd8c8818
data/README.md CHANGED
@@ -59,7 +59,8 @@ Just type `brutal` in a Ruby project's folder and watch the magic happen.
59
59
 
60
60
  ## Usage
61
61
 
62
- __Brutal__ needs a configuration file, it's a kind of manifest, or a meta-spec if you prefer.
62
+ __Brutal__ needs a configuration file to know how to write your tests.
63
+ Currently, only the YAML format is supported.
63
64
  This file is composed of 4 top-level sections:
64
65
 
65
66
  * `header` - Specifies the code to execute before generating the test suite.
@@ -67,59 +68,31 @@ This file is composed of 4 top-level sections:
67
68
  * `contexts` - Specifies a list of variables to populate the subject's template.
68
69
  * `actuals` - Specifies templates to challenge evaluated subjects & get results.
69
70
 
70
- By default, this file is called `.brutal.yml`, but it would be possible to call it differently by passing it as an argument to the brutal command.
71
-
72
- Currently, only the YAML format is supported.
73
-
74
- ### Getting started
75
-
76
- 1. Create a `.brutal.yml` file in your application's root directory.
77
- 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:
78
72
 
79
- ```yaml
80
- ---
81
- subject: |
82
- "Hello " + "%{string}"
83
-
84
- contexts:
85
- string:
86
- - Alice
87
- - Bob
88
-
89
- actuals:
90
- - "%{subject}.to_s"
91
- - "%{subject}.length"
73
+ ```sh
74
+ brutal test_hello_world.yml
92
75
  ```
93
76
 
94
- 2. Run the `brutal` command from the same directory.
77
+ This would create a `test_hello_world.rb` file containing the test suite.
95
78
 
96
- 3. Read the generated `test.rb` file in the same directory:
79
+ To avoid accidentally overwriting a file, the `--no-force` option can be used:
97
80
 
98
- ```ruby
99
- # Brutal test suite
100
-
101
- # ------------------------------------------------------------------------------
102
-
103
- actual = begin
104
- "Hello " + "Alice"
105
- end
106
-
107
- raise if actual.to_s != "Hello Alice"
108
- raise if actual.length != 11
81
+ ```sh
82
+ brutal test_hello_world.yml --no-force
83
+ ```
109
84
 
110
- # ------------------------------------------------------------------------------
85
+ > A test_hello_world.rb file already exists!
111
86
 
112
- actual = begin
113
- "Hello " + "Bob"
114
- end
87
+ ### Getting started
115
88
 
116
- raise if actual.to_s != "Hello Bob"
117
- raise if actual.length != 9
118
- ```
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>
119
92
 
120
93
  ### More examples
121
94
 
122
- https://github.com/fixrb/brutal/raw/main/examples/
95
+ <https://github.com/fixrb/brutal/blob/v1.4.0/examples/>
123
96
 
124
97
  ## Rake integration example
125
98
 
data/bin/brutal CHANGED
@@ -3,4 +3,4 @@
3
3
 
4
4
  require_relative File.join("..", "lib", "brutal")
5
5
 
6
- Brutal.generate! ARGV.fetch(0, Brutal::File::DEFAULT_CONFIG_FILENAME)
6
+ Brutal.generate! ARGV.fetch(0, Brutal::File::DEFAULT_CONFIG_FILENAME), force: ARGV.none?("--no-force")
data/lib/brutal/file.rb CHANGED
@@ -11,10 +11,27 @@ module Brutal
11
11
  DEFAULT_CONFIG_FILENAME = ".brutal.yml"
12
12
  DEFAULT_GENERATED_FILENAME = "test.rb"
13
13
 
14
- def self.generated_filename(filename)
15
- return DEFAULT_GENERATED_FILENAME if filename == DEFAULT_CONFIG_FILENAME
14
+ def self.generated_pathname(pathname)
15
+ filename = pathname.split(separator).fetch(-1)
16
16
 
17
- filename.gsub(/.[^.]+\z/, ".rb")
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
18
34
  end
35
+ private_class_method :separator
19
36
  end
20
37
  end
@@ -42,20 +42,35 @@ module Brutal
42
42
  #
43
43
  # @return [String]
44
44
  def to_s
45
- "#{header.chomp}\n#{blank_line}" + combinations_values.map do |values|
46
- attributes = context_names.each_with_index.inject({}) do |h, (name, i)|
47
- h.merge(name.to_sym => inspect(values.fetch(i)))
48
- end
45
+ ruby_lines.join(separator_ruby_code)
46
+ end
47
+
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
+
54
+ def context_names
55
+ contexts.keys.sort
56
+ end
49
57
 
50
- actual_str = format(inspect(subject), **attributes)
58
+ def contexts_values
59
+ context_names.map { |context_name| contexts.fetch(context_name) }
60
+ end
51
61
 
52
- string = <<~CODE
53
- actual = begin
54
- #{actual_str.gsub(/^/, ' ')}
55
- end
62
+ def combinations_values
63
+ Array(contexts_values[0]).product(*Array(contexts_values[1..]))
64
+ end
56
65
 
57
- CODE
66
+ def ruby_lines
67
+ [header_ruby_code] + actual_ruby_codes
68
+ end
58
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)
59
74
  actual = eval(actual_str) # rubocop:disable Security/Eval, Lint/UselessAssignment
60
75
 
61
76
  actuals.each do |actual_value|
@@ -64,25 +79,35 @@ module Brutal
64
79
  end
65
80
 
66
81
  string
67
- end.join(blank_line)
82
+ end
68
83
  end
69
84
 
70
- def blank_line
71
- "\n" \
72
- "# #{'-' * 78}\n" \
73
- "\n"
85
+ def actual_ruby_code(actual_str)
86
+ <<~RUBY_CODE
87
+ actual = begin
88
+ #{actual_str.gsub(/^/, ' ')}
89
+ end
90
+
91
+ RUBY_CODE
74
92
  end
75
93
 
76
- def context_names
77
- contexts.keys.sort
94
+ def header_ruby_code
95
+ <<~RUBY_CODE
96
+ #{header.chomp}
97
+ RUBY_CODE
78
98
  end
79
99
 
80
- def contexts_values
81
- context_names.map { |context_name| contexts.fetch(context_name) }
100
+ def separator_ruby_code
101
+ <<~RUBY_CODE
102
+
103
+ #{thematic_break_ruby_code}
104
+ RUBY_CODE
82
105
  end
83
106
 
84
- def combinations_values
85
- Array(contexts_values[0]).product(*Array(contexts_values[1..]))
107
+ def thematic_break_ruby_code
108
+ <<~RUBY_CODE
109
+ # #{'-' * 78}
110
+ RUBY_CODE
86
111
  end
87
112
  end
88
113
  end
data/lib/brutal/yaml.rb CHANGED
@@ -16,8 +16,8 @@ module Brutal
16
16
  ::YAML.safe_load(yaml, symbolize_names: false)
17
17
  end
18
18
 
19
- def self.parse?(filename)
20
- filename_extension = filename.split(".")[1..][-1]
19
+ def self.parse?(pathname)
20
+ filename_extension = pathname.split(".")[1..][-1]
21
21
  FILENAME_EXTENSIONS.include?(filename_extension)
22
22
  end
23
23
  end
data/lib/brutal.rb CHANGED
@@ -9,16 +9,8 @@
9
9
 
10
10
  # The Brutal namespace.
11
11
  module Brutal
12
- def self.generate!(filename)
13
- file = File::Read.new(filename).call
14
-
15
- hash = if Yaml.parse?(filename)
16
- Yaml.parse(file)
17
- else
18
- raise ::ArgumentError, "Unrecognized extension. " \
19
- "Impossible to parse #{filename.inspect}."
20
- end
21
-
12
+ def self.generate!(pathname, force: true)
13
+ hash = parse(pathname)
22
14
  conf = Configuration.load(hash)
23
15
 
24
16
  ruby = Scaffold.new(conf.header,
@@ -26,8 +18,26 @@ module Brutal
26
18
  *conf.actuals,
27
19
  **conf.contexts)
28
20
 
29
- new_filename = File.generated_filename(filename)
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
30
36
 
31
- File::Write.new(new_filename).call(ruby)
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)
32
41
  end
42
+ private_class_method :write
33
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.3.0
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: 2022-08-21 00:00:00.000000000 Z
11
+ date: 2022-08-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler