brutal 0.2.0 → 1.0.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 +4 -4
- data/LICENSE.md +1 -1
- data/README.md +80 -66
- data/bin/brutal +2 -34
- data/lib/brutal.rb +21 -6
- data/lib/brutal/configuration.rb +45 -0
- data/lib/brutal/scaffold.rb +81 -0
- metadata +26 -30
- data/bin/console +0 -7
- data/bin/setup +0 -7
- data/lib/brutal/framework/base.rb +0 -22
- data/lib/brutal/framework/por.rb +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 332c8755656f334781310460780dd233d621ddac83bc7d7dc5f0c555f4d1f955
|
4
|
+
data.tar.gz: c49ae44f98432fb3839bcf7c76ac3929bfee3eac82113bc4903e6d288863865e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f015f9cbc3f478c66374b72a3c6e7340863b472eac796833700aa11a501c3361b2519939f0e407308a6800df23bb7ba959ec60d70f5b16acb86f3d30ae0440e2
|
7
|
+
data.tar.gz: 90c7d4fef875977bd991a16405675e424524d2478318d33e694d073a47348986a2bb93bc27f9ff5cdfb5d5d48120d334f55733ad0ff6a3880c401ba901c85391
|
data/LICENSE.md
CHANGED
data/README.md
CHANGED
@@ -1,14 +1,38 @@
|
|
1
|
-
# Brutal
|
1
|
+
# Brutal 💎🔨
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-

|
6
|
-
|
7
|
-
[][travis]
|
3
|
+
[][workflow_rubocop]
|
4
|
+
[][travis]
|
8
5
|
[][gem]
|
9
|
-
[][inchpages]
|
10
7
|
[][rubydoc]
|
11
8
|
|
9
|
+
> A _code-first_ approach to automate the writing of unit tests.
|
10
|
+
|
11
|
+
## Intro
|
12
|
+
|
13
|
+
[](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
|
+
## Overview
|
19
|
+
|
20
|
+
Let __Brutal__ shape for you in no time the actual behavior of your code through as many combinations of contexts as needed.
|
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.
|
23
|
+
|
24
|
+
## Warning
|
25
|
+
|
26
|
+
__Brutal__ development process does not prevent from bugs.
|
27
|
+
|
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.
|
31
|
+
|
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_.
|
35
|
+
|
12
36
|
## Installation
|
13
37
|
|
14
38
|
Add this line to your application's Gemfile:
|
@@ -31,76 +55,67 @@ Just type `brutal` in a Ruby project's folder and watch the magic happen.
|
|
31
55
|
|
32
56
|
## Usage
|
33
57
|
|
34
|
-
The
|
58
|
+
The `brutal.yml` file is a manifest you can use to define your __Brutal__ meta-spec.
|
59
|
+
It has 4 top-level sections:
|
35
60
|
|
36
|
-
* `header`
|
37
|
-
* `subject`
|
38
|
-
* `
|
39
|
-
* `
|
61
|
+
* `header` - Specifies the code to execute before generating the test suite.
|
62
|
+
* `subject` - Specifies the template of the code to be declined across contexts.
|
63
|
+
* `contexts` - Specifies a list of variables to populate the subject's template.
|
64
|
+
* `actuals` - Specifies templates to challenge evaluated subjects & get results.
|
40
65
|
|
41
|
-
|
66
|
+
### Getting started
|
42
67
|
|
43
|
-
|
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:
|
44
70
|
|
45
71
|
```yaml
|
46
72
|
---
|
47
|
-
header: |
|
48
|
-
# Some string concatenation unit tests
|
49
|
-
|
50
73
|
subject: |
|
51
|
-
"Hello" + "%{
|
74
|
+
"Hello " + "%{string}"
|
52
75
|
|
53
|
-
|
54
|
-
:
|
55
|
-
-
|
56
|
-
-
|
76
|
+
contexts:
|
77
|
+
string:
|
78
|
+
- Alice
|
79
|
+
- Bob
|
57
80
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
challenges:
|
63
|
-
- "%{actual}.to_s"
|
64
|
-
- "%{actual}.length"
|
81
|
+
actuals:
|
82
|
+
- "%{subject}.to_s"
|
83
|
+
- "%{subject}.length"
|
65
84
|
```
|
66
85
|
|
67
|
-
|
68
|
-
|
69
|
-
```ruby
|
70
|
-
# Some string concatenation unit tests
|
86
|
+
2. Run the `brutal` command from the same directory.
|
71
87
|
|
72
|
-
|
88
|
+
3. Read the generated `test.rb` file in the same directory:
|
73
89
|
|
74
|
-
|
75
|
-
|
76
|
-
raise unless actual.to_s == "Hello!"
|
77
|
-
raise unless actual.length == 6
|
90
|
+
```ruby
|
91
|
+
# Brutal test suite
|
78
92
|
|
79
93
|
# ------------------------------------------------------------------------------
|
80
94
|
|
81
|
-
actual =
|
95
|
+
actual = begin
|
96
|
+
"Hello " + "Alice"
|
97
|
+
end
|
82
98
|
|
83
|
-
raise
|
84
|
-
raise
|
99
|
+
raise if actual.to_s != "Hello Alice"
|
100
|
+
raise if actual.length != 11
|
85
101
|
|
86
102
|
# ------------------------------------------------------------------------------
|
87
103
|
|
88
|
-
actual =
|
104
|
+
actual = begin
|
105
|
+
"Hello " + "Bob"
|
106
|
+
end
|
89
107
|
|
90
|
-
raise
|
91
|
-
raise
|
108
|
+
raise if actual.to_s != "Hello Bob"
|
109
|
+
raise if actual.length != 9
|
110
|
+
```
|
92
111
|
|
93
|
-
|
112
|
+
### More examples
|
94
113
|
|
95
|
-
|
114
|
+
https://github.com/fixrb/brutal/raw/master/examples/
|
96
115
|
|
97
|
-
|
98
|
-
raise unless actual.length == 13
|
99
|
-
```
|
116
|
+
## Rake integration example
|
100
117
|
|
101
|
-
|
102
|
-
|
103
|
-
The generated brutal test suite `test.rb` file can be declared as follows:
|
118
|
+
A generated `test.rb` file could be matched as follows:
|
104
119
|
|
105
120
|
```ruby
|
106
121
|
Rake::TestTask.new do |t|
|
@@ -110,28 +125,27 @@ end
|
|
110
125
|
|
111
126
|
## Contact
|
112
127
|
|
113
|
-
*
|
114
|
-
* Bugs/issues: https://github.com/cyril/brutal.rb/issues
|
115
|
-
|
116
|
-
## Rubies
|
117
|
-
|
118
|
-
* [MRI](https://www.ruby-lang.org/)
|
119
|
-
* [Rubinius](https://rubinius.com/)
|
120
|
-
* [JRuby](https://www.jruby.org/)
|
128
|
+
* Source code: https://github.com/fixrb/brutal
|
121
129
|
|
122
|
-
##
|
130
|
+
## Versioning
|
123
131
|
|
124
|
-
|
132
|
+
__Brutal__ follows [Semantic Versioning 2.0](https://semver.org/).
|
125
133
|
|
126
134
|
## License
|
127
135
|
|
128
136
|
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
129
137
|
|
130
|
-
|
138
|
+
***
|
131
139
|
|
132
|
-
|
140
|
+
<p>
|
141
|
+
This project is sponsored by:<br />
|
142
|
+
<a href="https://sashite.com/"><img
|
143
|
+
src="https://github.com/fixrb/brutal/raw/master/img/sashite.png"
|
144
|
+
alt="Sashite" /></a>
|
145
|
+
</p>
|
133
146
|
|
147
|
+
[workflow_rubocop]: https://github.com/fixrb/brutal/actions?query=workflow%3ARuboCop
|
134
148
|
[gem]: https://rubygems.org/gems/brutal
|
135
|
-
[travis]: https://travis-ci.org/
|
136
|
-
[inchpages]: https://inch-ci.org/github/
|
149
|
+
[travis]: https://travis-ci.org/fixrb/brutal
|
150
|
+
[inchpages]: https://inch-ci.org/github/fixrb/brutal
|
137
151
|
[rubydoc]: https://rubydoc.info/gems/brutal/frames
|
data/bin/brutal
CHANGED
@@ -1,38 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
4
|
+
require_relative File.join('..', 'lib', 'brutal')
|
5
5
|
|
6
|
-
|
7
|
-
CONF_PATH = ::File.join(::Dir.pwd, FILE_NAME)
|
8
|
-
|
9
|
-
abort "File #{CONF_PATH} not found!" unless ::File.exist?(CONF_PATH)
|
10
|
-
|
11
|
-
conf = ::YAML.load_file(CONF_PATH)
|
12
|
-
|
13
|
-
header = conf.fetch('header', '')
|
14
|
-
subject = conf.fetch('subject')
|
15
|
-
challenges = conf.fetch('challenges')
|
16
|
-
variables = conf.fetch('variables')
|
17
|
-
|
18
|
-
raise ::TypeError unless header.is_a?(::String)
|
19
|
-
raise ::TypeError unless challenges.is_a?(::Array)
|
20
|
-
raise ::TypeError unless variables.is_a?(::Hash)
|
21
|
-
|
22
|
-
require_relative ::File.join('..', 'lib', 'brutal')
|
23
|
-
|
24
|
-
brutal_scaffold = case ARGV.fetch(0, nil)
|
25
|
-
when nil
|
26
|
-
::Brutal::Framework::Por
|
27
|
-
else
|
28
|
-
abort "Framework #{ARGV[0].inspect} not (yet) supported!"
|
29
|
-
end
|
30
|
-
|
31
|
-
eval(header)
|
32
|
-
|
33
|
-
brutal_specs = header + brutal_scaffold.new(subject, *challenges, **variables)
|
34
|
-
.to_s
|
35
|
-
|
36
|
-
file = ::File.open('test.rb', 'w')
|
37
|
-
file.write(brutal_specs)
|
38
|
-
file.close
|
6
|
+
Brutal.generate!
|
data/lib/brutal.rb
CHANGED
@@ -1,11 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
%w[
|
4
|
+
configuration
|
5
|
+
scaffold
|
6
|
+
].each { |file_name| require_relative(File.join('brutal', file_name)) }
|
7
|
+
|
8
|
+
# The Brutal namespace
|
6
9
|
module Brutal
|
7
|
-
|
10
|
+
def self.settings
|
11
|
+
Configuration.load!
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.generate
|
15
|
+
Scaffold.new(*settings)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.generate!
|
19
|
+
file = ::File.open('test.rb', 'w')
|
20
|
+
file.write(generate)
|
8
21
|
|
9
|
-
|
10
|
-
|
22
|
+
true
|
23
|
+
ensure
|
24
|
+
file.close
|
25
|
+
end
|
11
26
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Brutal
|
6
|
+
# Brutal::Configuration
|
7
|
+
#
|
8
|
+
# @since 1.0.0
|
9
|
+
class Configuration
|
10
|
+
NAME = '.brutal.yml'
|
11
|
+
PATH = ::File.join(::Dir.pwd, NAME).freeze
|
12
|
+
|
13
|
+
def self.load!
|
14
|
+
new.to_a
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.file!
|
18
|
+
::YAML.load_file(PATH)
|
19
|
+
rescue ::Errno::ENOENT => _e
|
20
|
+
abort("File #{PATH} not found!")
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_reader(:header, :subject, :contexts, :actuals)
|
24
|
+
|
25
|
+
# rubocop:disable Metrics/AbcSize
|
26
|
+
def initialize
|
27
|
+
settings = self.class.file!
|
28
|
+
|
29
|
+
@header = settings.fetch('header', '# Brutal test suite')
|
30
|
+
@subject = settings.fetch('subject', '')
|
31
|
+
@contexts = settings.fetch('contexts', {})
|
32
|
+
@actuals = settings.fetch('actuals', [])
|
33
|
+
|
34
|
+
raise ::TypeError, @header.inspect unless @header.is_a?(::String)
|
35
|
+
raise ::TypeError, @subject.inspect unless @subject.is_a?(::String)
|
36
|
+
raise ::TypeError, @contexts.inspect unless @contexts.is_a?(::Hash)
|
37
|
+
raise ::TypeError, @actuals.inspect unless @actuals.is_a?(::Array)
|
38
|
+
end
|
39
|
+
# rubocop:enable Metrics/AbcSize
|
40
|
+
|
41
|
+
def to_a
|
42
|
+
[header, subject, *actuals, **contexts]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Brutal
|
4
|
+
# Brutal::Scaffold
|
5
|
+
#
|
6
|
+
# @since 1.0.0
|
7
|
+
class Scaffold
|
8
|
+
attr_reader(:header, :subject, :actuals, :contexts)
|
9
|
+
|
10
|
+
# Initialize a new scaffold generator
|
11
|
+
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?
|
15
|
+
|
16
|
+
eval(header) # rubocop:disable Security/Eval
|
17
|
+
|
18
|
+
@header = header
|
19
|
+
@subject = subject
|
20
|
+
@actuals = actuals
|
21
|
+
@contexts = contexts
|
22
|
+
end
|
23
|
+
|
24
|
+
# Return a Ruby string that can be evaluated.
|
25
|
+
def inspect(object)
|
26
|
+
return object.to_s unless object.is_a?(::String)
|
27
|
+
|
28
|
+
object.strip
|
29
|
+
end
|
30
|
+
|
31
|
+
# Return a string representation
|
32
|
+
#
|
33
|
+
# @return [String]
|
34
|
+
#
|
35
|
+
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
36
|
+
def to_s
|
37
|
+
header.chomp + "\n" + blank_line + combinations_values.map do |values|
|
38
|
+
attributes = context_names.each_with_index.inject({}) do |h, (name, i)|
|
39
|
+
h.merge(name.to_sym => inspect(values.fetch(i)))
|
40
|
+
end
|
41
|
+
|
42
|
+
actual_str = format(inspect(subject), **attributes)
|
43
|
+
|
44
|
+
string = <<~CODE
|
45
|
+
actual = begin
|
46
|
+
#{actual_str.gsub(/^/, ' ')}
|
47
|
+
end
|
48
|
+
|
49
|
+
CODE
|
50
|
+
|
51
|
+
actual = eval(actual_str) # rubocop:disable Security/Eval, Lint/UselessAssignment
|
52
|
+
|
53
|
+
actuals.each do |actual_value|
|
54
|
+
result_str = format(actual_value, subject: 'actual')
|
55
|
+
string += "raise if #{result_str} != #{eval(result_str).inspect}\n" # rubocop:disable Security/Eval
|
56
|
+
end
|
57
|
+
|
58
|
+
string
|
59
|
+
end.join(blank_line)
|
60
|
+
end
|
61
|
+
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength
|
62
|
+
|
63
|
+
def blank_line
|
64
|
+
"\n" \
|
65
|
+
"# #{('-' * 78)}\n" \
|
66
|
+
"\n"
|
67
|
+
end
|
68
|
+
|
69
|
+
def context_names
|
70
|
+
contexts.keys.sort
|
71
|
+
end
|
72
|
+
|
73
|
+
def contexts_values
|
74
|
+
context_names.map { |context_name| contexts.fetch(context_name) }
|
75
|
+
end
|
76
|
+
|
77
|
+
def combinations_values
|
78
|
+
Array(contexts_values[0]).product(*Array(contexts_values[1..-1]))
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
metadata
CHANGED
@@ -1,45 +1,45 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: brutal
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.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: 2020-03-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0'
|
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: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name: rubocop
|
42
|
+
name: rubocop-performance
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - ">="
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name: rubocop-
|
56
|
+
name: rubocop-thread_safety
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - ">="
|
@@ -70,48 +70,44 @@ dependencies:
|
|
70
70
|
name: simplecov
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '0
|
75
|
+
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '0
|
82
|
+
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: yard
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '0
|
89
|
+
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - "
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '0
|
97
|
-
description:
|
96
|
+
version: '0'
|
97
|
+
description: A code-first approach to automate the writing of unit tests.
|
98
98
|
email: contact@cyril.email
|
99
99
|
executables:
|
100
100
|
- brutal
|
101
|
-
- console
|
102
|
-
- setup
|
103
101
|
extensions: []
|
104
102
|
extra_rdoc_files: []
|
105
103
|
files:
|
106
104
|
- LICENSE.md
|
107
105
|
- README.md
|
108
106
|
- bin/brutal
|
109
|
-
- bin/console
|
110
|
-
- bin/setup
|
111
107
|
- lib/brutal.rb
|
112
|
-
- lib/brutal/
|
113
|
-
- lib/brutal/
|
114
|
-
homepage: https://github.com/
|
108
|
+
- lib/brutal/configuration.rb
|
109
|
+
- lib/brutal/scaffold.rb
|
110
|
+
homepage: https://github.com/fixrb/brutal
|
115
111
|
licenses:
|
116
112
|
- MIT
|
117
113
|
metadata: {}
|
@@ -130,8 +126,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
130
126
|
- !ruby/object:Gem::Version
|
131
127
|
version: '0'
|
132
128
|
requirements: []
|
133
|
-
rubygems_version: 3.
|
129
|
+
rubygems_version: 3.1.2
|
134
130
|
signing_key:
|
135
131
|
specification_version: 4
|
136
|
-
summary:
|
132
|
+
summary: A code-first approach to automate the writing of unit tests.
|
137
133
|
test_files: []
|
data/bin/console
DELETED
data/bin/setup
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
module Brutal
|
2
|
-
module Framework
|
3
|
-
class Base
|
4
|
-
# @api private
|
5
|
-
attr_reader :subject, :challenges, :variables
|
6
|
-
|
7
|
-
# Initialize a new framework
|
8
|
-
def initialize(subject, *challenges, **variables)
|
9
|
-
@subject = subject
|
10
|
-
@challenges = challenges
|
11
|
-
@variables = variables
|
12
|
-
end
|
13
|
-
|
14
|
-
# Return a string representation
|
15
|
-
#
|
16
|
-
# @api private
|
17
|
-
def to_s
|
18
|
-
raise ::NotImplementedError
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
data/lib/brutal/framework/por.rb
DELETED
@@ -1,41 +0,0 @@
|
|
1
|
-
require_relative 'base'
|
2
|
-
|
3
|
-
module Brutal
|
4
|
-
module Framework
|
5
|
-
# Plain Old Ruby
|
6
|
-
class Por < Base
|
7
|
-
# Return a string representation
|
8
|
-
#
|
9
|
-
# @return [String]
|
10
|
-
#
|
11
|
-
# @api public
|
12
|
-
def to_s
|
13
|
-
names = variables.keys.sort
|
14
|
-
values_arr = names.map { |name| variables.fetch(name) }
|
15
|
-
test_params = Array(values_arr[0]).product(*Array(values_arr[1..-1]))
|
16
|
-
|
17
|
-
test_params.inject('') do |string, values|
|
18
|
-
attributes = names.each_with_index.inject({}) do |h, (name, i)|
|
19
|
-
h.merge(name.to_sym => values.fetch(i))
|
20
|
-
end
|
21
|
-
|
22
|
-
actual_str = subject % attributes
|
23
|
-
|
24
|
-
string += "\n" \
|
25
|
-
"# #{('-' * 78)}\n" \
|
26
|
-
"\n" \
|
27
|
-
"actual = #{actual_str}\n"
|
28
|
-
|
29
|
-
actual = eval(actual_str)
|
30
|
-
|
31
|
-
challenges.each do |challenge|
|
32
|
-
result = challenge % { actual: 'actual' }
|
33
|
-
string += "raise unless #{result} == #{eval(result).inspect}\n"
|
34
|
-
end
|
35
|
-
|
36
|
-
string
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|