speq 0.2.0 → 0.2.1
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/.gitignore +2 -0
- data/Gemfile.lock +1 -1
- data/README.md +17 -20
- data/bin/console +0 -1
- data/exe/speq +1 -1
- data/lib/speq/cli.rb +1 -6
- data/lib/speq/fake.rb +13 -0
- data/lib/speq/matcher.rb +50 -0
- data/lib/speq/report.rb +31 -0
- data/lib/speq/test.rb +1 -50
- data/lib/speq/unit.rb +20 -0
- data/lib/speq/version.rb +1 -1
- data/lib/speq.rb +19 -3
- metadata +5 -3
- data/lib/speq/match.rb +0 -26
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ca948589baaf3fd6d4385aec6da046cb0b96595ea1cc78af59787bf76112abe0
|
|
4
|
+
data.tar.gz: 5879601e06032198afc0675b44130900b3fdbb895f207cab7c2cfc94b70638fb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8f999677ac2de3f9e9760cfebe7180d1cb91215060a6f424f0c856f981ba9818715105b13dc1353d1b43d1fb9382b6c2189a0f31f64d50b21999b8ecb4bd4e23
|
|
7
|
+
data.tar.gz: 1f674c4b2593df191a9d036b0f458cf1aee46f342066667f5df33504bd70e5cfb30858f3fdc208229f0a87741d36fd9b7785e5a05234bb2a0e4f85556c8ffb18
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -16,21 +16,24 @@ gem 'speq'
|
|
|
16
16
|
|
|
17
17
|
And then execute:
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
bundle
|
|
20
20
|
|
|
21
21
|
Or install it yourself as:
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
gem install speq
|
|
24
|
+
|
|
25
|
+
## Design
|
|
26
|
+
|
|
27
|
+
Speq's design choices are influenced by the competing motivations of having tests be as short and simple as possible while maintaining the flexibility to be as descriptive as needed.
|
|
28
|
+
|
|
29
|
+
Speq is loosely based on the given-when-then or arrange-act-assert testing pattern. Whereas one would typically need to make each step explicit, Speq tests focus on making it easy to simply assert the expected behavior with an implicit arrangement and action.
|
|
24
30
|
|
|
25
31
|
## Syntax
|
|
26
32
|
|
|
27
|
-
Speq
|
|
33
|
+
Speq's syntax is still in flux and likely to change dramatically until an effective setup is established.
|
|
28
34
|
|
|
29
35
|
```ruby
|
|
30
|
-
|
|
31
|
-
given 0, 1, 8, match: false
|
|
32
|
-
given 2, 3, 97, match: true
|
|
33
|
-
end
|
|
36
|
+
test_unit :sort, on: [3, 2, 1], eq: [1, 2, 3]
|
|
34
37
|
```
|
|
35
38
|
|
|
36
39
|
## Usage
|
|
@@ -40,30 +43,24 @@ end
|
|
|
40
43
|
```ruby
|
|
41
44
|
require 'speq'
|
|
42
45
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
Speq.test do
|
|
47
|
+
# Tests here can access local variables.
|
|
48
|
+
# Test results are printed to $stdout.
|
|
49
|
+
# The method returns true if all tests pass, false otherwise.
|
|
47
50
|
end
|
|
48
|
-
|
|
49
|
-
# Speq.test...
|
|
50
51
|
```
|
|
51
52
|
|
|
52
53
|
### With dedicated spec files
|
|
53
54
|
|
|
54
55
|
Speq also offers a simple CLI that lets you run tests written in dedicated spec files.
|
|
55
56
|
|
|
56
|
-
Executing the
|
|
57
|
-
|
|
58
|
-
$ bundle exec speq
|
|
59
|
-
|
|
60
|
-
will recursively search the working directory and run all files that end with `_speq.rb`.
|
|
57
|
+
Executing `bundle exec speq` will recursively search the working directory and run all files that end with `_speq.rb`.
|
|
61
58
|
|
|
62
59
|
To run individual files, specify a list of speq file prefixes. For example, to run tests that are within the files `example_speq.rb` and `sample_speq.rb`, simply execute:
|
|
63
60
|
|
|
64
|
-
|
|
61
|
+
bundle exec speq example sample
|
|
65
62
|
|
|
66
|
-
Speq files are not expected to require `speq`, but they should require other files that may be needed to run the
|
|
63
|
+
Speq files are not expected to require `speq`, but they should require other files that may be needed to run the specs.
|
|
67
64
|
|
|
68
65
|
## Contributing
|
|
69
66
|
|
data/bin/console
CHANGED
data/exe/speq
CHANGED
data/lib/speq/cli.rb
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
require 'find'
|
|
2
2
|
require 'colorize'
|
|
3
|
-
require 'speq/test'
|
|
4
3
|
|
|
5
4
|
# Provides a CLI for running Speq
|
|
6
5
|
module Speq
|
|
@@ -18,12 +17,8 @@ module Speq
|
|
|
18
17
|
Dir.glob("#{Dir.pwd}/**/{#{file_prefixes.join(',')}}_speq.rb")
|
|
19
18
|
end
|
|
20
19
|
|
|
21
|
-
def does(subject, &block)
|
|
22
|
-
tests << Test.new(subject, self, &block)
|
|
23
|
-
end
|
|
24
|
-
|
|
25
20
|
def run
|
|
26
|
-
@files.each { |file|
|
|
21
|
+
@files.each { |file| Speq.module_eval(File.read(file), file) }
|
|
27
22
|
@tests.each(&:report)
|
|
28
23
|
@tests.all?(&:passed?)
|
|
29
24
|
end
|
data/lib/speq/fake.rb
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# The Fake class inludes a variety of doubles, mocks, stubs, etc.
|
|
2
2
|
module Speq
|
|
3
3
|
class Fake
|
|
4
|
+
def initialize(mapping)
|
|
5
|
+
mapping.each do |method_name, return_value|
|
|
6
|
+
define_singleton_method(method_name, &infer_method_body(return_value))
|
|
7
|
+
end
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def infer_method_body(return_value)
|
|
11
|
+
if return_value.respond_to?(:call)
|
|
12
|
+
return_value
|
|
13
|
+
else
|
|
14
|
+
-> { return_value }
|
|
15
|
+
end
|
|
16
|
+
end
|
|
4
17
|
end
|
|
5
18
|
end
|
data/lib/speq/matcher.rb
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# The Match class includes factory methods for generating objects that
|
|
2
|
+
# respond to match, returning true for an expected return value of a unit test
|
|
3
|
+
module Speq
|
|
4
|
+
class Matcher
|
|
5
|
+
def initialize(expected)
|
|
6
|
+
@expected = expected
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def match(actual)
|
|
10
|
+
@expected[actual]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.truthy
|
|
14
|
+
Matcher.new(->(actual_value) { actual_value ? true : false })
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.falsey
|
|
18
|
+
Matcher.new(->(actual_value) { actual_value ? false : true })
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.eq(expected_value)
|
|
22
|
+
Matcher.new(->(actual_value) { expected_value.eql?(actual_value) })
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.is(expected_object)
|
|
26
|
+
Matcher.new(->(actual_object) { expected_object.equal?(actual_object) })
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.raises(expected_except)
|
|
30
|
+
case expected_except
|
|
31
|
+
when Class
|
|
32
|
+
raise_class(expected_except)
|
|
33
|
+
when String
|
|
34
|
+
raise_message(expected_except)
|
|
35
|
+
else
|
|
36
|
+
raise ArgumentError
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.raise_class(expected_error)
|
|
41
|
+
Matcher.new(->(actual_except) { actual_except.class <= expected_error })
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.raise_message(expected_message)
|
|
45
|
+
Matcher.new(
|
|
46
|
+
->(actual_except) { actual_except.message == expected_message }
|
|
47
|
+
)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
data/lib/speq/report.rb
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# The Report class produces and prints a report per test group
|
|
2
|
+
module Speq
|
|
3
|
+
class Report
|
|
4
|
+
def initialize(units)
|
|
5
|
+
@units = units
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def print_report
|
|
9
|
+
report_string = ''
|
|
10
|
+
|
|
11
|
+
@units.each do |unit|
|
|
12
|
+
if unit.passed?
|
|
13
|
+
outcome = 'PASSED: '
|
|
14
|
+
color = :green
|
|
15
|
+
else
|
|
16
|
+
outcome = 'FAILED: '
|
|
17
|
+
color = :red
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
method = "calling '#{unit.message}' "
|
|
21
|
+
arguments = unit.arguments ? "with arguments: '#{unit.arguments}'" : ''
|
|
22
|
+
receiver = unit.receiver == Object ? '' : "on: #{unit.receiver} "
|
|
23
|
+
|
|
24
|
+
report_string <<
|
|
25
|
+
[outcome, method, arguments, receiver, "\n"].join.colorize(color)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
puts report_string
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
data/lib/speq/test.rb
CHANGED
|
@@ -1,61 +1,12 @@
|
|
|
1
|
-
require 'speq/match'
|
|
2
|
-
|
|
3
1
|
# The Test class is a simple implementation of unit test block
|
|
4
2
|
module Speq
|
|
5
3
|
class Test
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
def initialize(method_symbol, class_name = Object, &block)
|
|
9
|
-
@method = method_symbol
|
|
10
|
-
@reciever = class_name
|
|
4
|
+
def initialize
|
|
11
5
|
@units = []
|
|
12
|
-
|
|
13
|
-
instance_eval(&block)
|
|
14
|
-
print_report
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def given(*args, match:)
|
|
18
|
-
args.each do |arg|
|
|
19
|
-
return_value = reciever.send(method, *arg)
|
|
20
|
-
|
|
21
|
-
@units << Match.new(return_value, :eql?, arg, match)
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def on(*receivers, match:)
|
|
26
|
-
receivers.each do |receiver|
|
|
27
|
-
return_value = receiver.send(method)
|
|
28
|
-
|
|
29
|
-
@units << Match.new(return_value, :eql?, arg, match)
|
|
30
|
-
end
|
|
31
6
|
end
|
|
32
7
|
|
|
33
8
|
def passed?
|
|
34
9
|
@units.all?(&:passed?)
|
|
35
10
|
end
|
|
36
|
-
|
|
37
|
-
def print_report
|
|
38
|
-
report_string = "Testing: #{method}\n"
|
|
39
|
-
|
|
40
|
-
@units.each do |one_test|
|
|
41
|
-
if one_test.passed?
|
|
42
|
-
outcome_text = 'PASSED'
|
|
43
|
-
color = :green
|
|
44
|
-
else
|
|
45
|
-
outcome_text = 'FAILED'
|
|
46
|
-
color = :red
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
indent = ' ' * @method.to_s.length
|
|
50
|
-
|
|
51
|
-
report_string <<
|
|
52
|
-
["\n#{outcome_text} when given: #{one_test.args}\n".colorize(color),
|
|
53
|
-
" returned: #{one_test.actual}\n".colorize(color),
|
|
54
|
-
" expected: #{one_test.expected}\n".colorize(color)].join
|
|
55
|
-
end
|
|
56
|
-
puts report_string
|
|
57
|
-
|
|
58
|
-
passed?
|
|
59
|
-
end
|
|
60
11
|
end
|
|
61
12
|
end
|
data/lib/speq/unit.rb
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# The Unit class is responsible for running a test and storing the result
|
|
2
|
+
module Speq
|
|
3
|
+
class Unit
|
|
4
|
+
attr_reader :message, :receiver, :arguments
|
|
5
|
+
|
|
6
|
+
def initialize(message, receiver = Object, arguments = [], matcher)
|
|
7
|
+
@result = matcher.match(receiver.send(message, *arguments))
|
|
8
|
+
rescue StandardError => exception
|
|
9
|
+
@result = matcher.match(exception)
|
|
10
|
+
ensure
|
|
11
|
+
@message = message
|
|
12
|
+
@receiver = receiver
|
|
13
|
+
@arguments = arguments
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def passed?
|
|
17
|
+
@result
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
data/lib/speq/version.rb
CHANGED
data/lib/speq.rb
CHANGED
|
@@ -1,13 +1,29 @@
|
|
|
1
1
|
require 'speq/version'
|
|
2
2
|
require 'speq/test'
|
|
3
|
-
require 'speq/
|
|
3
|
+
require 'speq/matcher'
|
|
4
|
+
require 'speq/report'
|
|
5
|
+
require 'speq/unit'
|
|
4
6
|
require 'speq/fake'
|
|
5
7
|
require 'speq/cli'
|
|
6
8
|
|
|
7
9
|
module Speq
|
|
8
10
|
module_function
|
|
9
11
|
|
|
10
|
-
def
|
|
11
|
-
|
|
12
|
+
def method_missing(method, *args)
|
|
13
|
+
if Matcher.respond_to?(method)
|
|
14
|
+
Matcher.send(method, *args)
|
|
15
|
+
else
|
|
16
|
+
super
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def unit_test(message, **kwargs)
|
|
21
|
+
matcher_method = kwargs.keys.find { |key| Matcher.respond_to?(key) }
|
|
22
|
+
matcher = send(matcher_method, kwargs[matcher_method])
|
|
23
|
+
|
|
24
|
+
unit = Unit.new(message, kwargs[:on], kwargs[:with], matcher)
|
|
25
|
+
Report.new([unit]).print_report
|
|
26
|
+
|
|
27
|
+
unit.passed?
|
|
12
28
|
end
|
|
13
29
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: speq
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- zaniar moradian
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2018-10-
|
|
11
|
+
date: 2018-10-31 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -86,8 +86,10 @@ files:
|
|
|
86
86
|
- lib/speq.rb
|
|
87
87
|
- lib/speq/cli.rb
|
|
88
88
|
- lib/speq/fake.rb
|
|
89
|
-
- lib/speq/
|
|
89
|
+
- lib/speq/matcher.rb
|
|
90
|
+
- lib/speq/report.rb
|
|
90
91
|
- lib/speq/test.rb
|
|
92
|
+
- lib/speq/unit.rb
|
|
91
93
|
- lib/speq/version.rb
|
|
92
94
|
- speq.gemspec
|
|
93
95
|
homepage: https://github.com/znrm/speq
|
data/lib/speq/match.rb
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# The Match class includes a variety of matchers
|
|
2
|
-
module Speq
|
|
3
|
-
class Match
|
|
4
|
-
attr_reader :actual, :expected, :passed, :args
|
|
5
|
-
|
|
6
|
-
def initialize(actual, match_sym, args, expected = nil)
|
|
7
|
-
@actual = actual
|
|
8
|
-
@expected = expected
|
|
9
|
-
@passed = false
|
|
10
|
-
@args = args
|
|
11
|
-
|
|
12
|
-
evaluate_match(match_sym)
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def evaluate_match(match_sym)
|
|
16
|
-
case match_sym
|
|
17
|
-
when :eql?, :equal?
|
|
18
|
-
@passed = actual.send(match_sym, expected)
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def passed?
|
|
23
|
-
@passed
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|