fix 0.0.1.pre → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -0
  3. data/.travis.yml +4 -2
  4. data/README.md +81 -49
  5. data/Rakefile +17 -0
  6. data/VERSION.semver +1 -1
  7. data/example/duck/README.md +9 -0
  8. data/example/duck/app.rb +3 -0
  9. data/example/duck/lib.rb +14 -0
  10. data/example/duck/spec.rb +31 -0
  11. data/example/duck/test.rb +6 -0
  12. data/fix.gemspec +10 -6
  13. data/lib/fix.rb +3 -17
  14. data/lib/fix/dsl.rb +10 -0
  15. data/lib/fix/expectation.rb +48 -0
  16. data/lib/fix/expectation_high.rb +26 -0
  17. data/lib/fix/expectation_low.rb +44 -0
  18. data/lib/fix/expectation_medium.rb +29 -0
  19. data/lib/fix/expectation_set.rb +8 -0
  20. data/lib/fix/helper/it_helper.rb +12 -0
  21. data/lib/fix/helper/its_helper.rb +12 -0
  22. data/lib/fix/helper/let_accessor_helper.rb +11 -0
  23. data/lib/fix/helper/let_reader_helper.rb +9 -0
  24. data/lib/fix/helper/let_writer_helper.rb +13 -0
  25. data/lib/fix/helper/on_helper.rb +12 -0
  26. data/lib/fix/helper/requirement_helper.rb +44 -0
  27. data/lib/fix/it.rb +14 -0
  28. data/lib/fix/its.rb +14 -0
  29. data/lib/fix/on.rb +20 -0
  30. data/lib/fix/spec.rb +16 -10
  31. data/lib/fix/subject.rb +43 -10
  32. data/lib/fix/test.rb +114 -0
  33. data/lib/fix/version.rb +9 -0
  34. data/spec/TODO +0 -0
  35. data/spec/spec_helper.rb +2 -4
  36. data/spec/support.rb +3 -0
  37. data/spec/support/coverage.rb +3 -0
  38. data/spec/support/env.rb +4 -0
  39. data/spec/support/presenter.rb +0 -0
  40. metadata +85 -22
  41. data/.ruby-version +0 -1
  42. data/bin/fix +0 -58
  43. data/lib/fix/base_matcher.rb +0 -38
  44. data/lib/fix/call.rb +0 -16
  45. data/lib/fix/constant.rb +0 -37
  46. data/lib/fix/expectation_target.rb +0 -41
  47. data/lib/fix/helper.rb +0 -34
  48. data/lib/fix/scope.rb +0 -20
  49. data/logo.png +0 -0
  50. data/logo.svg +0 -19
  51. data/spec/subject_spec.rb +0 -5
@@ -0,0 +1,29 @@
1
+ require_relative File.join 'expectation_high'
2
+
3
+ module Fix
4
+ class ExpectationMedium < ExpectationHigh
5
+ def evaluate front_object
6
+ subject = Subject.new front_object, *@args
7
+ got = nil
8
+
9
+ Thread.new {
10
+ report = expect { got = subject.actual }.
11
+ public_send target, @matcher => @expected
12
+
13
+ data = presenter report, got
14
+
15
+ Hash[ data.to_a + meta(subject).to_a ]
16
+ }.value
17
+ end
18
+
19
+ private
20
+
21
+ def pass? report
22
+ report.pass? || report.exception.nil?
23
+ end
24
+
25
+ def level
26
+ 2
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,8 @@
1
+ require 'set'
2
+ require 'singleton'
3
+
4
+ module Fix
5
+ class ExpectationSet < Set
6
+ include Singleton
7
+ end
8
+ end
@@ -0,0 +1,12 @@
1
+ module Fix
2
+ module Helper
3
+ module ItsHelper
4
+ def its attribute, *args, &block
5
+ i = Its.new @defs, *(@args + [[attribute] + args])
6
+ i.instance_eval(&block)
7
+ end
8
+ end
9
+ end
10
+ end
11
+
12
+ require_relative File.join '..', 'its'
@@ -0,0 +1,12 @@
1
+ module Fix
2
+ module Helper
3
+ module ItHelper
4
+ def it &block
5
+ i = It.new @defs, *@args
6
+ i.instance_eval(&block)
7
+ end
8
+ end
9
+ end
10
+ end
11
+
12
+ require_relative File.join '..', 'it'
@@ -0,0 +1,11 @@
1
+ require_relative File.join 'let_reader_helper'
2
+ require_relative File.join 'let_writer_helper'
3
+
4
+ module Fix
5
+ module Helper
6
+ module LetAccessorHelper
7
+ include LetReaderHelper
8
+ include LetWriterHelper
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ module Fix
2
+ module Helper
3
+ module LetReaderHelper
4
+ def method_missing name, *args, &block
5
+ @defs.has_key?(name) ? @defs.fetch(name).call : super
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ module Fix
2
+ module Helper
3
+ module LetWriterHelper
4
+ def let name, &block
5
+ if @defs.has_key? name
6
+ raise IndexError, 'the given key is already present.'
7
+ else
8
+ @defs.update name => block
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Fix
2
+ module Helper
3
+ module OnHelper
4
+ def on attribute, *args, &block
5
+ i = On.new @defs, *(@args + [[attribute] + args])
6
+ i.instance_eval(&block)
7
+ end
8
+ end
9
+ end
10
+ end
11
+
12
+ require_relative File.join '..', 'on'
@@ -0,0 +1,44 @@
1
+ require_relative File.join 'let_reader_helper'
2
+
3
+ module Fix
4
+ module Helper
5
+ module RequirementHelper
6
+ include Helper::LetReaderHelper
7
+
8
+ def MUST definition
9
+ ExpectationHigh.new true, definition, *@args
10
+ end
11
+
12
+ alias_method :is_REQUIRED_to, :MUST
13
+ alias_method :SHALL, :MUST
14
+
15
+ def MUST_NOT definition
16
+ ExpectationHigh.new false, definition, *@args
17
+ end
18
+
19
+ alias_method :SHALL_NOT, :MUST_NOT
20
+
21
+ def SHOULD definition
22
+ ExpectationMedium.new true, definition, *@args
23
+ end
24
+
25
+ alias_method :is_RECOMMENDED_to, :SHOULD
26
+
27
+ def SHOULD_NOT definition
28
+ ExpectationMedium.new false, definition, *@args
29
+ end
30
+
31
+ alias_method :is_NOT_RECOMMENDED_to, :SHOULD_NOT
32
+
33
+ def MAY definition
34
+ ExpectationLow.new true, definition, *@args
35
+ end
36
+
37
+ alias_method :is_OPTIONAL_to, :MAY
38
+ end
39
+ end
40
+ end
41
+
42
+ require_relative File.join '..', 'expectation_high'
43
+ require_relative File.join '..', 'expectation_low'
44
+ require_relative File.join '..', 'expectation_medium'
data/lib/fix/it.rb ADDED
@@ -0,0 +1,14 @@
1
+ require_relative File.join 'helper', 'requirement_helper'
2
+
3
+ module Fix
4
+ class It
5
+ include Helper::RequirementHelper
6
+
7
+ def initialize defs, *args
8
+ @defs = defs
9
+ @args = args
10
+
11
+ freeze
12
+ end
13
+ end
14
+ end
data/lib/fix/its.rb ADDED
@@ -0,0 +1,14 @@
1
+ require_relative File.join 'helper', 'requirement_helper'
2
+
3
+ module Fix
4
+ class Its
5
+ include Helper::RequirementHelper
6
+
7
+ def initialize defs, *args
8
+ @defs = defs
9
+ @args = args
10
+
11
+ freeze
12
+ end
13
+ end
14
+ end
data/lib/fix/on.rb ADDED
@@ -0,0 +1,20 @@
1
+ require_relative File.join 'helper', 'it_helper'
2
+ require_relative File.join 'helper', 'its_helper'
3
+ require_relative File.join 'helper', 'let_accessor_helper'
4
+ require_relative File.join 'helper', 'on_helper' unless defined? Fix::Helper::OnHelper
5
+
6
+ module Fix
7
+ class On
8
+ include Helper::ItHelper
9
+ include Helper::ItsHelper
10
+ include Helper::LetAccessorHelper
11
+ include Helper::OnHelper
12
+
13
+ def initialize defs, *args
14
+ @defs = defs
15
+ @args = args
16
+
17
+ freeze
18
+ end
19
+ end
20
+ end
data/lib/fix/spec.rb CHANGED
@@ -1,20 +1,26 @@
1
+ require_relative File.join 'dsl'
2
+ require_relative File.join 'test'
3
+
1
4
  module Fix
2
5
  class Spec
3
- attr_reader :examples
6
+ include DSL
7
+
8
+ def initialize title = nil, &block
9
+ @title = title
10
+ @defs = {}
11
+ @args = []
4
12
 
5
- def initialize *syms, &block
6
- @examples = Set.new
13
+ instance_eval(&block)
7
14
 
8
- const = syms.inject(Object) do |base, const|
9
- base.const_get(const)
10
- end
15
+ freeze
16
+ end
11
17
 
12
- @constant = Constant.new const, @examples
13
- @constant.instance_exec &block if block
18
+ def test front_object, seed: Random.new_seed, color: true, stdout: STDOUT, stderr: STDERR
19
+ Test.new front_object, seed: Random.new_seed, color: true, stdout: STDOUT, stderr: STDERR
14
20
  end
15
21
 
16
- def run
17
- @examples.map {|example| example.value }
22
+ def valid? front_object
23
+ Test.new(front_object).pass?
18
24
  end
19
25
  end
20
26
  end
data/lib/fix/subject.rb CHANGED
@@ -1,22 +1,55 @@
1
1
  module Fix
2
2
  class Subject
3
- attr_reader :object, :examples
3
+ attr_reader :error
4
4
 
5
- def initialize object, examples
6
- @examples = examples
7
- @object = object
5
+ def initialize input, *args
6
+ @input = input
7
+ @args = args
8
+ @error = nil
9
+
10
+ @implemented = nil
11
+
12
+ begin
13
+ param_id = 0
14
+ @cache_value = params.inject(input) do |mem, param|
15
+ param_id = param_id.next
16
+ @implemented = mem.respond_to? param.first, false
17
+ mem.public_send(*param)
18
+ end
19
+ rescue => e
20
+ @error = {
21
+ exception: e,
22
+ param_id: param_id
23
+ }
24
+ end
25
+
26
+ freeze
27
+ end
28
+
29
+ def actual
30
+ if valid?
31
+ @cache_value.public_send(*challenge)
32
+ else
33
+ raise @error.fetch :exception
34
+ end
35
+ end
36
+
37
+ def params
38
+ @args[0..-2]
8
39
  end
9
40
 
10
- def expect value
11
- ExpectationTarget.new value
41
+ def challenge
42
+ @args.last
12
43
  end
13
44
 
14
- def should matcher
15
- @examples << Thread.new { expect(@object).to matcher }
45
+ def implemented?
46
+ @implemented && valid? && @cache_value.respond_to?(challenge.first, false)
16
47
  end
17
48
 
18
- def should_not matcher
19
- @examples << Thread.new { expect(@object).not_to matcher }
49
+ private
50
+
51
+ def valid?
52
+ @error.nil?
20
53
  end
21
54
  end
22
55
  end
data/lib/fix/test.rb ADDED
@@ -0,0 +1,114 @@
1
+ require_relative File.join 'expectation_set'
2
+
3
+ module Fix
4
+ class Test
5
+ attr_reader :total_time
6
+
7
+ def initialize front_object, seed: Random.new_seed, color: true, stdout: STDOUT, stderr: STDERR
8
+ @options = { color: color, stdout: stdout, stderr: stderr }
9
+ @options.fetch(:stdout).puts about "Run options: --seed #{seed}"
10
+
11
+ random = Random.new seed
12
+ expectations = ExpectationSet.instance.to_a.shuffle(random: random)
13
+
14
+ start_time = Time.now
15
+ @results = expectations.map do |expectation|
16
+ log expectation.evaluate front_object
17
+ end
18
+ @total_time = Time.now - start_time
19
+
20
+ @options.fetch(:stdout).puts about "\nFinished in #{@total_time} seconds."
21
+ @options.fetch(:stdout).puts statistics
22
+
23
+ freeze
24
+ end
25
+
26
+ def pass?
27
+ @results.all? {|result| state(result) == :success }
28
+ end
29
+
30
+ def fail?
31
+ !pass?
32
+ end
33
+
34
+ def statistics
35
+ errors = @results.select {|result| state(result) == :error }
36
+ failures = @results.select {|result| state(result) == :failure }
37
+
38
+ color = if errors.any?
39
+ :error
40
+ elsif failures.any?
41
+ :failure
42
+ else
43
+ :success
44
+ end
45
+
46
+ __send__ color, [
47
+ "#{@results.length} tests",
48
+ "#{failures.length} failures",
49
+ "#{errors.length} errors"
50
+ ].join(', ')
51
+ end
52
+
53
+ private
54
+
55
+ def log result
56
+ color = state result
57
+ std = (color == :success ? :stdout : :stderr)
58
+
59
+ @options.fetch(std).print __send__ color, char(result)
60
+
61
+ result
62
+ end
63
+
64
+ def colorize state, string
65
+ @options[:color] ? "\e[#{state}m#{string}\e[0m" : string
66
+ end
67
+
68
+ def about string
69
+ colorize 37, string
70
+ end
71
+
72
+ def error string
73
+ colorize 31, string
74
+ end
75
+
76
+ def success string
77
+ colorize 32, string
78
+ end
79
+
80
+ def pending string
81
+ colorize 33, string
82
+ end
83
+
84
+ def matcher string
85
+ colorize 34, string
86
+ end
87
+
88
+ def failure string
89
+ colorize 35, string
90
+ end
91
+
92
+ # Returns the state of the expectation.
93
+ def state data
94
+ if data.fetch :pass
95
+ :success
96
+ elsif data.fetch(:exception).nil?
97
+ :failure
98
+ else
99
+ :error
100
+ end
101
+ end
102
+
103
+ # Returns a char as the result of the expectation.
104
+ def char data
105
+ if data.fetch :pass
106
+ '.'
107
+ elsif data.fetch(:exception).nil?
108
+ 'F'
109
+ else
110
+ 'E'
111
+ end
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,9 @@
1
+ require 'pathname'
2
+
3
+ module Fix
4
+
5
+ # Gem version
6
+ VERSION = File.open(
7
+ Pathname.new(__FILE__).join '..', '..', '..', 'VERSION.semver'
8
+ ).read.chomp.to_sym
9
+ end