elliottcable-speck 0

Sign up to get free protection for your applications and to get access to all the features.
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
+