test_runner-assert 0.1.0
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/lib/test_runner/assert.rb +21 -0
- data/lib/test_runner/assert/assertion.rb +116 -0
- data/lib/test_runner/assert/check.rb +53 -0
- data/lib/test_runner/assert/checks.rb +76 -0
- data/lib/test_runner/assert/checks/registry.rb +31 -0
- data/lib/test_runner/assert/errors.rb +46 -0
- data/lib/test_runner/assert/syntax.rb +94 -0
- data/lib/test_runner/plugin.rb +1 -0
- metadata +65 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f2ad4a61cd4c9e7215b788fc7e00d56c845ea72c
|
4
|
+
data.tar.gz: 3b875c966207c7deccf95176bf046202c8aafa6f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f9e864c1933698e42c931e154a4b81fd1fd06b9fc17c636e561622574c9a7e5ea6c025df3a91d588c27da46d272a349ab3f1f51629850e5a67babe506b0fbb07
|
7
|
+
data.tar.gz: b7a313ef50f282b5705ee14518b14e2465a7e6efc592d28e7aaafec2fc0bd5b49cacfa213b04ddc9a0a564b0f44a4c1a7bf85e3e8f1f156da9ed1715919ded18
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require "test_runner"
|
2
|
+
|
3
|
+
require_relative "assert/assertion"
|
4
|
+
require_relative "assert/check"
|
5
|
+
require_relative "assert/checks"
|
6
|
+
require_relative "assert/errors"
|
7
|
+
require_relative "assert/syntax"
|
8
|
+
|
9
|
+
module TestRunner
|
10
|
+
module Assert
|
11
|
+
def self.inspect object, truncate = 100
|
12
|
+
raw = object.inspect
|
13
|
+
return raw if raw.size <= truncate
|
14
|
+
"#{raw[0..truncate - 2]} …\""
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.included target
|
19
|
+
Assert::Syntax.infect target
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
module TestRunner
|
2
|
+
module Assert
|
3
|
+
class Assertion
|
4
|
+
attr_reader :fails
|
5
|
+
attr_reader :passes
|
6
|
+
attr_accessor :source
|
7
|
+
|
8
|
+
def initialize subject_proc, checks
|
9
|
+
@subject_proc = subject_proc
|
10
|
+
@checks = checks
|
11
|
+
@passes = []
|
12
|
+
@fails = []
|
13
|
+
@trace = caller_locations
|
14
|
+
end
|
15
|
+
|
16
|
+
def call
|
17
|
+
perform_checks
|
18
|
+
freeze
|
19
|
+
raise to_error if failed?
|
20
|
+
subject
|
21
|
+
end
|
22
|
+
|
23
|
+
def build_checks
|
24
|
+
@checks.map do |check_name, argument|
|
25
|
+
TestRunner::Config.internal_logger.debug "Resolving check #{check_name.inspect}, arg=#{argument.inspect}"
|
26
|
+
resolve_check check_name, argument
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def failed?
|
31
|
+
fails.any?
|
32
|
+
end
|
33
|
+
|
34
|
+
def file
|
35
|
+
@trace[0].path
|
36
|
+
end
|
37
|
+
|
38
|
+
def freeze
|
39
|
+
passes.freeze
|
40
|
+
fails.freeze
|
41
|
+
end
|
42
|
+
|
43
|
+
def line
|
44
|
+
@trace[0].lineno
|
45
|
+
end
|
46
|
+
|
47
|
+
def passed?
|
48
|
+
not failed?
|
49
|
+
end
|
50
|
+
|
51
|
+
def perform_checks
|
52
|
+
build_checks.each do |check|
|
53
|
+
check.evaluate
|
54
|
+
ary = if check.passed? then passes else fails end
|
55
|
+
ary.push check
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def resolve_check check_name, argument
|
60
|
+
check = Checks.resolve check_name do
|
61
|
+
check_name = :include if check_name == :includes
|
62
|
+
argument = [check_name, *argument]
|
63
|
+
Checks[:predicate]
|
64
|
+
end
|
65
|
+
check.new subject_thunk, argument
|
66
|
+
end
|
67
|
+
|
68
|
+
def subject
|
69
|
+
subject_thunk.call
|
70
|
+
end
|
71
|
+
|
72
|
+
def subject_thunk
|
73
|
+
@subject_thunk ||= SubjectThunk.new @subject_proc
|
74
|
+
end
|
75
|
+
|
76
|
+
def to_error
|
77
|
+
AssertionFailed.new self
|
78
|
+
end
|
79
|
+
|
80
|
+
def trace
|
81
|
+
BacktraceFilter.(@trace)
|
82
|
+
end
|
83
|
+
|
84
|
+
class Refutation < Assertion
|
85
|
+
def build_checks
|
86
|
+
super.each &:negate
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class SubjectThunk
|
91
|
+
def initialize block
|
92
|
+
@block = block
|
93
|
+
end
|
94
|
+
|
95
|
+
def call
|
96
|
+
return @subject if subject_resolved?
|
97
|
+
@subject = @block.call
|
98
|
+
end
|
99
|
+
|
100
|
+
def expect_error
|
101
|
+
raise "called after initially fetched" if subject_resolved?
|
102
|
+
@block.call
|
103
|
+
nothing_raised = true
|
104
|
+
rescue => error
|
105
|
+
@subject = error
|
106
|
+
ensure
|
107
|
+
raise NothingRaised.new if nothing_raised
|
108
|
+
end
|
109
|
+
|
110
|
+
def subject_resolved?
|
111
|
+
instance_variable_defined? :@subject
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module TestRunner
|
2
|
+
module Assert
|
3
|
+
class Check
|
4
|
+
singleton_class.send :attr_reader, :block, :name
|
5
|
+
|
6
|
+
attr :argument
|
7
|
+
|
8
|
+
def initialize subject_thunk, argument
|
9
|
+
@argument = argument
|
10
|
+
@subject_thunk = subject_thunk
|
11
|
+
end
|
12
|
+
|
13
|
+
def evaluate
|
14
|
+
self.class.block.call self, @argument
|
15
|
+
freeze
|
16
|
+
end
|
17
|
+
|
18
|
+
def expect_error
|
19
|
+
@subject_thunk.expect_error
|
20
|
+
end
|
21
|
+
|
22
|
+
def fail message
|
23
|
+
passed = negated? ^ yield
|
24
|
+
@fail_message = message unless passed
|
25
|
+
end
|
26
|
+
|
27
|
+
def fail_message
|
28
|
+
"expected #{Assert.inspect subject} to#{" not" if negated?} #{@fail_message}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def failed?
|
32
|
+
@fail_message ? true : false
|
33
|
+
end
|
34
|
+
|
35
|
+
def negated?
|
36
|
+
@negated ? true : false
|
37
|
+
end
|
38
|
+
|
39
|
+
def negate
|
40
|
+
@negated = !@negated
|
41
|
+
end
|
42
|
+
|
43
|
+
def passed?
|
44
|
+
not failed?
|
45
|
+
end
|
46
|
+
|
47
|
+
def subject
|
48
|
+
@expected_error or @subject_thunk.call
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module TestRunner
|
2
|
+
module Assert
|
3
|
+
module Checks
|
4
|
+
require_relative "checks/registry"
|
5
|
+
extend Registry
|
6
|
+
|
7
|
+
register :equals do |check, object|
|
8
|
+
obj_inspect = Assert.inspect object
|
9
|
+
|
10
|
+
if Assert.inspect(check.subject) == obj_inspect and not check.negated?
|
11
|
+
fail_message = "equal other object (no difference in #inspect output)"
|
12
|
+
else
|
13
|
+
fail_message = "equal #{obj_inspect}"
|
14
|
+
end
|
15
|
+
|
16
|
+
check.fail fail_message do check.subject == object end
|
17
|
+
end
|
18
|
+
|
19
|
+
register :included_in do |check, list|
|
20
|
+
check.fail "be included in #{Assert.inspect list}" do
|
21
|
+
list.include? check.subject
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
register :kind_of do |check, type|
|
26
|
+
check.fail "be a kind of #{type}" do
|
27
|
+
check.subject.kind_of? type
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
register :matches do |check, matcher|
|
32
|
+
check.fail "match #{Assert.inspect matcher}" do
|
33
|
+
check.subject.match matcher
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
register :predicate do |check, argument|
|
38
|
+
name, *args = argument
|
39
|
+
method_name = "#{name}?"
|
40
|
+
method = check.subject.method method_name
|
41
|
+
|
42
|
+
if method.arity == 0
|
43
|
+
expect_truth = args.all?
|
44
|
+
message = "be #{name}"
|
45
|
+
result = check.subject.public_send method_name
|
46
|
+
result = result ^ !expect_truth
|
47
|
+
else
|
48
|
+
result = check.subject.public_send method_name, *args
|
49
|
+
args = args.map &Assert.method(:inspect)
|
50
|
+
message = "#{name} #{args * ', '}"
|
51
|
+
end
|
52
|
+
|
53
|
+
check.fail message do result end
|
54
|
+
end
|
55
|
+
|
56
|
+
register :raises do |check, error_type|
|
57
|
+
check.expect_error
|
58
|
+
check.fail "be a #{Assert.inspect error_type}" do
|
59
|
+
check.subject.is_a? error_type
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
register :responds_to do |check, method_name|
|
64
|
+
check.fail "respond to ##{method_name}" do
|
65
|
+
check.subject.respond_to? method_name
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
register :truthy do |check, arg|
|
70
|
+
check.fail "be #{arg ? "truthy" : "falsey"}" do
|
71
|
+
!arg ^ check.subject
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module TestRunner
|
2
|
+
module Assert
|
3
|
+
module Checks
|
4
|
+
module Registry
|
5
|
+
def self.extended base
|
6
|
+
base.instance_variable_set :@registry, {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.define check_name, block
|
10
|
+
klass = Class.new Check
|
11
|
+
klass.instance_variable_set :@block, block
|
12
|
+
constant_name = Util.to_camel_case check_name
|
13
|
+
const_set constant_name, klass
|
14
|
+
klass
|
15
|
+
end
|
16
|
+
|
17
|
+
attr :registry
|
18
|
+
|
19
|
+
def register check_name, &block
|
20
|
+
registry[check_name] = Registry.define check_name, block
|
21
|
+
end
|
22
|
+
|
23
|
+
def resolve check_name, &block
|
24
|
+
block ||= -> * do raise MissingCheck.new check_name end
|
25
|
+
registry.fetch check_name, &block
|
26
|
+
end
|
27
|
+
alias_method :[], :resolve
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module TestRunner
|
2
|
+
module Assert
|
3
|
+
Error ||= Class.new StandardError
|
4
|
+
|
5
|
+
class AssertionFailed < Error
|
6
|
+
attr :assertion
|
7
|
+
|
8
|
+
def initialize assertion
|
9
|
+
@assertion = assertion
|
10
|
+
end
|
11
|
+
|
12
|
+
def backtrace
|
13
|
+
assertion.trace.map &:to_s
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
failures = assertion.fails.map do |failed_check|
|
18
|
+
failed_check.fail_message
|
19
|
+
end
|
20
|
+
if failures.size > 1
|
21
|
+
"Assertion failure:\n\n * #{failures * "\n * "}\n"
|
22
|
+
else
|
23
|
+
"Assertion failure: #{failures * ", "}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class MissingCheck < Error
|
29
|
+
attr :check_name
|
30
|
+
|
31
|
+
def initialize check_name
|
32
|
+
@check_name = check_name
|
33
|
+
end
|
34
|
+
|
35
|
+
def to_s
|
36
|
+
"could not resolve check #{check_name.inspect}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class NothingRaised < Error
|
41
|
+
def to_s
|
42
|
+
"expected subject block to raise an error"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module TestRunner
|
2
|
+
module Assert
|
3
|
+
class Syntax < Module
|
4
|
+
MISSING = :__test_runner_assert_arg_missing__
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def infect target
|
8
|
+
instance = new
|
9
|
+
if target.is_a? Class
|
10
|
+
target.send :include, instance
|
11
|
+
else
|
12
|
+
target.extend instance
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Public: assert is designed to be called a number of different ways,
|
17
|
+
# from 0 to 2 positional arguments, and maybe a block.
|
18
|
+
#
|
19
|
+
# subject_or_checks - the first optional argument passed in
|
20
|
+
# checks - the second optional argument passed in
|
21
|
+
# block - the &block parameter
|
22
|
+
#
|
23
|
+
# Valid examples:
|
24
|
+
#
|
25
|
+
# assert :raises => Error do … end
|
26
|
+
# assert "foo"
|
27
|
+
# assert 3, :included_in => [6, 3]
|
28
|
+
# assert [6, 3], :includes => 3
|
29
|
+
# assert :equal => 4 do 2 + 2 end
|
30
|
+
#
|
31
|
+
# Invalid examples:
|
32
|
+
#
|
33
|
+
# # Can't determine if the block or 2 is the subject
|
34
|
+
# assert 2, :equals => 4 do ̒… end
|
35
|
+
# # There's no subject at all
|
36
|
+
# assert :incuded_in => 4
|
37
|
+
#
|
38
|
+
# Returns two arguments, the subject, and a checks hash. If the checks
|
39
|
+
# would be empty, returns { :truthy => true }. The subject will always be
|
40
|
+
# a Proc that gets lazy evaluated when the assertion is checked.
|
41
|
+
def decode_assert_arguments subject_or_checks, checks, block
|
42
|
+
if checks == MISSING
|
43
|
+
if subject_or_checks == MISSING
|
44
|
+
missing_subject! unless block
|
45
|
+
subject_thunk = block
|
46
|
+
checks = { :truthy => true }
|
47
|
+
elsif block
|
48
|
+
ambiguous_subject! unless subject_or_checks.is_a? Hash
|
49
|
+
subject_thunk = block
|
50
|
+
checks = subject_or_checks
|
51
|
+
else
|
52
|
+
subject_thunk = -> do subject_or_checks end
|
53
|
+
checks = { :truthy => true }
|
54
|
+
end
|
55
|
+
else
|
56
|
+
ambiguous_subject! if block
|
57
|
+
subject_thunk = -> do subject_or_checks end
|
58
|
+
end
|
59
|
+
[subject_thunk, checks]
|
60
|
+
end
|
61
|
+
|
62
|
+
def ambiguous_subject!
|
63
|
+
raise ArgumentError, "cannot supply a block subject *and* a positional subject"
|
64
|
+
end
|
65
|
+
|
66
|
+
def missing_subject!
|
67
|
+
raise ArgumentError, "must supply either a positional subject *or* a block subject (but not both)"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def extended base
|
72
|
+
graft base.singleton_class
|
73
|
+
end
|
74
|
+
|
75
|
+
def included base
|
76
|
+
graft base
|
77
|
+
end
|
78
|
+
|
79
|
+
def graft base
|
80
|
+
method_body = -> method_name, assertion_class, syntax do
|
81
|
+
define_method method_name do |arg1 = MISSING, arg2 = MISSING, &block|
|
82
|
+
subject_thunk, checks = syntax.decode_assert_arguments arg1, arg2, block
|
83
|
+
assertion = assertion_class.new subject_thunk, checks
|
84
|
+
assertion.source = self
|
85
|
+
assertion.()
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
base.class_exec :assert, Assertion, self.class, &method_body
|
90
|
+
base.class_exec :refute, Assertion::Refutation, self.class, &method_body
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require "test_runner/assert"
|
metadata
ADDED
@@ -0,0 +1,65 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: test_runner-assert
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nathan Ladd
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-09-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: test-runner
|
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
|
+
description: Adds a powerful and simple assert implementation to test-runner
|
28
|
+
email: nathanladd+github@gmail.com
|
29
|
+
executables: []
|
30
|
+
extensions: []
|
31
|
+
extra_rdoc_files: []
|
32
|
+
files:
|
33
|
+
- lib/test_runner/assert.rb
|
34
|
+
- lib/test_runner/assert/assertion.rb
|
35
|
+
- lib/test_runner/assert/check.rb
|
36
|
+
- lib/test_runner/assert/checks.rb
|
37
|
+
- lib/test_runner/assert/checks/registry.rb
|
38
|
+
- lib/test_runner/assert/errors.rb
|
39
|
+
- lib/test_runner/assert/syntax.rb
|
40
|
+
- lib/test_runner/plugin.rb
|
41
|
+
homepage: https://github.com/ntl/test-runner
|
42
|
+
licenses:
|
43
|
+
- MIT
|
44
|
+
metadata: {}
|
45
|
+
post_install_message:
|
46
|
+
rdoc_options: []
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
requirements: []
|
60
|
+
rubyforge_project:
|
61
|
+
rubygems_version: 2.4.5.1
|
62
|
+
signing_key:
|
63
|
+
specification_version: 4
|
64
|
+
summary: Adds a powerful and simple assert implementation to test-runner
|
65
|
+
test_files: []
|