proof 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,26 @@
1
+ module Proof
2
+ module CoreExt
3
+ module Object
4
+ module Methods
5
+ extend self
6
+
7
+ def define_prove
8
+ ::Object.class_eval do
9
+ def prove(&blk)
10
+ obj_under_test = self
11
+ Proof::Extend.into obj_under_test
12
+ result = Proof::Execution.run Description.current, obj_under_test, blk
13
+ result.write
14
+ end
15
+ end
16
+ end
17
+
18
+ def undefine_prove
19
+ ::Object.class_eval do
20
+ undef :prove
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1 @@
1
+ require 'proof/core_ext/object'
@@ -0,0 +1,7 @@
1
+ module Proof
2
+ class Description
3
+ include Single
4
+
5
+ attr_accessor :current
6
+ end
7
+ end
@@ -0,0 +1,37 @@
1
+ module Proof
2
+ class Error
3
+ include Initializer
4
+
5
+ initializer :error
6
+
7
+
8
+ def self.output(error)
9
+ instance = new error
10
+ instance.output
11
+ end
12
+
13
+ def backtrace
14
+ @backtrace ||= @error.backtrace.extend Backtrace
15
+ end
16
+
17
+ def output
18
+ backtrace.remove_proof_framework_frames!
19
+ Output.error error_message
20
+ Output.backtrace " #{backtrace.join("\n ")}"
21
+ end
22
+
23
+ def error_message
24
+ "(#{error.class}) \"#{error.message}\" at #{backtrace.first_frame}"
25
+ end
26
+
27
+ module Backtrace
28
+ def first_frame
29
+ first.gsub(/.*\/proofs\/proof\/(.*\.rb.*)/,'\1')
30
+ end
31
+
32
+ def remove_proof_framework_frames!
33
+ reject! {|backtrace_line| backtrace_line =~ /proof\/lib\/proof/ }
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,23 @@
1
+ module Proof
2
+ class Execution
3
+ include Initializer
4
+
5
+ initializer :description, :obj_under_test, :blk
6
+
7
+ def self.run(description, obj_under_test, blk)
8
+ instance = new description, obj_under_test, blk
9
+ instance.run
10
+ end
11
+
12
+ def run
13
+ error = nil
14
+ begin
15
+ result = obj_under_test.instance_eval &blk
16
+ status = result ? :pass : :fail
17
+ rescue => error
18
+ status = :error
19
+ end
20
+ Proof::Result.new description, status, error
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,45 @@
1
+ module Proof
2
+ class Extend
3
+ include Initializer
4
+
5
+ initializer :obj_under_test
6
+
7
+ def self.into(obj_under_test)
8
+ instance = new obj_under_test
9
+ instance.extend_obj
10
+ end
11
+
12
+ def mod
13
+ @mod ||= ([Module, Class].include?(obj_under_test.class) ? obj_under_test : obj_under_test.class)
14
+ end
15
+
16
+ def extend_obj
17
+ if extension.nil?
18
+ Output.details "#{mod.name} not extended by #{extension_name}"
19
+ return obj_under_test
20
+ end
21
+
22
+ Output.details "Extending #{extension_name} into #{mod.name}"
23
+ obj_under_test.extend extension
24
+ end
25
+
26
+ def extension
27
+ return @extension if @extension
28
+
29
+ Output.details "#{mod.name} has #{defined ? '' : 'no '}inner Proof"
30
+
31
+ return nil unless defined
32
+
33
+ Output.details "Getting constant #{mod.name}::Proof"
34
+ @extension ||= mod.const_get :Proof, search_ancestors=false
35
+ end
36
+
37
+ def defined
38
+ @defined ||= mod.const_defined? :Proof, search_ancestors=false
39
+ end
40
+
41
+ def extension_name
42
+ "#{mod.name}::Proof"
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,11 @@
1
+ module Proof
2
+ module Namespace
3
+ def root_namespace
4
+ self.class.name.split('::').first
5
+ end
6
+
7
+ def namespace(*namespace)
8
+ namespace.join('::')
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,86 @@
1
+ require 'ostruct'
2
+
3
+ module Proof
4
+ class Output
5
+ include Single
6
+ include Setter::Settings
7
+ include ::Output
8
+
9
+ level :info
10
+
11
+ writer :h1, :level => :info do |text|
12
+ prefix :h1, text.upcase
13
+ end
14
+
15
+ writer :h2, :level => :info do |text|
16
+ prefix :h2, text
17
+ end
18
+
19
+ writer :pass, :level => :info do |text|
20
+ prefix :pass, "Pass: #{text}"
21
+ end
22
+
23
+ writer :fail, :level => :info do |text|
24
+ prefix :fail, "-> Fail: #{text}"
25
+ end
26
+
27
+ writer :error, :level => :warn do |text|
28
+ prefix :error, "Error: #{text}"
29
+ end
30
+
31
+ writer :backtrace, :level => :error do |text|
32
+ prefix :backtrace, text
33
+ end
34
+
35
+ writer :details, :level => :debug do |text|
36
+ prefix :details, "! #{text}"
37
+ end
38
+
39
+ writer :note, :level => :info do |text|
40
+ prefix :note, "* #{text}"
41
+ end
42
+
43
+ writer :info, :level => :info do |text|
44
+ prefix :info, text
45
+ end
46
+
47
+ writer :summary, :level => :info do |text|
48
+ prefix :summary, text.upcase
49
+ end
50
+
51
+ def prefix(method, text)
52
+ lines = lines(method)
53
+ "#{lines}#{text}"
54
+ end
55
+
56
+ def lines(method)
57
+ if [:h1, :summary].include? method
58
+ lines = 2
59
+ elsif [:h2, :details, :note, :info].include? method
60
+ lines = 1
61
+ elsif [:pass, :fail].include? method
62
+ if last_method? :h1, :h2, :error, :backtrace
63
+ lines = 1
64
+ else
65
+ lines = 0
66
+ end
67
+ elsif method == :error
68
+ lines = 1
69
+ elsif method == :backtrace
70
+ unless last_method? :error
71
+ lines = 1
72
+ else
73
+ lines = 0
74
+ end
75
+ else
76
+ lines = 1
77
+ end
78
+
79
+ new_line lines
80
+ end
81
+
82
+ def new_line(num=1)
83
+ "\n" * num
84
+ end
85
+ end
86
+ end
data/lib/proof/proof.rb CHANGED
@@ -1,32 +1,42 @@
1
- require 'mixology'
1
+ module Proof
2
+ def proof(description=nil, &block)
3
+ Proof::Description.current = description
4
+ Proof.begin
5
+ yield
6
+ Proof.end
7
+ Proof::Description.current = nil
8
+ end
9
+
10
+ def desc(description)
11
+ Proof::Description.current = description
12
+ end
2
13
 
3
- module Proof
4
- def start
5
- def_prove
14
+ def title(title)
15
+ Proof::Output.h1 title
16
+ end
17
+
18
+ def heading(heading)
19
+ Proof::Output.h2 heading
6
20
  if block_given?
7
21
  yield
8
- undef_prove
9
22
  end
10
23
  end
11
- module_function :start
12
-
13
- def def_prove
14
- Object.class_eval do
15
- def prove(&blk)
16
- proof_module = self.class.const_get :Proof
17
- mixin proof_module
18
- proof = instance_eval &blk
19
- unmix proof_module
20
- proof
21
- end
22
- end
24
+
25
+ def section(heading=nil)
26
+ Proof::Output.h2 heading if heading
27
+ yield if block_given?
23
28
  end
24
- module_function :def_prove
25
-
26
- def undef_prove
27
- Object.class_eval do
28
- undef :prove
29
- end
29
+ alias :block :section
30
+
31
+ def comment(comment)
32
+ Proof::Output.note comment
33
+ end
34
+
35
+ def self.begin
36
+ CoreExt::Object::Methods.define_prove
37
+ end
38
+
39
+ def self.end
40
+ CoreExt::Object::Methods.undefine_prove
30
41
  end
31
- module_function :undef_prove
32
42
  end
@@ -0,0 +1,19 @@
1
+ module Proof
2
+ class Result
3
+ include Initializer
4
+
5
+ initializer :description, :status, :error
6
+
7
+ def write
8
+ Output.write output_method, description
9
+ Error.output error if status == :error
10
+ end
11
+
12
+ def output_method
13
+ if status == :error
14
+ return :fail
15
+ end
16
+ return status
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,2 @@
1
+ require 'proof/runner/suite'
2
+ require 'proof/runner/summary'
@@ -0,0 +1,82 @@
1
+ require 'stringio'
2
+ require 'pathname'
3
+
4
+ module Proof
5
+ class Suite
6
+ attr_reader :files
7
+
8
+ def device
9
+ @device ||= self.class.default_device
10
+ end
11
+
12
+ def output
13
+ @output ||= self.class.default_output
14
+ end
15
+
16
+ def initialize(files, device = nil, output = nil)
17
+ @files = files
18
+ @device = device
19
+ @output = output
20
+ end
21
+
22
+ def self.default_device
23
+ Output::Devices.build_device(:string_io, :name => :suite_results)
24
+ end
25
+
26
+ def self.default_output
27
+ Proof::Output.instance
28
+ end
29
+
30
+ def self.run(*args)
31
+ device = default_device
32
+ output = default_output
33
+
34
+ if args.last.is_a? Hash
35
+ opts = args.pop
36
+ device = opts[:device] || device
37
+ output = opts[:output] || output
38
+ end
39
+
40
+ base_dir = File.expand_path(File.dirname(caller[0]))
41
+ file_patterns = flatten(args)
42
+ files = glob(file_patterns, base_dir)
43
+
44
+ if files.empty?
45
+ output.summary "!! Suite has no files"
46
+ return :failure
47
+ end
48
+
49
+ instance = new files, device, output
50
+ results = instance.run
51
+
52
+ Summary.output(results, output)
53
+ end
54
+
55
+ def self.glob(patterns, base_dir)
56
+ files = []
57
+ patterns.each do |pattern|
58
+ pattern = Pathname.new(pattern).absolute? ? pattern : File.join(base_dir, pattern)
59
+ files.concat Dir.glob(pattern)
60
+ end
61
+ files
62
+ end
63
+
64
+ def self.flatten(args)
65
+ files = []
66
+ args.each do |pattern|
67
+ files.concat pattern.is_a?(Array) ? pattern : [pattern]
68
+ end
69
+ files
70
+ end
71
+
72
+ def run
73
+ output.push_device(device) do
74
+ files.each do |file|
75
+ load file
76
+ end
77
+ end
78
+
79
+ device.readlines
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,61 @@
1
+ module Proof
2
+ class Summary
3
+ include Initializer
4
+
5
+ PASS_PATTERN = /Pass:.*$/
6
+ FAIL_PATTERN = /-> Fail:.*$/
7
+ ERROR_PATTERN = /Error:.*$/
8
+
9
+ initializer :results, :the_output
10
+
11
+ def self.output(results, output)
12
+ instance = new results, output
13
+ instance.output
14
+ instance.status
15
+ end
16
+
17
+ def passes
18
+ results.grep PASS_PATTERN
19
+ end
20
+
21
+ def fails
22
+ results.grep FAIL_PATTERN
23
+ end
24
+
25
+ def errors
26
+ results.grep ERROR_PATTERN
27
+ end
28
+
29
+ def status
30
+ if no_results? or any_failures?
31
+ @status = :failure
32
+ else any_successes?
33
+ @status = :success
34
+ end
35
+
36
+ @status
37
+ end
38
+
39
+ def no_results?
40
+ [passes.count, fails.count, errors.count].all? { |count| count == 0 }
41
+ end
42
+
43
+ def any_failures?
44
+ [fails.count, errors.count].any? { |count| count > 0 }
45
+ end
46
+
47
+ def any_successes?
48
+ [fails.count, errors.count].any? { |count| count > 0 }
49
+ end
50
+
51
+ def summary
52
+ "Passed: #{passes.count}\n" \
53
+ "Failed: #{fails.count}\n" \
54
+ "Errors: #{errors.count}\n"
55
+ end
56
+
57
+ def output
58
+ @the_output.summary summary
59
+ end
60
+ end
61
+ end
data/lib/proof.rb CHANGED
@@ -1 +1,17 @@
1
- require 'observance/observance'
1
+ require 'logging'
2
+ require 'single'
3
+ require 'setter'
4
+ require 'output'
5
+ require 'initializer'
6
+
7
+ require 'proof/namespace'
8
+ require 'proof/description'
9
+ require 'proof/extend'
10
+ require 'proof/result'
11
+ require 'proof/execution'
12
+ require 'proof/error'
13
+ require 'proof/core_ext'
14
+ require 'proof/proof'
15
+ require 'proof/output'
16
+ require 'proof/suite'
17
+ require 'proof/summary'
metadata CHANGED
@@ -1,18 +1,18 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: proof
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.0.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
8
- - We made this
8
+ - The Sans Collective
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-18 00:00:00.000000000 Z
12
+ date: 2013-04-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: mixology
15
+ name: logging
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
@@ -33,10 +33,21 @@ executables: []
33
33
  extensions: []
34
34
  extra_rdoc_files: []
35
35
  files:
36
+ - lib/proof/core_ext/object.rb
37
+ - lib/proof/core_ext.rb
38
+ - lib/proof/description.rb
39
+ - lib/proof/error.rb
40
+ - lib/proof/execution.rb
41
+ - lib/proof/extend.rb
42
+ - lib/proof/namespace.rb
43
+ - lib/proof/output.rb
36
44
  - lib/proof/proof.rb
37
- - lib/proof/version.rb
45
+ - lib/proof/result.rb
46
+ - lib/proof/runner.rb
47
+ - lib/proof/suite.rb
48
+ - lib/proof/summary.rb
38
49
  - lib/proof.rb
39
- homepage:
50
+ homepage: https://github.com/Sans/proof
40
51
  licenses: []
41
52
  post_install_message:
42
53
  rdoc_options: []
@@ -56,7 +67,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
56
67
  version: '0'
57
68
  requirements: []
58
69
  rubyforge_project:
59
- rubygems_version: 1.8.24
70
+ rubygems_version: 1.8.25
60
71
  signing_key:
61
72
  specification_version: 3
62
73
  summary: Proof Library
data/lib/proof/version.rb DELETED
@@ -1,3 +0,0 @@
1
- module Proof
2
- VERSION = "0.0.0"
3
- end