brutal 1.1.0 → 1.2.1

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: 31950aed12f6f2f8a292c6df194cbab35c832f649597df8a96f73a7852688da9
4
- data.tar.gz: 5300bdf71607debf6de06e4ddf37e8f7c7d4104822b18784cffed24451df8f30
3
+ metadata.gz: 958cf59b6aea2f5e323b849c83a86399cd9ad99e2433b899160a2422275a319e
4
+ data.tar.gz: bdb36f749b6bfcb87683f12d3db9e74c716bdbfbf41e21c845864bf1e17f7a7e
5
5
  SHA512:
6
- metadata.gz: fd76ba0d91ce4a7df5c477906970e1affb5459d2dcffa03709d6078089e95b82a0a80b372d659e6306a870b5c6f73469c6bcf95e7c8367d09f833f53941fa0de
7
- data.tar.gz: 5cc889579792f8d836de4327eb83007c490e204016da975fdbe60792eea096d41c5906127a5210a5d2899cfc565024eede92d566ad69afe0b4f748fdbd46e8f1
6
+ metadata.gz: 6f4b098047917136946c7bb88b111b5e6facf2a13ab70677bf0bce480bc2b4f0931f89f0be8ad2dc6db152abaaeffbdece5993d7ac5fba2ca85fde601df0c4c2
7
+ data.tar.gz: 7d5d125189afacf46a008a6b12c79ec68ffeb6e15c4324c1a6924a19be9061dac5760224225a564a8a1d9410b18a3da80591beeb30e5abc15995a5094326fab4
data/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2020 Cyril Kato
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,53 +1,57 @@
1
1
  # Brutal 💎🔨
2
2
 
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]
5
- [![Gem Version](https://badge.fury.io/rb/brutal.svg)][gem]
6
- [![Inline docs](https://inch-ci.org/github/fixrb/brutal.svg?branch=master)][inchpages]
7
- [![Documentation](http://img.shields.io/:yard-docs-38c800.svg)][rubydoc]
3
+ [![Version](https://img.shields.io/github/v/tag/fixrb/brutal?label=Version&logo=github)](https://github.com/fixrb/brutal/releases)
4
+ [![Yard documentation](https://img.shields.io/badge/Yard-documentation-blue.svg?logo=github)](https://rubydoc.info/github/fixrb/brutal/main)
5
+ [![CI](https://github.com/fixrb/brutal/workflows/CI/badge.svg?branch=main)](https://github.com/fixrb/brutal/actions?query=workflow%3Aci+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
 
11
11
  ## Intro
12
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.")
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.<br/>
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__ shape for you in no time the actual behavior of your code through as many combinations of contexts as needed.
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'll be able to focus on your core business: the code itself.
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
- __Brutal__ development process does not prevent from bugs.
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
- As a _picture of the behavior of the code_,
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
- However, this document becomes relevant when it shows that the code behaves as it is supposed to.
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
 
38
38
  Add this line to your application's Gemfile:
39
39
 
40
40
  ```ruby
41
- gem 'brutal'
41
+ gem "brutal"
42
42
  ```
43
43
 
44
44
  And then execute:
45
45
 
46
- $ bundle install
46
+ ```sh
47
+ bundle install
48
+ ```
47
49
 
48
50
  Or install it yourself as:
49
51
 
50
- $ gem install brutal
52
+ ```sh
53
+ gem install brutal
54
+ ```
51
55
 
52
56
  ## Quick Start
53
57
 
@@ -111,7 +115,7 @@ raise if actual.length != 9
111
115
 
112
116
  ### More examples
113
117
 
114
- https://github.com/fixrb/brutal/raw/master/examples/
118
+ https://github.com/fixrb/brutal/raw/main/examples/
115
119
 
116
120
  ## Rake integration example
117
121
 
@@ -119,10 +123,14 @@ A generated `test.rb` file could be matched as follows:
119
123
 
120
124
  ```ruby
121
125
  Rake::TestTask.new do |t|
122
- t.pattern = 'test.rb'
126
+ t.pattern = "test.rb"
123
127
  end
124
128
  ```
125
129
 
130
+ ## Test suite
131
+
132
+ __Brutal__'s test set is brutally self-generated here: [./test.rb](https://github.com/fixrb/brutal/blob/main/test.rb)
133
+
126
134
  ## Contact
127
135
 
128
136
  * Source code: https://github.com/fixrb/brutal
@@ -133,19 +141,13 @@ __Brutal__ follows [Semantic Versioning 2.0](https://semver.org/).
133
141
 
134
142
  ## License
135
143
 
136
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
144
+ 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
145
 
138
146
  ***
139
147
 
140
148
  <p>
141
149
  This project is sponsored by:<br />
142
150
  <a href="https://sashite.com/"><img
143
- src="https://github.com/fixrb/brutal/raw/master/img/sashite.png"
151
+ src="https://github.com/fixrb/brutal/raw/main/img/sashite.png"
144
152
  alt="Sashite" /></a>
145
153
  </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
data/bin/brutal CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- require_relative File.join('..', 'lib', 'brutal')
4
+ require_relative File.join("..", "lib", "brutal")
5
5
 
6
6
  Brutal.generate!
@@ -5,17 +5,48 @@ module Brutal
5
5
  #
6
6
  # @since 1.0.0
7
7
  class Configuration
8
- HEAD = '# Brutal test suite'
8
+ ACTUALS_KEY = "actuals"
9
+ CONTEXTS_KEY = "contexts"
10
+ HEADER_KEY = "header"
11
+ SUBJECT_KEY = "subject"
9
12
 
10
- attr_reader(:actuals, :contexts, :header, :subject)
13
+ DEFAULT_ACTUALS = [].freeze
14
+ DEFAULT_CONTEXTS = {}.freeze
15
+ DEFAULT_HEADER = "# Brutal test suite"
16
+ DEFAULT_SUBJECT = ""
11
17
 
12
- def initialize(actuals: [], contexts: {}, header: HEAD, subject: '')
18
+ # Load the configuration parameters.
19
+ #
20
+ # @param params [Hash] Receive the 4 top-level section parameters.
21
+ def self.load(params)
22
+ new(
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)
27
+ )
28
+ end
29
+
30
+ # Specifies templates to challenge evaluated subjects & get results.
31
+ attr_reader :actuals
32
+
33
+ # Specifies a list of variables to populate the subject's template.
34
+ attr_reader :contexts
35
+
36
+ # Specifies the code to execute before generating the test suite.
37
+ attr_reader :header
38
+
39
+ # Specifies the template of the code to be declined across contexts.
40
+ attr_reader :subject
41
+
42
+ # Initialize a new configuration.
43
+ def initialize(actuals:, contexts:, header:, subject:)
13
44
  raise ::TypeError, actuals.inspect unless actuals.is_a?(::Array)
14
45
  raise ::TypeError, contexts.inspect unless contexts.is_a?(::Hash)
15
46
  raise ::TypeError, header.inspect unless header.is_a?(::String)
16
47
  raise ::TypeError, subject.inspect unless subject.is_a?(::String)
17
48
 
18
- @actuals = actuals
49
+ @actuals = actuals.sort
19
50
  @contexts = contexts
20
51
  @header = header
21
52
  @subject = subject
@@ -9,7 +9,7 @@ module Brutal
9
9
  #
10
10
  # @since 1.1.0
11
11
  class Read
12
- NAME = '.brutal.yml'
12
+ NAME = ".brutal.yml"
13
13
 
14
14
  attr_reader :name
15
15
 
@@ -9,7 +9,7 @@ module Brutal
9
9
  #
10
10
  # @since 1.1.0
11
11
  class Write
12
- NAME = 'test.rb'
12
+ NAME = "test.rb"
13
13
 
14
14
  attr_reader :name
15
15
 
@@ -18,7 +18,7 @@ module Brutal
18
18
  end
19
19
 
20
20
  def call(scaffold)
21
- file = ::File.open(path, 'w')
21
+ file = ::File.open(path, "w")
22
22
  file.write(scaffold)
23
23
 
24
24
  true
@@ -5,13 +5,23 @@ module Brutal
5
5
  #
6
6
  # @since 1.0.0
7
7
  class Scaffold
8
- attr_reader(:header, :subject, :actuals, :contexts)
8
+ # Specifies templates to challenge evaluated subjects & get results.
9
+ attr_reader :actuals
9
10
 
10
- # Initialize a new scaffold generator
11
+ # Specifies a list of variables to populate the subject's template.
12
+ attr_reader :contexts
13
+
14
+ # Specifies the code to execute before generating the test suite.
15
+ attr_reader :header
16
+
17
+ # Specifies the template of the code to be declined across contexts.
18
+ attr_reader :subject
19
+
20
+ # Initialize a new scaffold generator.
11
21
  def initialize(header, subject, *actuals, **contexts)
12
- warn('Empty subject!') if subject.empty?
13
- warn('Empty actual values!') if actuals.empty?
14
- warn('Empty contexts!') if contexts.empty?
22
+ warn("Empty subject!") if subject.empty?
23
+ warn("Empty actual values!") if actuals.empty?
24
+ warn("Empty contexts!") if contexts.empty?
15
25
 
16
26
  eval(header) # rubocop:disable Security/Eval
17
27
 
@@ -28,13 +38,11 @@ module Brutal
28
38
  object.strip
29
39
  end
30
40
 
31
- # Return a string representation
41
+ # Return a string representation.
32
42
  #
33
43
  # @return [String]
34
- #
35
- # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
36
44
  def to_s
37
- header.chomp + "\n" + blank_line + combinations_values.map do |values|
45
+ "#{header.chomp}\n#{blank_line}" + combinations_values.map do |values|
38
46
  attributes = context_names.each_with_index.inject({}) do |h, (name, i)|
39
47
  h.merge(name.to_sym => inspect(values.fetch(i)))
40
48
  end
@@ -43,7 +51,7 @@ module Brutal
43
51
 
44
52
  string = <<~CODE
45
53
  actual = begin
46
- #{actual_str.gsub(/^/, ' ')}
54
+ #{actual_str.gsub(/^/, " ")}
47
55
  end
48
56
 
49
57
  CODE
@@ -51,19 +59,18 @@ module Brutal
51
59
  actual = eval(actual_str) # rubocop:disable Security/Eval, Lint/UselessAssignment
52
60
 
53
61
  actuals.each do |actual_value|
54
- result_str = format(actual_value, subject: 'actual')
62
+ result_str = format(actual_value, subject: "actual")
55
63
  string += "raise if #{result_str} != #{eval(result_str).inspect}\n" # rubocop:disable Security/Eval
56
64
  end
57
65
 
58
66
  string
59
67
  end.join(blank_line)
60
68
  end
61
- # rubocop:enable Metrics/AbcSize, Metrics/MethodLength
62
69
 
63
70
  def blank_line
64
- "\n" \
65
- "# #{('-' * 78)}\n" \
66
- "\n"
71
+ "\n" \
72
+ "# #{"-" * 78}\n" \
73
+ "\n"
67
74
  end
68
75
 
69
76
  def context_names
@@ -75,7 +82,7 @@ module Brutal
75
82
  end
76
83
 
77
84
  def combinations_values
78
- Array(contexts_values[0]).product(*Array(contexts_values[1..-1]))
85
+ Array(contexts_values[0]).product(*Array(contexts_values[1..]))
79
86
  end
80
87
  end
81
88
  end
data/lib/brutal/yaml.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'yaml'
3
+ require "yaml"
4
4
 
5
5
  module Brutal
6
6
  # Brutal::Yaml
@@ -8,7 +8,7 @@ module Brutal
8
8
  # @since 1.1.0
9
9
  module Yaml
10
10
  def self.parse(yaml)
11
- ::YAML.safe_load(yaml, symbolize_names: true)
11
+ ::YAML.safe_load(yaml, symbolize_names: false)
12
12
  end
13
13
  end
14
14
  end
data/lib/brutal.rb CHANGED
@@ -6,14 +6,15 @@
6
6
  file/write
7
7
  scaffold
8
8
  yaml
9
- ].each { |file_name| require_relative(File.join('brutal', file_name)) }
9
+ ].each { |file_name| require_relative(File.join("brutal", file_name)) }
10
10
 
11
- # The Brutal namespace
11
+ # The Brutal namespace.
12
12
  module Brutal
13
13
  def self.generate!
14
14
  yaml = File::Read.new.call
15
15
  hash = Yaml.parse(yaml)
16
- conf = Configuration.new(**hash)
16
+ conf = Configuration.load(hash)
17
+
17
18
  ruby = Scaffold.new(conf.header,
18
19
  conf.subject,
19
20
  *conf.actuals,
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.1.0
4
+ version: 1.2.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: 2020-03-14 00:00:00.000000000 Z
11
+ date: 2022-04-03 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-md
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-performance
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +66,20 @@ dependencies:
52
66
  - - ">="
53
67
  - !ruby/object:Gem::Version
54
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop-rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: rubocop-thread_safety
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -113,7 +141,8 @@ files:
113
141
  homepage: https://github.com/fixrb/brutal
114
142
  licenses:
115
143
  - MIT
116
- metadata: {}
144
+ metadata:
145
+ rubygems_mfa_required: 'true'
117
146
  post_install_message:
118
147
  rdoc_options: []
119
148
  require_paths:
@@ -122,14 +151,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
122
151
  requirements:
123
152
  - - ">="
124
153
  - !ruby/object:Gem::Version
125
- version: 2.6.0
154
+ version: 2.7.0
126
155
  required_rubygems_version: !ruby/object:Gem::Requirement
127
156
  requirements:
128
157
  - - ">="
129
158
  - !ruby/object:Gem::Version
130
159
  version: '0'
131
160
  requirements: []
132
- rubygems_version: 3.0.1
161
+ rubygems_version: 3.1.6
133
162
  signing_key:
134
163
  specification_version: 4
135
164
  summary: A code-first approach to automate the writing of unit tests.