elliottcable-speck 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.
- data/.manifest +8 -0
- data/README.markdown +3 -0
- data/Rakefile.rb +89 -0
- data/lib/speck.rake +27 -0
- data/lib/speck.rb +83 -0
- data/lib/speck/check.rb +70 -0
- data/lib/speck/core_ext.rb +1 -0
- data/lib/speck/core_ext/check_mixins.rb +74 -0
- data/speck.gemspec +34 -0
- metadata +85 -0
data/.manifest
ADDED
data/README.markdown
ADDED
data/Rakefile.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
($:.unshift File.expand_path(File.join( File.dirname(__FILE__), 'lib' ))).uniq!
|
2
|
+
require 'speck'
|
3
|
+
|
4
|
+
# =======================
|
5
|
+
# = Gem packaging tasks =
|
6
|
+
# =======================
|
7
|
+
begin
|
8
|
+
require 'echoe'
|
9
|
+
|
10
|
+
task :install => :'package:install'
|
11
|
+
task :package => :'package:package'
|
12
|
+
task :manifest => :'package:manifest'
|
13
|
+
namespace :package do
|
14
|
+
Echoe.new('speck', Speck::Version) do |g|
|
15
|
+
g.project = 'speck'
|
16
|
+
g.author = ['elliottcable']
|
17
|
+
g.email = ['Speck@elliottcable.com']
|
18
|
+
g.summary = "Supah-light 'n sexy specking!"
|
19
|
+
g.url = 'http://github.com/elliottcable/speck'
|
20
|
+
g.runtime_dependencies = []
|
21
|
+
g.development_dependencies = ['echoe >= 3.0.2']
|
22
|
+
g.manifest_name = '.manifest'
|
23
|
+
g.retain_gemspec = true
|
24
|
+
g.rakefile_name = 'Rakefile.rb'
|
25
|
+
g.ignore_pattern = /^\.git\/|^meta\/|\.gemspec/
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
rescue LoadError
|
30
|
+
desc 'You need the `echoe` gem to package Speck'
|
31
|
+
task :package
|
32
|
+
end
|
33
|
+
|
34
|
+
# ===============
|
35
|
+
# = Speck tasks =
|
36
|
+
# ===============
|
37
|
+
begin
|
38
|
+
# require 'speck'
|
39
|
+
|
40
|
+
task :default => :'speck:run'
|
41
|
+
task :speck => :'speck:run'
|
42
|
+
namespace :speck do
|
43
|
+
load 'speck.rake'
|
44
|
+
end
|
45
|
+
|
46
|
+
rescue LoadError
|
47
|
+
desc 'You need the `speck` gem to run specks'
|
48
|
+
task :speck
|
49
|
+
end
|
50
|
+
|
51
|
+
# =======================
|
52
|
+
# = Documentation tasks =
|
53
|
+
# =======================
|
54
|
+
begin
|
55
|
+
require 'yard'
|
56
|
+
require 'yard/rake/yardoc_task'
|
57
|
+
|
58
|
+
task :documentation => :'documentation:generate'
|
59
|
+
namespace :documentation do
|
60
|
+
YARD::Rake::YardocTask.new :generate do |t|
|
61
|
+
t.files = ['lib/**/*.rb']
|
62
|
+
t.options = ['--output-dir', File.join('meta', 'documentation'),
|
63
|
+
'--readme', 'README.markdown',
|
64
|
+
'--markup', 'markdown', '--markup-provider', 'maruku']
|
65
|
+
end
|
66
|
+
|
67
|
+
YARD::Rake::YardocTask.new :dotyardoc do |t|
|
68
|
+
t.files = ['lib/**/*.rb']
|
69
|
+
t.options = ['--no-output',
|
70
|
+
'--readme', 'README.markdown',
|
71
|
+
'--markup', 'markdown', '--markup-provider', 'maruku']
|
72
|
+
end
|
73
|
+
|
74
|
+
task :open do
|
75
|
+
system 'open ' + File.join('meta', 'documentation', 'index.html') if RUBY_PLATFORM['darwin']
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
rescue LoadError
|
80
|
+
desc 'You need the `yard` and `maruku` gems to generate documentation'
|
81
|
+
task :documentation
|
82
|
+
end
|
83
|
+
|
84
|
+
desc 'Check everything over before commiting'
|
85
|
+
task :aok => [:'documentation:generate', :'documentation:open',
|
86
|
+
:'package:manifest',
|
87
|
+
:'speck:run']
|
88
|
+
|
89
|
+
task :ci => [:'documentation:generate', :'speck:run']
|
data/lib/speck.rake
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
def ansi text, code
|
2
|
+
"\033[#{code}#{text}\033[0m"
|
3
|
+
end
|
4
|
+
|
5
|
+
def red text; ansi(text, "31m") end
|
6
|
+
def green text; ansi(text, "32m") end
|
7
|
+
|
8
|
+
desc 'Recursively runs all root specks'
|
9
|
+
task :run do
|
10
|
+
roots = Speck::specks.select {|s| s.parent == nil }
|
11
|
+
|
12
|
+
playback = lambda do |speck|
|
13
|
+
speck.execute
|
14
|
+
speck.checks.each do |check|
|
15
|
+
begin
|
16
|
+
check.execute
|
17
|
+
puts check.description.ljust(72) + green(" # => " + check.status.inspect)
|
18
|
+
rescue Speck::Exception::CheckFailed
|
19
|
+
# TODO: Print a description of why the error failed, what was expected
|
20
|
+
# and what was actually received.
|
21
|
+
puts check.description.ljust(72) + red(" # ! " + check.status.inspect)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
speck.children.each &playback
|
25
|
+
end
|
26
|
+
roots.each &playback
|
27
|
+
end
|
data/lib/speck.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
# All library files are required at the bottom, because in this unique case we
|
2
|
+
# need `Speck` defined before we can use it to `Speck` anything.
|
3
|
+
|
4
|
+
class Speck
|
5
|
+
Version = 0
|
6
|
+
|
7
|
+
class <<self
|
8
|
+
|
9
|
+
##
|
10
|
+
# All defined Specks.
|
11
|
+
attr_accessor :specks
|
12
|
+
def specks; @specks ||= Array.new; end
|
13
|
+
|
14
|
+
##
|
15
|
+
# The current stack of nested `Speck`s.
|
16
|
+
#
|
17
|
+
# @see #current
|
18
|
+
attr_accessor :stack
|
19
|
+
def stack; @stack ||= Array.new; end
|
20
|
+
|
21
|
+
##
|
22
|
+
# Returns the currently active `Speck`.
|
23
|
+
#
|
24
|
+
# When your `Speck`s are being run, there is a `stack` of `Speck` objects,
|
25
|
+
# consisting of the current nesting list of `Speck`s being run.
|
26
|
+
def current
|
27
|
+
stack.last
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# The block to be executed
|
33
|
+
attr_accessor :speck
|
34
|
+
|
35
|
+
##
|
36
|
+
# Child `Speck`s
|
37
|
+
attr_accessor :children
|
38
|
+
def children; @children ||= Array.new; end
|
39
|
+
|
40
|
+
##
|
41
|
+
# Parent `Speck`
|
42
|
+
attr_accessor :parent
|
43
|
+
|
44
|
+
##
|
45
|
+
# The checks involved in the current `Speck`.
|
46
|
+
attr_accessor :checks
|
47
|
+
def checks; @checks ||= Array.new; end
|
48
|
+
|
49
|
+
##
|
50
|
+
# Creates a new `Speck`.
|
51
|
+
def initialize *targets, &speck
|
52
|
+
@speck = speck
|
53
|
+
@parent = Speck.current
|
54
|
+
|
55
|
+
@parent.children << self if @parent
|
56
|
+
Speck.specks << self
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# Executes the `Speck`.
|
61
|
+
def execute
|
62
|
+
Speck::Mixins::mixin!
|
63
|
+
|
64
|
+
Speck.stack << self
|
65
|
+
speck.call
|
66
|
+
Speck.stack.pop
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
##
|
71
|
+
# A root class, and container class, for `Speck` exceptions.
|
72
|
+
class Exception < StandardError
|
73
|
+
# Raised any time checks are run outside of a `Speck`
|
74
|
+
NoEnvironment = Class.new self
|
75
|
+
|
76
|
+
# Raised when a `Check` fails
|
77
|
+
CheckFailed = Class.new self
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
require 'speck/core_ext'
|
83
|
+
require 'speck/check'
|
data/lib/speck/check.rb
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
class Speck
|
2
|
+
##
|
3
|
+
# Represents a queued thing to be checked of some sort, within a `Speck`.
|
4
|
+
class Check
|
5
|
+
##
|
6
|
+
# A block to be executed.
|
7
|
+
attr_accessor :lambda
|
8
|
+
|
9
|
+
##
|
10
|
+
# A description for the check. Usually a relevant line of code.
|
11
|
+
attr_accessor :description
|
12
|
+
|
13
|
+
##
|
14
|
+
# The status of the `Check`. `nil` indicates the `Check` hasn’t been
|
15
|
+
# executed, and `true` or `false` indicate the success of the latest
|
16
|
+
# execution.
|
17
|
+
attr_accessor :status
|
18
|
+
|
19
|
+
##
|
20
|
+
# Checks the truthiness of this `Check`’s `status`.
|
21
|
+
def success?
|
22
|
+
!!status
|
23
|
+
end
|
24
|
+
Speck.new :status do
|
25
|
+
object = Object.new
|
26
|
+
Check.new(->{true}).execute.status
|
27
|
+
.check {|s| s == true}
|
28
|
+
Check.new(->{object}).execute.status
|
29
|
+
.check {|s| s == object}
|
30
|
+
|
31
|
+
Check.new(->{true}).execute.success?.check
|
32
|
+
Check.new(->{object}).execute.success?.check
|
33
|
+
|
34
|
+
Check.new(->{false}).tap {|c| c.execute rescue nil } .status
|
35
|
+
.check {|s| s == false}
|
36
|
+
Check.new(->{nil}).tap {|c| c.execute rescue nil } .status
|
37
|
+
.check {|s| s == false}
|
38
|
+
end
|
39
|
+
|
40
|
+
def initialize(lambda, description = "<undocumented>")
|
41
|
+
@lambda = lambda
|
42
|
+
@description = description
|
43
|
+
end
|
44
|
+
Speck.new Check, :new do
|
45
|
+
my_lambda = ->{}
|
46
|
+
Check.new(my_lambda).lambda.check {|l| l == my_lambda }
|
47
|
+
|
48
|
+
Check.new(->{}, "WOO! BLANK CHECK!").description
|
49
|
+
.check {|d| d == "WOO! BLANK CHECK!" }
|
50
|
+
end
|
51
|
+
|
52
|
+
##
|
53
|
+
# Executes this `Check`, raising an error if the block returns nil or
|
54
|
+
# false.
|
55
|
+
def execute
|
56
|
+
@lambda.call.tap {|result| @status = result ? result : false }
|
57
|
+
raise Exception::CheckFailed unless success?
|
58
|
+
self
|
59
|
+
end
|
60
|
+
Speck.new :execute do
|
61
|
+
Check.new(->{true}).execute.check {|c| c.success? }
|
62
|
+
->{ Check.new(->{false}).execute }
|
63
|
+
.check_exception Speck::Exception::CheckFailed
|
64
|
+
|
65
|
+
Check.new(->{"value"}).execute.check
|
66
|
+
Check.new(->{2 * 2}).execute.check {|value| value == 4 }
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'speck/core_ext/check_mixins'
|
@@ -0,0 +1,74 @@
|
|
1
|
+
class Speck
|
2
|
+
##
|
3
|
+
# These methods, when mixed into their respective classes, provide some
|
4
|
+
# conveniences when it comes to creating `Check`s.
|
5
|
+
module Mixins
|
6
|
+
|
7
|
+
##
|
8
|
+
# This method will quickly mix all of our `Mixins` into their respective
|
9
|
+
# targets.
|
10
|
+
def self.mixin!
|
11
|
+
Speck::Mixins.constants
|
12
|
+
.map {|mod| Speck::Mixins.const_get(mod) }
|
13
|
+
.each {|mod| mod::Target.send :include, mod }
|
14
|
+
end
|
15
|
+
|
16
|
+
module Object; Target = ::Object
|
17
|
+
##
|
18
|
+
# This method is responsible for running some sort of test on the
|
19
|
+
# receiver.
|
20
|
+
#
|
21
|
+
# It expects a block (returning true or false) to be passed. The block
|
22
|
+
# will be passed the receiver, so you can run comparators on it, or
|
23
|
+
# whatever else you like.
|
24
|
+
#
|
25
|
+
# `#check` can also be called without block on truthy objects (`true`,
|
26
|
+
# `false`, or `nil`, any other object will be treated as `true`)
|
27
|
+
def check &check
|
28
|
+
check = ->(_){self} unless block_given?
|
29
|
+
|
30
|
+
# TODO: Should we allow specks in the root environment? Could be useful
|
31
|
+
# for quick checks…
|
32
|
+
raise Exception::NoEnvironment unless Speck.current
|
33
|
+
|
34
|
+
file, line, _ = Kernel::caller.first.split(':')
|
35
|
+
source = File.open(file).readlines[line.to_i - 1]
|
36
|
+
source.strip!
|
37
|
+
source = source.partition(".check").first
|
38
|
+
# TODO: Get rid of the "(…)" around the resulting string.
|
39
|
+
|
40
|
+
Speck::Check.new(->(){ check[self] }, source)
|
41
|
+
.tap {|check| Speck.current.checks << check }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module Proc; Target = ::Proc
|
46
|
+
|
47
|
+
##
|
48
|
+
# This method is responsible for checking that a particular proc raises
|
49
|
+
# a particular exception type when called.
|
50
|
+
def check_exception exception = Exception
|
51
|
+
# TODO: Should we allow specks in the root environment? Could be useful
|
52
|
+
# for quick checks…
|
53
|
+
raise Exception::NoEnvironment unless Speck.current
|
54
|
+
|
55
|
+
file, line, _ = Kernel::caller.first.split(':')
|
56
|
+
source = File.open(file).readlines[line.to_i - 1]
|
57
|
+
source.strip!
|
58
|
+
source = source.partition(".check_exception").first
|
59
|
+
# TODO: Get rid of the "->{…}" around the resulting string.
|
60
|
+
|
61
|
+
Speck.current.checks <<
|
62
|
+
Speck::Check.new(->(){
|
63
|
+
begin
|
64
|
+
self.call
|
65
|
+
rescue exception
|
66
|
+
return true
|
67
|
+
end
|
68
|
+
return false
|
69
|
+
}, source)
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/speck.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{speck}
|
5
|
+
s.version = "0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["elliottcable"]
|
9
|
+
s.date = %q{2009-08-03}
|
10
|
+
s.description = %q{Supah-light 'n sexy specking!}
|
11
|
+
s.email = ["Speck@elliottcable.com"]
|
12
|
+
s.extra_rdoc_files = ["lib/speck/check.rb", "lib/speck/core_ext/check_mixins.rb", "lib/speck/core_ext.rb", "lib/speck.rake", "lib/speck.rb", "README.markdown"]
|
13
|
+
s.files = ["lib/speck/check.rb", "lib/speck/core_ext/check_mixins.rb", "lib/speck/core_ext.rb", "lib/speck.rake", "lib/speck.rb", "Rakefile.rb", "README.markdown", ".manifest", "speck.gemspec"]
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.homepage = %q{http://github.com/elliottcable/speck}
|
16
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Speck", "--main", "README.markdown"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = %q{speck}
|
19
|
+
s.rubygems_version = %q{1.3.1}
|
20
|
+
s.summary = %q{Supah-light 'n sexy specking!}
|
21
|
+
|
22
|
+
if s.respond_to? :specification_version then
|
23
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
24
|
+
s.specification_version = 2
|
25
|
+
|
26
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
27
|
+
s.add_development_dependency(%q<echoe>, [">= 0", "= 3.0.2"])
|
28
|
+
else
|
29
|
+
s.add_dependency(%q<echoe>, [">= 0", "= 3.0.2"])
|
30
|
+
end
|
31
|
+
else
|
32
|
+
s.add_dependency(%q<echoe>, [">= 0", "= 3.0.2"])
|
33
|
+
end
|
34
|
+
end
|
metadata
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: elliottcable-speck
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- elliottcable
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-08-03 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: echoe
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
- - "="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 3.0.2
|
27
|
+
version:
|
28
|
+
description: Supah-light 'n sexy specking!
|
29
|
+
email:
|
30
|
+
- Speck@elliottcable.com
|
31
|
+
executables: []
|
32
|
+
|
33
|
+
extensions: []
|
34
|
+
|
35
|
+
extra_rdoc_files:
|
36
|
+
- lib/speck/check.rb
|
37
|
+
- lib/speck/core_ext/check_mixins.rb
|
38
|
+
- lib/speck/core_ext.rb
|
39
|
+
- lib/speck.rake
|
40
|
+
- lib/speck.rb
|
41
|
+
- README.markdown
|
42
|
+
files:
|
43
|
+
- lib/speck/check.rb
|
44
|
+
- lib/speck/core_ext/check_mixins.rb
|
45
|
+
- lib/speck/core_ext.rb
|
46
|
+
- lib/speck.rake
|
47
|
+
- lib/speck.rb
|
48
|
+
- Rakefile.rb
|
49
|
+
- README.markdown
|
50
|
+
- .manifest
|
51
|
+
- speck.gemspec
|
52
|
+
has_rdoc: true
|
53
|
+
homepage: http://github.com/elliottcable/speck
|
54
|
+
licenses:
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options:
|
57
|
+
- --line-numbers
|
58
|
+
- --inline-source
|
59
|
+
- --title
|
60
|
+
- Speck
|
61
|
+
- --main
|
62
|
+
- README.markdown
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: "0"
|
70
|
+
version:
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: "1.2"
|
76
|
+
version:
|
77
|
+
requirements: []
|
78
|
+
|
79
|
+
rubyforge_project: speck
|
80
|
+
rubygems_version: 1.3.5
|
81
|
+
signing_key:
|
82
|
+
specification_version: 2
|
83
|
+
summary: Supah-light 'n sexy specking!
|
84
|
+
test_files: []
|
85
|
+
|