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 ADDED
@@ -0,0 +1,8 @@
1
+ lib/speck/check.rb
2
+ lib/speck/core_ext/check_mixins.rb
3
+ lib/speck/core_ext.rb
4
+ lib/speck.rake
5
+ lib/speck.rb
6
+ Rakefile.rb
7
+ README.markdown
8
+ .manifest
data/README.markdown ADDED
@@ -0,0 +1,3 @@
1
+ Speck
2
+ =====
3
+ Specs… supah–light.
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'
@@ -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
+