specifier 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4a4098b51fe3a0a29ab860be282db1a5a8d2007b
4
+ data.tar.gz: 46e4a79e654b9c3fa4ea7dd16dd0f0e8156e11ac
5
+ SHA512:
6
+ metadata.gz: a481e8da92542e1274dd295e327945fe0286852a66eae950e3ea99ec6796ea4c60ff6bb207b698a0decf7886dbb6daeaa19cc59cab1026310c59020d101e6ddc
7
+ data.tar.gz: 075ca1cda8870fd238b161705077f82073d254170a12b36d99fa03a73e16354ee99ef9ccd2581dfcdd22c3cbc787068eb463bf25dd47d8586dedfc255906d3a2
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Kevin Sylvestre
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,31 @@
1
+ # Specifier
2
+
3
+ ## Example
4
+
5
+ ```ruby
6
+ class Echo
7
+ def self.say(message)
8
+ message
9
+ end
10
+ end
11
+ ```
12
+
13
+ ```ruby
14
+ Specifier.specify Echo do
15
+ describe '.say' do
16
+ it 'says "Hello" if you say "Hello"' do
17
+ expect(Echo.say('Hello')).to equal('Hello')
18
+ end
19
+
20
+ it 'says "Goodbye" if you say "Goodbye"' do
21
+ expect(Echo.say('Goodbye')).to equal('Goodbye')
22
+ end
23
+ end
24
+ end
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ```bash
30
+ bundle exec specifier ./specs
31
+ ```
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'specifier'
4
+
5
+ cli = Specifier::CLI.new
6
+ cli.parse
@@ -0,0 +1,35 @@
1
+ require 'find'
2
+ require 'slop'
3
+
4
+ require 'specifier/version'
5
+ require 'specifier/cli'
6
+ require 'specifier/config'
7
+ require 'specifier/logger'
8
+ require 'specifier/runner'
9
+ require 'specifier/context'
10
+ require 'specifier/example'
11
+ require 'specifier/expectation'
12
+ require 'specifier/memoizer'
13
+ require 'specifier/matcher'
14
+ require 'specifier/formatter'
15
+
16
+ module Specifier
17
+
18
+ def self.specify(scope, &block)
19
+ context = Context.new(scope, &block)
20
+ context.run
21
+ end
22
+
23
+ def self.config
24
+ @config ||= Config.new
25
+ end
26
+
27
+ def self.logger
28
+ @logger ||= Logger.new
29
+ end
30
+
31
+ def self.formatter
32
+ @formatter ||= Formatter::Progress.new(logger)
33
+ end
34
+
35
+ end
@@ -0,0 +1,42 @@
1
+ module Specifier
2
+ class CLI
3
+ BANNER = 'usage: specifier [options] [./specs]'.freeze
4
+
5
+ def parse(items = ARGV)
6
+ config = Slop.parse(items) do |options|
7
+ options.banner = BANNER
8
+
9
+ options.on '-h', '--help', 'help' do
10
+ return help(options)
11
+ end
12
+
13
+ options.on '-v', '--version', 'version' do
14
+ return version
15
+ end
16
+ end
17
+
18
+ run(config)
19
+ end
20
+
21
+ private
22
+
23
+ def help(options)
24
+ Specifier.logger.log(String(options))
25
+ end
26
+
27
+ def version
28
+ Specifier.logger.log(String(VERSION))
29
+ end
30
+
31
+ def run(options)
32
+ paths = Set.new
33
+ options.arguments.each do |argument|
34
+ Find.find(argument) do |path|
35
+ paths << path if path.match?(/\A(.*).rb\Z/)
36
+ end
37
+ end
38
+ Runner.new(paths: paths).run
39
+ end
40
+
41
+ end
42
+ end
File without changes
@@ -0,0 +1,31 @@
1
+ require 'byebug'
2
+
3
+ module Specifier
4
+ class Context
5
+ attr_accessor :parent
6
+
7
+ def initialize(scope, &block)
8
+ @_scope = scope
9
+ @_block = block
10
+ @_examples = Set.new
11
+ end
12
+
13
+ def describe(scope, &block)
14
+ context = Context.new(scope, &block)
15
+ context.parent = self
16
+ context.run
17
+ end
18
+
19
+ def it(descriptor, &block)
20
+ @_examples << Example.new(descriptor, &block)
21
+ end
22
+
23
+ def run
24
+ instance_eval(&@_block)
25
+ @_examples.each do |example|
26
+ Specifier.formatter.record(example, example.run)
27
+ end
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,32 @@
1
+ module Specifier
2
+ class Example
3
+ Result = Struct.new(:status, :message)
4
+
5
+ def initialize(descriptor, &block)
6
+ @_descriptor = descriptor
7
+ @_block = block
8
+ end
9
+
10
+ # def let(name, &block)
11
+ # define_method(name) do
12
+ # @_memoizer.resolve(name, block)
13
+ # end
14
+ # end
15
+
16
+ def expect(value)
17
+ Expectation.new(value)
18
+ end
19
+
20
+ def equal(value)
21
+ Matcher::Equal.new(value)
22
+ end
23
+
24
+ def run
25
+ instance_eval(&@_block)
26
+ return Result.new(:pass)
27
+ rescue Specifier::Expectation::Miss => miss
28
+ return Result.new(:fail, miss.message)
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,17 @@
1
+ module Specifier
2
+ class Expectation
3
+ class Miss < StandardError
4
+ def initialize(message)
5
+ @message = message
6
+ end
7
+ end
8
+
9
+ def initialize(value)
10
+ @value = value
11
+ end
12
+
13
+ def to(matcher)
14
+ raise Miss, matcher.message unless matcher.match?(@value)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,2 @@
1
+ require 'specifier/formatter/base'
2
+ require 'specifier/formatter/progress'
@@ -0,0 +1,49 @@
1
+ module Specifier
2
+ module Formatter
3
+ class Base
4
+ Recording = Struct.new(:example, :result) do
5
+ def status
6
+ result.status
7
+ end
8
+
9
+ def pass?
10
+ status.eql?(:pass)
11
+ end
12
+
13
+ def fail?
14
+ status.eql?(:fail)
15
+ end
16
+ end
17
+
18
+ def initialize(logger)
19
+ @logger = logger
20
+ @recordings = []
21
+ end
22
+
23
+ def record(example, result)
24
+ @recordings << Recording.new(example, result)
25
+ end
26
+
27
+ def passed
28
+ @recordings.select(&:pass?)
29
+ end
30
+
31
+ def failed
32
+ @recordings.select(&:fail?)
33
+ end
34
+
35
+ def summarize
36
+ @logger.log
37
+ @logger.log(summary)
38
+ end
39
+
40
+ def summary
41
+ <<~SUMMARY
42
+ Total: #{@recordings.count}
43
+ Passed: #{passed.count}
44
+ Failed: #{failed.count}
45
+ SUMMARY
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,20 @@
1
+ module Specifier
2
+ module Formatter
3
+ class Progress < Base
4
+ def record(example, result)
5
+ super
6
+ @logger << symbol(result)
7
+ end
8
+
9
+ private
10
+
11
+ def symbol(result)
12
+ case result.status
13
+ when :pass then '+'
14
+ when :fail then '-'
15
+ end
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,25 @@
1
+ module Specifier
2
+
3
+ # A generic logger extracting output for testing. Can be accessed via the global.
4
+ #
5
+ # Usage:
6
+ #
7
+ # Specifier.logger.log("...")
8
+ #
9
+ class Logger
10
+
11
+ def initialize(stream = STDOUT)
12
+ @stream = stream
13
+ end
14
+
15
+ def <<(message)
16
+ @stream << message
17
+ end
18
+
19
+ def log(message = nil)
20
+ @stream.puts message
21
+ end
22
+
23
+ end
24
+
25
+ end
@@ -0,0 +1,2 @@
1
+ require 'specifier/matcher/base'
2
+ require 'specifier/matcher/equal'
@@ -0,0 +1,11 @@
1
+ module Specifier
2
+ module Matcher
3
+ class Base
4
+ attr_accessor :expected
5
+
6
+ def match?(expected)
7
+ self.expected = expected
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,18 @@
1
+ module Specifier
2
+ module Matcher
3
+ class Equal < Base
4
+ def initialize(value)
5
+ @value = value
6
+ end
7
+
8
+ def match?(expected)
9
+ super
10
+ expected.eql?(@value)
11
+ end
12
+
13
+ def message
14
+ "expected #{@expected.inspect} got #{@value.inspect}"
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,11 @@
1
+ module Specifier
2
+ class Memoizer
3
+ def initialize
4
+ @resolutions = {}
5
+ end
6
+
7
+ def resolve(name)
8
+ @resolutions[name] ||= yield
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ module Specifier
2
+ class Runner
3
+ def initialize(paths:)
4
+ @paths = paths
5
+ end
6
+
7
+ def run
8
+ @paths.each do |path|
9
+ load path
10
+ end
11
+ Specifier.formatter.summarize
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,3 @@
1
+ module Specifier
2
+ VERSION = '0.1.0'.freeze
3
+ end
metadata ADDED
@@ -0,0 +1,149 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: specifier
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Kevin Sylvestre
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-08-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: slop
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: byebug
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Thi should probably never be used.
98
+ email:
99
+ - kevin@ksylvest.com
100
+ executables:
101
+ - specifier
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - Gemfile
106
+ - LICENSE
107
+ - README.md
108
+ - bin/specifier
109
+ - lib/specifier.rb
110
+ - lib/specifier/cli.rb
111
+ - lib/specifier/config.rb
112
+ - lib/specifier/context.rb
113
+ - lib/specifier/example.rb
114
+ - lib/specifier/expectation.rb
115
+ - lib/specifier/formatter.rb
116
+ - lib/specifier/formatter/base.rb
117
+ - lib/specifier/formatter/progress.rb
118
+ - lib/specifier/logger.rb
119
+ - lib/specifier/matcher.rb
120
+ - lib/specifier/matcher/base.rb
121
+ - lib/specifier/matcher/equal.rb
122
+ - lib/specifier/memoizer.rb
123
+ - lib/specifier/runner.rb
124
+ - lib/specifier/version.rb
125
+ homepage: https://github.com/ksylvest/specifier
126
+ licenses:
127
+ - MIT
128
+ metadata: {}
129
+ post_install_message:
130
+ rdoc_options: []
131
+ require_paths:
132
+ - lib
133
+ required_ruby_version: !ruby/object:Gem::Requirement
134
+ requirements:
135
+ - - ">="
136
+ - !ruby/object:Gem::Version
137
+ version: '0'
138
+ required_rubygems_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ requirements: []
144
+ rubyforge_project:
145
+ rubygems_version: 2.6.11
146
+ signing_key:
147
+ specification_version: 4
148
+ summary: A testing framework written for fun.
149
+ test_files: []