tengu 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +16 -0
- data/Rakefile +7 -0
- data/bin/tengu +16 -0
- data/lib/tengu.rb +19 -0
- data/lib/tengu/allow.rb +12 -0
- data/lib/tengu/base_formatter.rb +57 -0
- data/lib/tengu/composite_matcher.rb +23 -0
- data/lib/tengu/describe_block.rb +61 -0
- data/lib/tengu/double.rb +22 -0
- data/lib/tengu/expectation.rb +33 -0
- data/lib/tengu/file.rb +43 -0
- data/lib/tengu/it_block.rb +77 -0
- data/lib/tengu/matcher.rb +13 -0
- data/lib/tengu/matchers.rb +57 -0
- data/lib/tengu/rake_task.rb +19 -0
- data/lib/tengu/receive_matcher.rb +18 -0
- data/lib/tengu/receiver.rb +53 -0
- data/lib/tengu/result.rb +16 -0
- data/lib/tengu/runner.rb +29 -0
- data/lib/tengu/version.rb +3 -0
- data/spec/allow_spec.rb +12 -0
- data/spec/base_formatter_spec.rb +62 -0
- data/spec/composite_matcher_spec.rb +29 -0
- data/spec/describe_block_spec.rb +37 -0
- data/spec/double_spec.rb +7 -0
- data/spec/expectation_spec.rb +43 -0
- data/spec/file_spec.rb +39 -0
- data/spec/fixtures/example.rb +23 -0
- data/spec/it_block_spec.rb +21 -0
- data/spec/matcher_spec.rb +7 -0
- data/spec/receive_matcher_spec.rb +7 -0
- data/spec/receiver_spec.rb +13 -0
- data/spec/result_spec.rb +19 -0
- data/spec/runner_spec.rb +19 -0
- data/spec/tengu_spec.rb +13 -0
- data/tengu.gemspec +25 -0
- metadata +156 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 12e7d2f0783ace8519c31deb1b36a70057c2ddb2
|
4
|
+
data.tar.gz: 22900571d9768970c13b1fe6bb42cdfa220e45b4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 575f49bd06887612dfa45a755047358e2f8ec8b9ad6ad7745cb9c1b7d9b0eabd3356ef7858d8642e9f3f8556d103d4f21ea31b24541919ca481e2884736e2180
|
7
|
+
data.tar.gz: a20dc50058a5bc07118fa8cf12d0d5172e1b3f7f9bd05eecc1a25d3be98cc0e9657396960a4e76d400008c7b56f69c5c15f76af5614fe712a1e5afed3ee43533
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 halogenandtoast
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# Tengu
|
2
|
+
|
3
|
+
An object oriented test library with similar syntax to RSpec
|
4
|
+
|
5
|
+
## About
|
6
|
+
|
7
|
+
This is a work in progress and isn't suggested for actual use.
|
8
|
+
|
9
|
+
|
10
|
+
## Contributing
|
11
|
+
|
12
|
+
1. Fork it
|
13
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
14
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
15
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
16
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/bin/tengu
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
4
|
+
|
5
|
+
require "tengu"
|
6
|
+
|
7
|
+
formatter = Tengu::BaseFormatter.new
|
8
|
+
runner = Tengu::Runner.new
|
9
|
+
|
10
|
+
if ARGV.count < 1
|
11
|
+
files = Dir.glob("spec/**/*_spec.rb").map { |filename| ::File.open(filename, "r") }
|
12
|
+
else
|
13
|
+
files = ARGV.map { |arg| ::File.open(arg, "r") }
|
14
|
+
end
|
15
|
+
|
16
|
+
runner.run(files, [formatter])
|
data/lib/tengu.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "tengu/base_formatter"
|
2
|
+
require "tengu/composite_matcher"
|
3
|
+
require "tengu/describe_block.rb"
|
4
|
+
require "tengu/expectation"
|
5
|
+
require "tengu/file"
|
6
|
+
require "tengu/it_block.rb"
|
7
|
+
require "tengu/matcher"
|
8
|
+
require "tengu/matchers"
|
9
|
+
require "tengu/result"
|
10
|
+
require "tengu/runner"
|
11
|
+
require "tengu/version"
|
12
|
+
|
13
|
+
module Tengu
|
14
|
+
def self.test(file_name, formatter = nil)
|
15
|
+
formatters = Array(formatter)
|
16
|
+
runner = Runner.new
|
17
|
+
runner.run([::File.open(file_name, "r")], formatters)
|
18
|
+
end
|
19
|
+
end
|
data/lib/tengu/allow.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
module Tengu
|
2
|
+
class BaseFormatter
|
3
|
+
def initialize(out = $stdout)
|
4
|
+
@out = out
|
5
|
+
@failures = []
|
6
|
+
end
|
7
|
+
|
8
|
+
def notify(event, object = nil)
|
9
|
+
case event
|
10
|
+
when :started then started(object)
|
11
|
+
when :pending then out.print "P"
|
12
|
+
when :success then out.print "."
|
13
|
+
when :failure then
|
14
|
+
@failures << object
|
15
|
+
out.print "F"
|
16
|
+
when :finished then finished(object)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
attr_reader :out
|
23
|
+
|
24
|
+
def started(runner)
|
25
|
+
@started = Time.now
|
26
|
+
end
|
27
|
+
|
28
|
+
def finished(result)
|
29
|
+
out.puts
|
30
|
+
out.puts "Finished in %0.5f seconds" % [Time.now - @started]
|
31
|
+
out.puts "#{display(result.total_count, "example")}, #{display(result.failure_count, "failure")}"
|
32
|
+
if @failures.count > 0
|
33
|
+
puts
|
34
|
+
@failures.each do |it_block|
|
35
|
+
puts it_block.description
|
36
|
+
it_block.expectations.each do |expectation|
|
37
|
+
unless expectation.success?
|
38
|
+
puts expectation.message
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
if result.pending_count > 0
|
44
|
+
out.puts "#{result.pending_count} pending"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def display(count, word)
|
49
|
+
"#{count} " +
|
50
|
+
if count == 1
|
51
|
+
word
|
52
|
+
else
|
53
|
+
word + "s"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Tengu
|
2
|
+
class CompositeMatcher
|
3
|
+
def matches?(object)
|
4
|
+
object
|
5
|
+
end
|
6
|
+
|
7
|
+
def > value
|
8
|
+
Matcher.new("be greater than #{value.inspect}") { |object| object > value }
|
9
|
+
end
|
10
|
+
|
11
|
+
def >= value
|
12
|
+
Matcher.new("be greater than or equal to #{value.inspect}") { |object| object >= value }
|
13
|
+
end
|
14
|
+
|
15
|
+
def < value
|
16
|
+
Matcher.new("be less than #{value.inspect}") { |object| object < value }
|
17
|
+
end
|
18
|
+
|
19
|
+
def <= value
|
20
|
+
Matcher.new("be less than or equal to #{value.inspect}") { |object| object <= value }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module Tengu
|
2
|
+
class DescribeBlock
|
3
|
+
def initialize(description, block)
|
4
|
+
@description = description
|
5
|
+
@block = block
|
6
|
+
@test_cases = []
|
7
|
+
@before_hooks = []
|
8
|
+
@after_hooks = []
|
9
|
+
load_test_cases
|
10
|
+
end
|
11
|
+
|
12
|
+
def run(runner, listeners = [])
|
13
|
+
run_test_cases(runner, listeners)
|
14
|
+
end
|
15
|
+
|
16
|
+
def success_count
|
17
|
+
@test_cases.count { |test_case| test_case.success? }
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_count
|
21
|
+
@test_cases.count { |test_case| !test_case.pending? }
|
22
|
+
end
|
23
|
+
|
24
|
+
def pending_count
|
25
|
+
@test_cases.count { |test_case| test_case.pending? }
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def include(included_module)
|
31
|
+
singleton_class.send(:include, included_module)
|
32
|
+
end
|
33
|
+
|
34
|
+
def before(&block)
|
35
|
+
@before_hooks << block
|
36
|
+
end
|
37
|
+
|
38
|
+
def after(&block)
|
39
|
+
@after_hooks << block
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
def load_test_cases
|
44
|
+
instance_eval &@block
|
45
|
+
end
|
46
|
+
|
47
|
+
def run_test_cases(runner, listeners = [])
|
48
|
+
@test_cases.each do |test_case|
|
49
|
+
@before_hooks.each { |hook| hook.call }
|
50
|
+
test_case.run(runner, listeners)
|
51
|
+
@after_hooks.each { |hook| hook.call }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def it(description = nil, &block)
|
56
|
+
@test_cases << ItBlock.new(description, block)
|
57
|
+
end
|
58
|
+
|
59
|
+
def xit(description, &block); end
|
60
|
+
end
|
61
|
+
end
|
data/lib/tengu/double.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module Tengu
|
2
|
+
class Double
|
3
|
+
def initialize(identifier = nil, methods = {})
|
4
|
+
@identifier = identifier
|
5
|
+
methods.each do |message, value|
|
6
|
+
define_singleton_method message, -> (*args) { _tengu_received[message] << args; value }
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def _tengu_received
|
11
|
+
@_tengu_received ||= Hash.new { |hash, key| hash[key] = [] }
|
12
|
+
end
|
13
|
+
|
14
|
+
def _tengu_received?(message, args = [])
|
15
|
+
if args.length > 0
|
16
|
+
_tengu_received[message] && _tengu_received[message].include?(args)
|
17
|
+
else
|
18
|
+
_tengu_received.keys.include?(message)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Tengu
|
2
|
+
class Expectation
|
3
|
+
def initialize(object)
|
4
|
+
@object = object
|
5
|
+
@success = false
|
6
|
+
@positive = true
|
7
|
+
@matcher = nil
|
8
|
+
end
|
9
|
+
|
10
|
+
def success?
|
11
|
+
@success
|
12
|
+
end
|
13
|
+
|
14
|
+
def to(matcher)
|
15
|
+
@matcher = matcher
|
16
|
+
@success = @matcher.matches?(@object)
|
17
|
+
end
|
18
|
+
|
19
|
+
def not_to(matcher)
|
20
|
+
@positive = false
|
21
|
+
@matcher = matcher
|
22
|
+
@success = !@matcher.matches?(@object)
|
23
|
+
end
|
24
|
+
|
25
|
+
def message
|
26
|
+
if @positive
|
27
|
+
"expected #{@object.inspect} to #{@matcher.description}"
|
28
|
+
else
|
29
|
+
"expected #{@object.inspect} not to #{@matcher.description}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/lib/tengu/file.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
module Tengu
|
2
|
+
class File
|
3
|
+
def initialize(io)
|
4
|
+
@io = io
|
5
|
+
@describes = []
|
6
|
+
load_tests
|
7
|
+
end
|
8
|
+
|
9
|
+
def run(runner, listeners = [])
|
10
|
+
run_tests(runner, listeners)
|
11
|
+
end
|
12
|
+
|
13
|
+
def success_count
|
14
|
+
@describes.inject(0) { |sum, n| sum += n.success_count }
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_count
|
18
|
+
@describes.inject(0) { |sum, n| sum += n.test_count }
|
19
|
+
end
|
20
|
+
|
21
|
+
def pending_count
|
22
|
+
@describes.inject(0) { |sum, n| sum += n.pending_count }
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def code
|
28
|
+
@code ||= @io.read
|
29
|
+
end
|
30
|
+
|
31
|
+
def load_tests
|
32
|
+
instance_eval(code)
|
33
|
+
end
|
34
|
+
|
35
|
+
def run_tests(runner, listeners= [])
|
36
|
+
@describes.each { |describe| describe.run(runner, listeners) }
|
37
|
+
end
|
38
|
+
|
39
|
+
def describe(description, &block)
|
40
|
+
@describes << DescribeBlock.new(description, block)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require "tengu/matchers"
|
2
|
+
require "tengu/double"
|
3
|
+
require "tengu/allow"
|
4
|
+
require "tengu/receiver"
|
5
|
+
|
6
|
+
module Tengu
|
7
|
+
class ItBlock
|
8
|
+
include Matchers
|
9
|
+
attr_reader :description, :expectations
|
10
|
+
|
11
|
+
def initialize(description, block)
|
12
|
+
@description = description
|
13
|
+
@block = block
|
14
|
+
@success = true
|
15
|
+
@pending = false
|
16
|
+
@expectations = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def run(runner, listeners = [])
|
20
|
+
@runner = runner
|
21
|
+
instance_eval(&@block)
|
22
|
+
@runner.reset_overrides
|
23
|
+
notify(listeners)
|
24
|
+
end
|
25
|
+
|
26
|
+
def success?
|
27
|
+
unless pending?
|
28
|
+
@expectations.all? { |expectation| expectation.success? }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def pending?
|
33
|
+
@pending
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def allow(object)
|
39
|
+
Allow.new(@runner, object)
|
40
|
+
end
|
41
|
+
|
42
|
+
def receive(message)
|
43
|
+
Receiver.new(message)
|
44
|
+
end
|
45
|
+
|
46
|
+
def double(identifier = nil, args = {})
|
47
|
+
Double.new(identifier, args)
|
48
|
+
end
|
49
|
+
|
50
|
+
def notify(listeners)
|
51
|
+
listeners.each do |listener|
|
52
|
+
listener.notify(success_state, self)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def success_state
|
57
|
+
if pending?
|
58
|
+
:pending
|
59
|
+
elsif success?
|
60
|
+
:success
|
61
|
+
else
|
62
|
+
:failure
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def pending
|
67
|
+
@success = false
|
68
|
+
@pending = true
|
69
|
+
end
|
70
|
+
|
71
|
+
def expect(object)
|
72
|
+
expectation = Expectation.new(object)
|
73
|
+
@expectations << expectation
|
74
|
+
expectation
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require "tengu/receive_matcher"
|
2
|
+
|
3
|
+
module Tengu
|
4
|
+
module Matchers
|
5
|
+
def be_true
|
6
|
+
eq(true)
|
7
|
+
end
|
8
|
+
|
9
|
+
def be_false
|
10
|
+
eq(false)
|
11
|
+
end
|
12
|
+
|
13
|
+
def be_nil
|
14
|
+
eq(nil)
|
15
|
+
end
|
16
|
+
|
17
|
+
def have_received(message)
|
18
|
+
ReceiveMatcher.new(message, "have received #{message.inspect}") { |object| object._tengu_received?(message) }
|
19
|
+
end
|
20
|
+
|
21
|
+
def include(value)
|
22
|
+
Matcher.new("include #{value.inspect}") { |object| object.include?(value) }
|
23
|
+
end
|
24
|
+
|
25
|
+
def eq(value)
|
26
|
+
Matcher.new("be eq to #{value.inspect}") { |object| object == value }
|
27
|
+
end
|
28
|
+
|
29
|
+
def eql(value)
|
30
|
+
Matcher.new("be eql to #{value.inspect}") { |object| object.eql?(value) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def equal(value)
|
34
|
+
Matcher.new("be equal to #{value.inspect}") { |object| object.equal?(value) }
|
35
|
+
end
|
36
|
+
|
37
|
+
def be(value = nil)
|
38
|
+
if value
|
39
|
+
equal(value)
|
40
|
+
else
|
41
|
+
CompositeMatcher.new
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def be_instance_of(value)
|
46
|
+
Matcher.new("be instance of #{value.inspect}") { |object| object.instance_of?(value) }
|
47
|
+
end
|
48
|
+
|
49
|
+
def be_kind_of(value)
|
50
|
+
Matcher.new("be kind of #{value.inspect}") { |object| object.kind_of?(value) }
|
51
|
+
end
|
52
|
+
|
53
|
+
def match(value)
|
54
|
+
Matcher.new("match #{value.inspect}") { |object| object =~ value }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "rake"
|
2
|
+
require "rake/tasklib"
|
3
|
+
require "tengu"
|
4
|
+
|
5
|
+
module Tengu
|
6
|
+
class RakeTask < ::Rake::TaskLib
|
7
|
+
include ::Rake::DSL if defined?(::Rake::DSL)
|
8
|
+
|
9
|
+
def initialize(name = :spec)
|
10
|
+
desc "Run tengu tests"
|
11
|
+
task name do |_, task_args|
|
12
|
+
files = Dir.glob("spec/**/*_spec.rb").map { |filename| ::File.open(filename, "r") }
|
13
|
+
formatter = Tengu::BaseFormatter.new
|
14
|
+
runner = Tengu::Runner.new
|
15
|
+
runner.run(files, [formatter])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "tengu/matcher"
|
2
|
+
|
3
|
+
module Tengu
|
4
|
+
class ReceiveMatcher < Matcher
|
5
|
+
def initialize(method_message, message, &block)
|
6
|
+
@method_message = method_message
|
7
|
+
@message = message
|
8
|
+
@with = nil
|
9
|
+
super(message, &block)
|
10
|
+
end
|
11
|
+
|
12
|
+
def with(*args)
|
13
|
+
method_message = @method_message
|
14
|
+
@block = -> (object) { object._tengu_received?(method_message, args) }
|
15
|
+
self
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'pry'
|
2
|
+
|
3
|
+
module Tengu
|
4
|
+
class Receiver
|
5
|
+
def initialize(message)
|
6
|
+
@message = message
|
7
|
+
@args = nil
|
8
|
+
@return = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def with(*args)
|
12
|
+
@args = args
|
13
|
+
self
|
14
|
+
end
|
15
|
+
|
16
|
+
def and_return(return_value)
|
17
|
+
@return = return_value
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
def setup_allow(runner, object)
|
22
|
+
unless object.respond_to?(:_tengu_received?)
|
23
|
+
object.instance_eval do
|
24
|
+
define_singleton_method(:_tengu_received) do
|
25
|
+
@_tengu_received ||= Hash.new { |hash, key| hash[key] = [] }
|
26
|
+
end
|
27
|
+
|
28
|
+
define_singleton_method(:_tengu_received?) do |message, args = []|
|
29
|
+
if args.length > 0
|
30
|
+
_tengu_received[message] && _tengu_received[message].include?(args)
|
31
|
+
else
|
32
|
+
_tengu_received.keys.include?(message)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
message = @message
|
39
|
+
return_value = @return
|
40
|
+
if object.is_a? Tengu::Double
|
41
|
+
object.instance_eval do
|
42
|
+
define_singleton_method message, -> (*args) { _tengu_received[message] << args; return_value }
|
43
|
+
end
|
44
|
+
else
|
45
|
+
original_method = object.method(@message.to_sym)
|
46
|
+
runner.record_override(object, original_method)
|
47
|
+
object.instance_eval do
|
48
|
+
define_singleton_method message, -> (*args) { _tengu_received[message] << args; return_value }
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/tengu/result.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Tengu
|
2
|
+
class Result
|
3
|
+
attr_reader :success_count, :total_count, :pending_count
|
4
|
+
|
5
|
+
def initialize(files)
|
6
|
+
@files = files
|
7
|
+
@success_count = @files.inject(0) { |sum, n| sum += n.success_count }
|
8
|
+
@total_count = @files.inject(0) { |sum, n| sum += n.test_count }
|
9
|
+
@pending_count = @files.inject(0) { |sum, n| sum += n.pending_count }
|
10
|
+
end
|
11
|
+
|
12
|
+
def failure_count
|
13
|
+
total_count - success_count
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/tengu/runner.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
module Tengu
|
2
|
+
class Runner
|
3
|
+
def initialize(options = {})
|
4
|
+
@options = options
|
5
|
+
@overrides = []
|
6
|
+
end
|
7
|
+
|
8
|
+
def record_override(object, method)
|
9
|
+
@overrides << [object, method]
|
10
|
+
end
|
11
|
+
|
12
|
+
def reset_overrides
|
13
|
+
@overrides.reverse.each do |object, method|
|
14
|
+
object.instance_eval do
|
15
|
+
define_singleton_method method.name, method
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def run(ios, formatters = [])
|
21
|
+
@files = ios.map { |io| Tengu::File.new(io) }
|
22
|
+
formatters.each { |formatter| formatter.notify(:started, self) }
|
23
|
+
@files.each { |file| file.run(self, formatters) }
|
24
|
+
result = Result.new(@files)
|
25
|
+
formatters.each { |formatter| formatter.notify(:finished, result) }
|
26
|
+
result
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/spec/allow_spec.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
describe Tengu::Allow do
|
2
|
+
include Tengu
|
3
|
+
|
4
|
+
it "sets up the receiver" do
|
5
|
+
runner = double
|
6
|
+
object = double
|
7
|
+
receiver = double
|
8
|
+
allow(receiver).to receive(:setup_allow).with(runner, object).and_return("expected")
|
9
|
+
tengu_allow = Allow.new(runner, object)
|
10
|
+
expect(tengu_allow.to(receiver)).to eq("expected")
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require "tengu"
|
2
|
+
require "stringio"
|
3
|
+
|
4
|
+
describe "BaseFormatter" do
|
5
|
+
it "prints . when notified of success" do
|
6
|
+
output = StringIO.new
|
7
|
+
formatter = Tengu::BaseFormatter.new(output)
|
8
|
+
formatter.notify(:success)
|
9
|
+
output.rewind
|
10
|
+
expect(output.read).to eq(".")
|
11
|
+
end
|
12
|
+
|
13
|
+
it "prints F when notified of failure" do
|
14
|
+
output = StringIO.new
|
15
|
+
formatter = Tengu::BaseFormatter.new(output)
|
16
|
+
formatter.notify(:failure)
|
17
|
+
output.rewind
|
18
|
+
expect(output.read).to eq("F")
|
19
|
+
end
|
20
|
+
|
21
|
+
it "prints P when notified of pending" do
|
22
|
+
output = StringIO.new
|
23
|
+
formatter = Tengu::BaseFormatter.new(output)
|
24
|
+
formatter.notify(:pending)
|
25
|
+
output.rewind
|
26
|
+
expect(output.read).to eq("P")
|
27
|
+
end
|
28
|
+
|
29
|
+
it "tracks the time" do
|
30
|
+
output = StringIO.new
|
31
|
+
formatter = Tengu::BaseFormatter.new(output)
|
32
|
+
allow(Time).to receive(:now).and_return(10)
|
33
|
+
formatter.notify(:started, nil)
|
34
|
+
allow(Time).to receive(:now).and_return(31)
|
35
|
+
result = OpenStruct.new(total_count: 0, failure_count: 0, pending_count: 0)
|
36
|
+
formatter.notify(:finished, result)
|
37
|
+
output.rewind
|
38
|
+
expect(output.read).to match(/Finished in 21.00000 seconds/)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "tracks the example count" do
|
42
|
+
allow(Time).to receive(:now).and_return(10)
|
43
|
+
output = StringIO.new
|
44
|
+
formatter = Tengu::BaseFormatter.new(output)
|
45
|
+
formatter.notify(:started, nil)
|
46
|
+
result = OpenStruct.new(total_count: 5, failure_count: 0, pending_count: 0)
|
47
|
+
formatter.notify(:finished, result)
|
48
|
+
output.rewind
|
49
|
+
expect(output.read).to match(/5 examples/)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "tracks the failure count" do
|
53
|
+
allow(Time).to receive(:now).and_return(10)
|
54
|
+
output = StringIO.new
|
55
|
+
formatter = Tengu::BaseFormatter.new(output)
|
56
|
+
formatter.notify(:started, nil)
|
57
|
+
result = OpenStruct.new(total_count: 0, failure_count: 3, pending_count: 0)
|
58
|
+
formatter.notify(:finished, result)
|
59
|
+
output.rewind
|
60
|
+
expect(output.read).to match(/3 failures/)
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
describe Tengu::CompositeMatcher do
|
2
|
+
include Tengu
|
3
|
+
|
4
|
+
it "will check existance" do
|
5
|
+
expect(CompositeMatcher.new.matches?("wombat")).to be
|
6
|
+
end
|
7
|
+
|
8
|
+
it "will check >" do
|
9
|
+
expect(5).to be > 4
|
10
|
+
expect(3).not_to be > 4
|
11
|
+
end
|
12
|
+
|
13
|
+
it "will check >=" do
|
14
|
+
expect(5).to be >= 4
|
15
|
+
expect(5).to be >= 5
|
16
|
+
expect(5).not_to be >= 6
|
17
|
+
end
|
18
|
+
|
19
|
+
it "will check <" do
|
20
|
+
expect(5).to be < 6
|
21
|
+
expect(6).not_to be < 6
|
22
|
+
end
|
23
|
+
|
24
|
+
it "will check <=" do
|
25
|
+
expect(5).to be <= 6
|
26
|
+
expect(6).to be <= 6
|
27
|
+
expect(7).not_to be <= 6
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "tengu"
|
2
|
+
|
3
|
+
describe Tengu::DescribeBlock do
|
4
|
+
include Tengu
|
5
|
+
|
6
|
+
it "evaluates the code passed in" do
|
7
|
+
test = "foo"
|
8
|
+
code = -> (wombat) { test = wombat }
|
9
|
+
block = DescribeBlock.new("test", code)
|
10
|
+
expect(test).to eq block
|
11
|
+
end
|
12
|
+
|
13
|
+
it "will include modules" do
|
14
|
+
marsupial = Module.new
|
15
|
+
code = -> (wombat) { include marsupial }
|
16
|
+
wombat = DescribeBlock.new("test", code)
|
17
|
+
expect(wombat).to be_kind_of marsupial
|
18
|
+
end
|
19
|
+
|
20
|
+
it "runs before_hooks" do
|
21
|
+
expected = -> {}
|
22
|
+
allow(expected).to receive(:call)
|
23
|
+
allow(ItBlock).to receive(:new).and_return(double(ItBlock, run: true))
|
24
|
+
code = -> (wombat) { before &expected; it {} }
|
25
|
+
DescribeBlock.new("test", code).run(nil, [])
|
26
|
+
expect(expected).to have_received(:call)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "runs after_hooks" do
|
30
|
+
expected = -> {}
|
31
|
+
allow(expected).to receive(:call)
|
32
|
+
allow(ItBlock).to receive(:new).and_return(double(ItBlock, run: true))
|
33
|
+
code = -> (wombat) { after &expected; it {} }
|
34
|
+
DescribeBlock.new("test", code).run(nil, [])
|
35
|
+
expect(expected).to have_received(:call)
|
36
|
+
end
|
37
|
+
end
|
data/spec/double_spec.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
describe Tengu::Expectation do
|
2
|
+
include Tengu
|
3
|
+
|
4
|
+
it "sets success to true on postive match" do
|
5
|
+
expectation = Expectation.new("wombat")
|
6
|
+
matcher = double(Matcher, matches?: true)
|
7
|
+
expectation.to(matcher)
|
8
|
+
expect(expectation.success?).to be_true
|
9
|
+
end
|
10
|
+
|
11
|
+
it "sets success to false on postive mismatch" do
|
12
|
+
expectation = Expectation.new("wombat")
|
13
|
+
matcher = double(Matcher, matches?: false)
|
14
|
+
expectation.to(matcher)
|
15
|
+
expect(expectation.success?).to be_false
|
16
|
+
end
|
17
|
+
|
18
|
+
it "sets success to true on negative mismatch" do
|
19
|
+
expectation = Expectation.new("wombat")
|
20
|
+
matcher = double(Matcher, matches?: false)
|
21
|
+
expectation.not_to(matcher)
|
22
|
+
expect(expectation.success?).to be_true
|
23
|
+
end
|
24
|
+
|
25
|
+
it "sets success to false on negative match" do
|
26
|
+
expectation = Expectation.new("wombat")
|
27
|
+
matcher = double(Matcher, matches?: true)
|
28
|
+
expectation.not_to(matcher)
|
29
|
+
expect(expectation.success?).to be_false
|
30
|
+
end
|
31
|
+
|
32
|
+
it "returns a formatted positive message" do
|
33
|
+
expectation = Expectation.new("wombat")
|
34
|
+
expectation.to(double(Matcher, matches?: true, description: "win"))
|
35
|
+
expect(expectation.message).to eq 'expected "wombat" to win'
|
36
|
+
end
|
37
|
+
|
38
|
+
it "returns a formatted negative message" do
|
39
|
+
expectation = Expectation.new("numbat")
|
40
|
+
expectation.not_to(double(Matcher, matches?: true, description: "win"))
|
41
|
+
expect(expectation.message).to eq 'expected "numbat" not to win'
|
42
|
+
end
|
43
|
+
end
|
data/spec/file_spec.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'pry'
|
2
|
+
|
3
|
+
describe Tengu::File do
|
4
|
+
include Tengu
|
5
|
+
|
6
|
+
it "reads the tests" do
|
7
|
+
code = double(File, read: "describe('test') {}")
|
8
|
+
file = File.new(code)
|
9
|
+
expect(code).to have_received(:read)
|
10
|
+
end
|
11
|
+
|
12
|
+
it "runs the tests" do
|
13
|
+
describe_block = double(DescribeBlock, run: true)
|
14
|
+
allow(DescribeBlock).to receive(:new).and_return(describe_block)
|
15
|
+
code = double(File, read: "describe('test') {}")
|
16
|
+
file = File.new(code)
|
17
|
+
runner = double
|
18
|
+
file.run(runner)
|
19
|
+
expect(describe_block).to have_received(:run).with(runner, [])
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns the success count" do
|
23
|
+
describe_block = double(DescribeBlock, run: true, success_count: 5)
|
24
|
+
allow(DescribeBlock).to receive(:new).and_return(describe_block)
|
25
|
+
code = double(File, read: "describe('test') {}")
|
26
|
+
file = File.new(code)
|
27
|
+
file.run(double)
|
28
|
+
expect(file.success_count).to eq 5
|
29
|
+
end
|
30
|
+
|
31
|
+
it "returns the test count" do
|
32
|
+
describe_block = double(DescribeBlock, run: true, test_count: 7)
|
33
|
+
allow(DescribeBlock).to receive(:new).and_return(describe_block)
|
34
|
+
code = double(File, read: "describe('test') {}")
|
35
|
+
file = File.new(code)
|
36
|
+
file.run(double)
|
37
|
+
expect(file.test_count).to eq 7
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
$foo = "bar"
|
2
|
+
|
3
|
+
describe "True" do
|
4
|
+
before do
|
5
|
+
$foo = "baz"
|
6
|
+
end
|
7
|
+
|
8
|
+
it "is true" do
|
9
|
+
expect($foo).to eq("baz")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "includes pending" do
|
13
|
+
pending
|
14
|
+
end
|
15
|
+
|
16
|
+
xit "skips others" do
|
17
|
+
expect($foo).to eq("bar")
|
18
|
+
end
|
19
|
+
|
20
|
+
after do
|
21
|
+
$foo = "bar"
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
describe Tengu::ItBlock do
|
2
|
+
it "runs the tests" do
|
3
|
+
pending
|
4
|
+
end
|
5
|
+
|
6
|
+
it "resets the overrides" do
|
7
|
+
pending
|
8
|
+
end
|
9
|
+
|
10
|
+
it "notifies the listeners" do
|
11
|
+
pending
|
12
|
+
end
|
13
|
+
|
14
|
+
it "returns success" do
|
15
|
+
pending
|
16
|
+
end
|
17
|
+
|
18
|
+
it "returns pending" do
|
19
|
+
pending
|
20
|
+
end
|
21
|
+
end
|
data/spec/result_spec.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
describe Tengu::Result do
|
2
|
+
include Tengu
|
3
|
+
|
4
|
+
it "determines the success count" do
|
5
|
+
pending
|
6
|
+
end
|
7
|
+
|
8
|
+
it "determines the total count" do
|
9
|
+
pending
|
10
|
+
end
|
11
|
+
|
12
|
+
it "determines the pending count" do
|
13
|
+
pending
|
14
|
+
end
|
15
|
+
|
16
|
+
it "determines the failure count" do
|
17
|
+
pending
|
18
|
+
end
|
19
|
+
end
|
data/spec/runner_spec.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
describe Tengu::Runner do
|
2
|
+
include Tengu
|
3
|
+
|
4
|
+
it "records the overrides" do
|
5
|
+
pending
|
6
|
+
end
|
7
|
+
|
8
|
+
it "resets the overrides" do
|
9
|
+
pending
|
10
|
+
end
|
11
|
+
|
12
|
+
it "notifies the listeners" do
|
13
|
+
pending
|
14
|
+
end
|
15
|
+
|
16
|
+
it "runs the files" do
|
17
|
+
pending
|
18
|
+
end
|
19
|
+
end
|
data/spec/tengu_spec.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "tengu"
|
2
|
+
|
3
|
+
describe "Tengu" do
|
4
|
+
it "will .test a particular file" do
|
5
|
+
file_path = "test"
|
6
|
+
fake_file = double(::File)
|
7
|
+
fake_runner = double(Tengu::Runner)
|
8
|
+
allow(::File).to receive(:open).with(file_path, "r").and_return(fake_file)
|
9
|
+
allow(Tengu::Runner).to receive(:new).and_return(fake_runner)
|
10
|
+
allow(fake_runner).to receive(:run).with([fake_file], []).and_return("expected")
|
11
|
+
expect(Tengu.test(file_path)).to eq("expected")
|
12
|
+
end
|
13
|
+
end
|
data/tengu.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'tengu/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "tengu"
|
8
|
+
spec.version = Tengu::VERSION
|
9
|
+
spec.authors = ["halogenandtoast"]
|
10
|
+
spec.email = ["halogenandtoast@gmail.com"]
|
11
|
+
spec.description = %q{A truly object oriented testing library}
|
12
|
+
spec.summary = %q{A truly object oriented testing library}
|
13
|
+
spec.homepage = "http://github.com/halogenandtoast/tengu"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
22
|
+
spec.add_development_dependency "rake"
|
23
|
+
spec.add_development_dependency "rspec"
|
24
|
+
spec.add_development_dependency "pry"
|
25
|
+
end
|
metadata
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tengu
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- halogenandtoast
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-01-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
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: rspec
|
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: pry
|
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
|
+
description: A truly object oriented testing library
|
70
|
+
email:
|
71
|
+
- halogenandtoast@gmail.com
|
72
|
+
executables:
|
73
|
+
- tengu
|
74
|
+
extensions: []
|
75
|
+
extra_rdoc_files: []
|
76
|
+
files:
|
77
|
+
- .gitignore
|
78
|
+
- Gemfile
|
79
|
+
- LICENSE.txt
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- bin/tengu
|
83
|
+
- lib/tengu.rb
|
84
|
+
- lib/tengu/allow.rb
|
85
|
+
- lib/tengu/base_formatter.rb
|
86
|
+
- lib/tengu/composite_matcher.rb
|
87
|
+
- lib/tengu/describe_block.rb
|
88
|
+
- lib/tengu/double.rb
|
89
|
+
- lib/tengu/expectation.rb
|
90
|
+
- lib/tengu/file.rb
|
91
|
+
- lib/tengu/it_block.rb
|
92
|
+
- lib/tengu/matcher.rb
|
93
|
+
- lib/tengu/matchers.rb
|
94
|
+
- lib/tengu/rake_task.rb
|
95
|
+
- lib/tengu/receive_matcher.rb
|
96
|
+
- lib/tengu/receiver.rb
|
97
|
+
- lib/tengu/result.rb
|
98
|
+
- lib/tengu/runner.rb
|
99
|
+
- lib/tengu/version.rb
|
100
|
+
- spec/allow_spec.rb
|
101
|
+
- spec/base_formatter_spec.rb
|
102
|
+
- spec/composite_matcher_spec.rb
|
103
|
+
- spec/describe_block_spec.rb
|
104
|
+
- spec/double_spec.rb
|
105
|
+
- spec/expectation_spec.rb
|
106
|
+
- spec/file_spec.rb
|
107
|
+
- spec/fixtures/example.rb
|
108
|
+
- spec/it_block_spec.rb
|
109
|
+
- spec/matcher_spec.rb
|
110
|
+
- spec/receive_matcher_spec.rb
|
111
|
+
- spec/receiver_spec.rb
|
112
|
+
- spec/result_spec.rb
|
113
|
+
- spec/runner_spec.rb
|
114
|
+
- spec/tengu_spec.rb
|
115
|
+
- tengu.gemspec
|
116
|
+
homepage: http://github.com/halogenandtoast/tengu
|
117
|
+
licenses:
|
118
|
+
- MIT
|
119
|
+
metadata: {}
|
120
|
+
post_install_message:
|
121
|
+
rdoc_options: []
|
122
|
+
require_paths:
|
123
|
+
- lib
|
124
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - '>='
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
requirements: []
|
135
|
+
rubyforge_project:
|
136
|
+
rubygems_version: 2.0.3
|
137
|
+
signing_key:
|
138
|
+
specification_version: 4
|
139
|
+
summary: A truly object oriented testing library
|
140
|
+
test_files:
|
141
|
+
- spec/allow_spec.rb
|
142
|
+
- spec/base_formatter_spec.rb
|
143
|
+
- spec/composite_matcher_spec.rb
|
144
|
+
- spec/describe_block_spec.rb
|
145
|
+
- spec/double_spec.rb
|
146
|
+
- spec/expectation_spec.rb
|
147
|
+
- spec/file_spec.rb
|
148
|
+
- spec/fixtures/example.rb
|
149
|
+
- spec/it_block_spec.rb
|
150
|
+
- spec/matcher_spec.rb
|
151
|
+
- spec/receive_matcher_spec.rb
|
152
|
+
- spec/receiver_spec.rb
|
153
|
+
- spec/result_spec.rb
|
154
|
+
- spec/runner_spec.rb
|
155
|
+
- spec/tengu_spec.rb
|
156
|
+
has_rdoc:
|