brutal 1.3.0 → 1.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: 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