spectus 1.0.0.pre

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.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +14 -0
  4. data/.travis.yml +6 -0
  5. data/.yardopts +1 -0
  6. data/Gemfile +2 -0
  7. data/LICENSE.md +22 -0
  8. data/README.md +239 -0
  9. data/Rakefile +18 -0
  10. data/VERSION.semver +1 -0
  11. data/lib/spectus.rb +6 -0
  12. data/lib/spectus/dsl.rb +14 -0
  13. data/lib/spectus/expectation_target.rb +27 -0
  14. data/lib/spectus/matcher.rb +35 -0
  15. data/lib/spectus/matcher/capture_stderr.rb +31 -0
  16. data/lib/spectus/matcher/capture_stdout.rb +31 -0
  17. data/lib/spectus/matcher/eql.rb +21 -0
  18. data/lib/spectus/matcher/equal.rb +21 -0
  19. data/lib/spectus/matcher/match.rb +21 -0
  20. data/lib/spectus/matcher/raise_exception.rb +27 -0
  21. data/lib/spectus/reporter.rb +45 -0
  22. data/lib/spectus/version.rb +9 -0
  23. data/spectus.gemspec +20 -0
  24. data/test/helper_test.rb +4 -0
  25. data/test/spectus/helper_test.rb +1 -0
  26. data/test/spectus/matcher/built_in/helper_test.rb +1 -0
  27. data/test/spectus/matcher/built_in/test_capture_stderr.rb +21 -0
  28. data/test/spectus/matcher/built_in/test_capture_stdout.rb +21 -0
  29. data/test/spectus/matcher/built_in/test_eql.rb +21 -0
  30. data/test/spectus/matcher/built_in/test_equal.rb +21 -0
  31. data/test/spectus/matcher/built_in/test_match.rb +21 -0
  32. data/test/spectus/matcher/built_in/test_raise_exception.rb +21 -0
  33. data/test/spectus/matcher/custom/be_prime/helper_test.rb +13 -0
  34. data/test/spectus/matcher/custom/be_prime/test_be_prime.rb +21 -0
  35. data/test/spectus/matcher/custom/be_the_answer/helper_test.rb +11 -0
  36. data/test/spectus/matcher/custom/be_the_answer/test_be_the_answer.rb +21 -0
  37. data/test/spectus/matcher/custom/helper_test.rb +1 -0
  38. data/test/spectus/matcher/custom/start_with/helper_test.rb +15 -0
  39. data/test/spectus/matcher/custom/start_with/test_start_with.rb +21 -0
  40. data/test/spectus/matcher/helper_test.rb +1 -0
  41. data/test/spectus/test_dsl.rb +9 -0
  42. data/test/spectus/test_expectation_target.rb +17 -0
  43. data/test/spectus/test_matcher.rb +34 -0
  44. data/test/spectus/test_reporter.rb +97 -0
  45. data/test/spectus/test_version.rb +11 -0
  46. data/test/support.rb +3 -0
  47. data/test/support/coverage.rb +3 -0
  48. data/test/support/env.rb +4 -0
  49. data/test/support/presenter.rb +23 -0
  50. metadata +175 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 96fa46cd60fb62f1704a8dbf1dbe3b5519b1981f
4
+ data.tar.gz: 5ade56a1a4865de27fe71781c3fd21853d94dd8a
5
+ SHA512:
6
+ metadata.gz: 2ba1d3381e9c4f408e6f188c204582b11752119c8ee5fbca13e306ecfe93142cb4d7531bf2711ce768d9c38801b75228506de0a4e18edd8e4462531ecee2699f
7
+ data.tar.gz: db138bad384985792d3c480403a7881596a7334feca59618dd9146a265f1d4725fcd43bf20c331bb9a49be59b5276f82c149534147b10339d26f667d129146fa
data/.coveralls.yml ADDED
@@ -0,0 +1 @@
1
+ service_name: travis-ci
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ script: 'bundle exec rake test:coverage'
3
+ rvm:
4
+ - 2.0.0
5
+ - 2.1.3
6
+ - ruby-head
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ - README.md
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE.md ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Cyril Wack
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,239 @@
1
+ # Spectus
2
+
3
+ [![Build Status](https://travis-ci.org/cyril/spectus.rb.svg?branch=master)](https://travis-ci.org/cyril/spectus.rb)
4
+ [![Coverage Status](http://img.shields.io/coveralls/cyril/spectus.rb.svg?branch=master)](https://coveralls.io/r/cyril/spectus.rb)
5
+ [![Code Climate](http://img.shields.io/codeclimate/github/cyril/spectus.rb.svg)](https://codeclimate.com/github/cyril/spectus.rb)
6
+ [![Dependency Status](https://gemnasium.com/cyril/spectus.rb.svg)](https://gemnasium.com/cyril/spectus.rb)
7
+ [![Gem Version](http://img.shields.io/gem/v/spectus.svg)](https://rubygems.org/gems/spectus)
8
+ [![Inline docs](http://inch-ci.org/github/cyril/spectus.rb.svg)](http://inch-ci.org/github/cyril/spectus.rb)
9
+ [![Documentation](http://img.shields.io/:yard-docs-38c800.svg)](http://rubydoc.info/gems/spectus/frames)
10
+ [![License](http://img.shields.io/:license-MIT-38c800.svg)](http://cyril.mit-license.org/)
11
+
12
+ > An expectation library with some built-in matchers for Ruby.
13
+
14
+ ## Contact
15
+
16
+ * Home page: https://github.com/cyril/spectus.rb
17
+ * Bugs/issues: https://github.com/cyril/spectus.rb/issues
18
+ * Support: https://stackoverflow.com/questions/tagged/spectus-ruby
19
+
20
+ ## Rubies
21
+
22
+ __Spectus__ is supported by Ruby (MRI) 2+.
23
+
24
+ ## Installation
25
+
26
+ Add this line to your application's Gemfile:
27
+
28
+ ```ruby
29
+ gem 'spectus'
30
+ ```
31
+
32
+ And then execute:
33
+
34
+ ```shell
35
+ $ bundle
36
+ ```
37
+
38
+ Or install it yourself as:
39
+
40
+ ```shell
41
+ $ gem install spectus
42
+ ```
43
+
44
+ ## Why would I want this library?
45
+
46
+ * It's ~200 lines of fast and KISS code.
47
+ * Atomic state transitions, immutable objects, thread-safe.
48
+ * A generic, consistent DSL for assertions.
49
+
50
+ ## Usage
51
+
52
+ ```ruby
53
+ class Duck
54
+ def walks
55
+ "Klop klop!"
56
+ end
57
+
58
+ def swims
59
+ "Swoosh..."
60
+ end
61
+
62
+ def quacks
63
+ puts "Quaaaaaack!"
64
+ end
65
+ end
66
+
67
+ @bird = Duck.new
68
+ ```
69
+
70
+ > When I see a #<Duck:0x007f96b285d6d0> that ...
71
+
72
+ ```ruby
73
+ require 'spectus'
74
+ extend Spectus::DSL
75
+
76
+ expectation_1 = expect { @bird.walks }.to eql: "Klop klop!"
77
+ expectation_2 = expect { @bird.swims }.to eql: "Swoosh..."
78
+ expectation_3 = expect { @bird.quacks }.to capture_stdout: "Quaaaaaack!\n"
79
+ expectation_4 = expect { @bird.speaks }.to raise_exception: NoMethodError
80
+
81
+ case (expectation_1.pass? &&
82
+ expectation_2.pass? &&
83
+ expectation_3.pass? &&
84
+ expectation_4.pass?)
85
+ when true then puts "I call that #{@bird} a duck."
86
+ else warn 'WAT?'
87
+ end
88
+ ```
89
+
90
+ > I call that #<Duck:0x007f96b285d6d0> a duck.
91
+
92
+ ## Built-in matchers
93
+
94
+ ### Standard error
95
+
96
+ ```ruby
97
+ expect { warn 'foo' }.to capture_stderr: "foo\n"
98
+ ```
99
+
100
+ ### Standard output
101
+
102
+ ```ruby
103
+ expect { puts 'foo' }.to capture_stdout: "foo\n"
104
+ ```
105
+
106
+ ### Equivalence
107
+
108
+ ```ruby
109
+ expect { 'foo' }.to eql: 'foo'
110
+ ```
111
+
112
+ ### Identity
113
+
114
+ ```ruby
115
+ expect { :foo }.to equal: :foo
116
+ ```
117
+
118
+ ### Regular expressions
119
+
120
+ ```ruby
121
+ expect { 'foo' }.to({match: /^foo$/})
122
+ ```
123
+
124
+ ### Expecting errors
125
+
126
+ ```ruby
127
+ expect { Foo }.to raise_exception: NameError
128
+ ```
129
+
130
+ ## Custom matchers
131
+
132
+ Custom matchers can also be defined for expressing expectations.
133
+
134
+ ### Be prime
135
+
136
+ The following expression...
137
+
138
+ ```ruby
139
+ require 'prime'
140
+ expect { Prime.prime? 42 }.to equal: false
141
+ ```
142
+
143
+ ...could be refactored into:
144
+
145
+ ```ruby
146
+ expect { 42 }.not_to :be_prime
147
+ ```
148
+
149
+ It can be done with this custom matcher:
150
+
151
+ ```ruby
152
+ require 'prime'
153
+
154
+ module Spectus
155
+ module Matcher
156
+ class BePrime
157
+ def matches?
158
+ Prime.prime? yield
159
+ end
160
+ end
161
+ end
162
+ end
163
+ ```
164
+
165
+ ### Be the answer
166
+
167
+ The following expression...
168
+
169
+ ```ruby
170
+ expect { 42 }.to equal: 42
171
+ ```
172
+
173
+ ...could be refactored into:
174
+
175
+ ```ruby
176
+ expect { 42 }.to :be_the_answer
177
+ ```
178
+
179
+ It can be done with this custom matcher:
180
+
181
+ ```ruby
182
+ module Spectus
183
+ module Matcher
184
+ class BeTheAnswer
185
+ def matches?
186
+ 42.equal? yield
187
+ end
188
+ end
189
+ end
190
+ end
191
+ ```
192
+
193
+ ### Start with
194
+
195
+ The following expression...
196
+
197
+ ```ruby
198
+ expect { 'foobar' }.to match: /^foo/
199
+ ```
200
+
201
+ ...could be refactored into:
202
+
203
+ ```ruby
204
+ expect { 'foobar' }.to start_with: 'foo'
205
+ ```
206
+
207
+ It can be done with this custom matcher:
208
+
209
+ ```ruby
210
+ module Spectus
211
+ module Matcher
212
+ class StartWith
213
+ def initialize expected
214
+ @expected = expected
215
+ end
216
+
217
+ def matches?
218
+ !Regexp.new("^#{@expected}").match(yield).nil?
219
+ end
220
+ end
221
+ end
222
+ end
223
+ ```
224
+
225
+ ## Contributing
226
+
227
+ 1. [Fork it](https://github.com/cyril/spectus.rb/fork)
228
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
229
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
230
+ 4. Push to the branch (`git push origin my-new-feature`)
231
+ 5. Create a new Pull Request
232
+
233
+ ## Versioning
234
+
235
+ __Spectus__ follows [Semantic Versioning 2.0](http://semver.org/)
236
+
237
+ ## Copyright
238
+
239
+ &copy; [Cyril Wack](https://plus.google.com/+CyrilWack?rel=author)
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.pattern = File.join 'test', '**', 'test_*.rb'
6
+ t.verbose = true
7
+ t.warning = true
8
+ end
9
+
10
+ namespace :test do
11
+ task :coverage do
12
+ ENV['COVERAGE'] = 'true'
13
+ Rake::Task['test'].invoke
14
+ end
15
+ end
16
+
17
+ task(:doc_stats) { ruby '-S yard stats' }
18
+ task default: [:test, :doc_stats]
data/VERSION.semver ADDED
@@ -0,0 +1 @@
1
+ 1.0.0.pre
data/lib/spectus.rb ADDED
@@ -0,0 +1,6 @@
1
+ require_relative File.join 'spectus', 'dsl'
2
+ require_relative File.join 'spectus', 'version'
3
+
4
+ # Namespace for the Spectus library.
5
+ module Spectus
6
+ end
@@ -0,0 +1,14 @@
1
+ require_relative 'expectation_target'
2
+
3
+ module Spectus
4
+
5
+ # Expectation's domain-specific language.
6
+ module DSL
7
+
8
+ # Expectations are built with this method which takes a value, called the
9
+ # actual.
10
+ def expect &input
11
+ ExpectationTarget.new(&input)
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,27 @@
1
+ require_relative 'matcher'
2
+
3
+ module Spectus
4
+
5
+ # Wraps the target of an expectation.
6
+ #
7
+ # @example
8
+ # expect { do_something } # => ExpectationTarget wrapping the block
9
+ class ExpectationTarget
10
+ # @api private
11
+ def initialize &actual
12
+ @actual = actual
13
+
14
+ freeze
15
+ end
16
+
17
+ # To evaluate to a positive assertion.
18
+ def to definition
19
+ Matcher.eval false, definition, &@actual
20
+ end
21
+
22
+ # To evaluate to a negative assertion.
23
+ def not_to definition
24
+ Matcher.eval true, definition, &@actual
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,35 @@
1
+ require_relative 'reporter'
2
+
3
+ module Spectus
4
+
5
+ # This module provides matchers to define expectations.
6
+ module Matcher
7
+
8
+ # Evaluate the expectation, and report the result.
9
+ def self.eval negated, definition, &actual
10
+ params = Array(definition).flatten(1)
11
+ name = params.first
12
+ expected_args = params[1..-1]
13
+ matcher = Matcher.get(name).new(*expected_args)
14
+
15
+ Reporter.new negated, name, *expected_args, begin
16
+ negated ^ matcher.matches?(&actual)
17
+ rescue => e
18
+ e
19
+ end
20
+ end
21
+
22
+ # Get the class of a matcher from its symbol.
23
+ #
24
+ # @example
25
+ #
26
+ # Matcher.get(:eql) # => Eql
27
+ def self.get name
28
+ const_get name.to_s.split('_').map {|w| w.capitalize }.join.to_sym
29
+ end
30
+ end
31
+ end
32
+
33
+ Dir[File.join File.dirname(__FILE__), 'matcher', '*.rb'].each do |filename|
34
+ require_relative filename
35
+ end
@@ -0,0 +1,31 @@
1
+ require 'stringio'
2
+
3
+ module Spectus
4
+ module Matcher
5
+
6
+ # @api private
7
+ # Provides the implementation for `capture_stderr`.
8
+ class CaptureStderr
9
+
10
+ # @api private
11
+ def initialize expected
12
+ @expected = expected
13
+
14
+ freeze
15
+ end
16
+
17
+ # @return [Boolean] Comparison between actual and expected values.
18
+ def matches?
19
+ begin
20
+ orig_std = $stderr
21
+ $stderr = StringIO.new
22
+
23
+ yield
24
+ $stderr.string.eql? @expected
25
+ ensure
26
+ $stderr = orig_std
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end