suture 1.1.1 → 1.2.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 +5 -5
- data/.github/workflows/main.yml +31 -0
- data/.gitignore +1 -1
- data/.standard.yml +7 -0
- data/CHANGELOG.md +32 -3
- data/Gemfile +9 -1
- data/Gemfile.lock +120 -0
- data/README.md +38 -25
- data/Rakefile +15 -48
- data/bin/console +0 -4
- data/lib/suture/adapter/dictaphone.rb +1 -2
- data/lib/suture/comparator.rb +4 -4
- data/lib/suture/create/builds_plan.rb +6 -6
- data/lib/suture/create/chooses_surgeon.rb +1 -1
- data/lib/suture/create/validates_plan.rb +10 -10
- data/lib/suture/error/invalid_plan.rb +6 -6
- data/lib/suture/error/observation_conflict.rb +1 -1
- data/lib/suture/error/result_mismatch.rb +1 -1
- data/lib/suture/error/schema_version.rb +1 -1
- data/lib/suture/error/verification_failed.rb +11 -13
- data/lib/suture/reset.rb +0 -1
- data/lib/suture/surgeon/auditor.rb +5 -7
- data/lib/suture/surgeon/no_op.rb +1 -1
- data/lib/suture/surgeon/observer.rb +2 -3
- data/lib/suture/surgeon/remediator.rb +6 -8
- data/lib/suture/util/compares_results.rb +1 -1
- data/lib/suture/util/env.rb +5 -5
- data/lib/suture/util/scalpel.rb +5 -6
- data/lib/suture/util/shuffle.rb +1 -1
- data/lib/suture/value/observation.rb +1 -1
- data/lib/suture/value/plan.rb +4 -4
- data/lib/suture/value/result.rb +1 -1
- data/lib/suture/value/test_plan.rb +12 -12
- data/lib/suture/value/test_results.rb +0 -1
- data/lib/suture/verify/administers_test.rb +2 -2
- data/lib/suture/verify/interprets_results.rb +0 -2
- data/lib/suture/verify/prescribes_test_plan.rb +5 -5
- data/lib/suture/verify/tests_patient.rb +2 -3
- data/lib/suture/verify.rb +0 -1
- data/lib/suture/version.rb +1 -1
- data/lib/suture/wrap/logger.rb +35 -15
- data/lib/suture/wrap/sqlite.rb +2 -2
- data/lib/suture.rb +0 -1
- data/suture.gemspec +14 -27
- metadata +8 -108
- data/.travis.yml +0 -15
|
@@ -3,36 +3,36 @@ module Suture::Error
|
|
|
3
3
|
HEADER = "Suture was unable to create your seam, because options passed to `Suture.create` were invalid."
|
|
4
4
|
|
|
5
5
|
def self.missing_requirements(requirements)
|
|
6
|
-
new <<-MSG.gsub(/^ {8}/,
|
|
6
|
+
new <<-MSG.gsub(/^ {8}/, "")
|
|
7
7
|
#{HEADER}
|
|
8
8
|
|
|
9
9
|
The following options are required:
|
|
10
10
|
|
|
11
|
-
#{requirements.map {|(name,explanation)|
|
|
11
|
+
#{requirements.map { |(name, explanation)|
|
|
12
12
|
"* #{name.inspect} - #{explanation}"
|
|
13
13
|
}.join("\n ")}
|
|
14
14
|
MSG
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def self.invalid_options(invalids)
|
|
18
|
-
new <<-MSG.gsub(/^ {8}/,
|
|
18
|
+
new <<-MSG.gsub(/^ {8}/, "")
|
|
19
19
|
#{HEADER}
|
|
20
20
|
|
|
21
21
|
The following options were invalid:
|
|
22
22
|
|
|
23
|
-
#{invalids.map {|(name,rule)|
|
|
23
|
+
#{invalids.map { |(name, rule)|
|
|
24
24
|
"* #{name.inspect} - #{rule[:message]}"
|
|
25
25
|
}.join("\n ")}
|
|
26
26
|
MSG
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def self.conflicting_options(conflicts)
|
|
30
|
-
new <<-MSG.gsub(/^ {8}/,
|
|
30
|
+
new <<-MSG.gsub(/^ {8}/, "")
|
|
31
31
|
#{HEADER}
|
|
32
32
|
|
|
33
33
|
Suture isn't sure how to best handle the combination of options passed:
|
|
34
34
|
|
|
35
|
-
#{conflicts.map {|message|
|
|
35
|
+
#{conflicts.map { |message|
|
|
36
36
|
"* #{message}"
|
|
37
37
|
}.join("\n ")}
|
|
38
38
|
MSG
|
|
@@ -7,7 +7,7 @@ module Suture::Error
|
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
def message
|
|
10
|
-
<<-MSG.gsub(/^ {8}/,
|
|
10
|
+
<<-MSG.gsub(/^ {8}/, "")
|
|
11
11
|
The results from the old & new code paths did not match for the seam
|
|
12
12
|
#{@plan.name.inspect} and Suture is raising this error because the `:call_both`
|
|
13
13
|
option is enabled, because both code paths are expected to return the
|
|
@@ -6,7 +6,7 @@ module Suture::Error
|
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
def message
|
|
9
|
-
"Your suture gem is too #{@expected > @actual ? "new" : "old"} for this schema. Either delete your database or #{@expected > @actual ? "upgrade" : "downgrade"} the gem (expected schema version #{@expected}, was #{@actual})"
|
|
9
|
+
"Your suture gem is too #{(@expected > @actual) ? "new" : "old"} for this schema. Either delete your database or #{(@expected > @actual) ? "upgrade" : "downgrade"} the gem (expected schema version #{@expected}, was #{@actual})"
|
|
10
10
|
end
|
|
11
11
|
end
|
|
12
12
|
end
|
|
@@ -22,7 +22,7 @@ module Suture::Error
|
|
|
22
22
|
private
|
|
23
23
|
|
|
24
24
|
def intro
|
|
25
|
-
<<-MSG.gsub(/^ {8}/,
|
|
25
|
+
<<-MSG.gsub(/^ {8}/, "")
|
|
26
26
|
|
|
27
27
|
# Verification of your seam failed!
|
|
28
28
|
|
|
@@ -31,7 +31,7 @@ module Suture::Error
|
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def summarize(results)
|
|
34
|
-
<<-MSG.gsub(/^ {8}/,
|
|
34
|
+
<<-MSG.gsub(/^ {8}/, "")
|
|
35
35
|
# Result Summary
|
|
36
36
|
|
|
37
37
|
- Passed........#{results.passed_count}
|
|
@@ -49,7 +49,7 @@ module Suture::Error
|
|
|
49
49
|
results.all.size
|
|
50
50
|
)
|
|
51
51
|
percent = Suture::Util::Numbers.percent(results.passed.size, results.all.size)
|
|
52
|
-
<<-MSG.gsub(/^ {8}/,
|
|
52
|
+
<<-MSG.gsub(/^ {8}/, "")
|
|
53
53
|
## Progress
|
|
54
54
|
|
|
55
55
|
Here's what your progress to initial completion looks like so far:
|
|
@@ -61,7 +61,7 @@ module Suture::Error
|
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
def configuration(plan)
|
|
64
|
-
<<-MSG.gsub(/^ {8}/,
|
|
64
|
+
<<-MSG.gsub(/^ {8}/, "")
|
|
65
65
|
# Configuration
|
|
66
66
|
|
|
67
67
|
This is the configuration used by this test run:
|
|
@@ -81,7 +81,7 @@ module Suture::Error
|
|
|
81
81
|
end
|
|
82
82
|
|
|
83
83
|
def describe_comparator(comparator)
|
|
84
|
-
if comparator.
|
|
84
|
+
if comparator.is_a?(Proc)
|
|
85
85
|
"Proc # (in: `#{describe_source_location(*comparator.source_location)}`)"
|
|
86
86
|
elsif comparator.respond_to?(:method) && comparator.method(:call)
|
|
87
87
|
"#{comparator.inspect}.new, # (in: `#{describe_source_location(*comparator.method(:call).source_location)}`)"
|
|
@@ -90,7 +90,7 @@ module Suture::Error
|
|
|
90
90
|
|
|
91
91
|
def describe_source_location(file, line)
|
|
92
92
|
root = File.join(Dir.getwd, "/")
|
|
93
|
-
path = file.start_with?(root) ? file.gsub(root,
|
|
93
|
+
path = file.start_with?(root) ? file.gsub(root, "") : file
|
|
94
94
|
"#{path}:#{line}"
|
|
95
95
|
end
|
|
96
96
|
|
|
@@ -108,7 +108,7 @@ module Suture::Error
|
|
|
108
108
|
|
|
109
109
|
def describe_failure(failure, index)
|
|
110
110
|
expected = failure[:observation]
|
|
111
|
-
|
|
111
|
+
<<-MSG.gsub(/^ {8}/, "")
|
|
112
112
|
#{index + 1}.) Recorded call for seam #{expected.name.inspect} (ID: #{expected.id}) ran and #{failure[:error] ? "raised an error" : "failed comparison"}.
|
|
113
113
|
|
|
114
114
|
Arguments: ```
|
|
@@ -122,8 +122,7 @@ module Suture::Error
|
|
|
122
122
|
stringify_error(failure[:error])
|
|
123
123
|
else
|
|
124
124
|
failure[:new_result].value.inspect
|
|
125
|
-
end
|
|
126
|
-
}
|
|
125
|
+
end}
|
|
127
126
|
```
|
|
128
127
|
|
|
129
128
|
Ideas to fix this:
|
|
@@ -138,7 +137,7 @@ module Suture::Error
|
|
|
138
137
|
end
|
|
139
138
|
|
|
140
139
|
def describe_general_failure_advice(plan)
|
|
141
|
-
<<-MSG.gsub(/^ {8}/,
|
|
140
|
+
<<-MSG.gsub(/^ {8}/, "")
|
|
142
141
|
### Fixing these failures
|
|
143
142
|
|
|
144
143
|
#### Custom comparator
|
|
@@ -156,7 +155,7 @@ module Suture::Error
|
|
|
156
155
|
behavior somewhere in your subject's code.
|
|
157
156
|
|
|
158
157
|
#{if !plan.random_seed.nil?
|
|
159
|
-
<<-MOAR.gsub(/^ {14}/,
|
|
158
|
+
<<-MOAR.gsub(/^ {14}/, "")
|
|
160
159
|
To re-run the tests with the same random seed as was used in this run,
|
|
161
160
|
set the env var `SUTURE_RANDOM_SEED=#{plan.random_seed}` or the config entry
|
|
162
161
|
`:random_seed => #{plan.random_seed}`.
|
|
@@ -167,7 +166,7 @@ module Suture::Error
|
|
|
167
166
|
`:random_seed => nil`.
|
|
168
167
|
MOAR
|
|
169
168
|
else
|
|
170
|
-
<<-MOAR.gsub(/^ {14}/,
|
|
169
|
+
<<-MOAR.gsub(/^ {14}/, "")
|
|
171
170
|
This test was run in insertion order (by the primary key of the table
|
|
172
171
|
that stores calls, ascending). This is sometimes necessary when the
|
|
173
172
|
code has an order-dependent side effect, but shouldn't be set unless it's
|
|
@@ -180,7 +179,6 @@ module Suture::Error
|
|
|
180
179
|
MSG
|
|
181
180
|
end
|
|
182
181
|
|
|
183
|
-
|
|
184
182
|
def stringify_error(error)
|
|
185
183
|
s = error.inspect
|
|
186
184
|
s += "\n" + error.backtrace.join("\n") if error.backtrace
|
data/lib/suture/reset.rb
CHANGED
|
@@ -24,11 +24,9 @@ module Suture::Surgeon
|
|
|
24
24
|
private
|
|
25
25
|
|
|
26
26
|
def result_for(plan, path)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
Suture::Value::Result.errored(error)
|
|
31
|
-
end
|
|
27
|
+
Suture::Value::Result.returned(@scalpel.cut(plan, path))
|
|
28
|
+
rescue => error
|
|
29
|
+
Suture::Value::Result.errored(error)
|
|
32
30
|
end
|
|
33
31
|
|
|
34
32
|
def comparable?(plan, old_result, new_result)
|
|
@@ -53,12 +51,12 @@ module Suture::Surgeon
|
|
|
53
51
|
if result.errored?
|
|
54
52
|
raise result.value
|
|
55
53
|
else
|
|
56
|
-
|
|
54
|
+
result.value
|
|
57
55
|
end
|
|
58
56
|
end
|
|
59
57
|
|
|
60
58
|
def log_warning(plan, old_result, new_result)
|
|
61
|
-
log_warn <<-MSG.gsub(/^ {8}/,
|
|
59
|
+
log_warn <<-MSG.gsub(/^ {8}/, "")
|
|
62
60
|
Seam #{plan.name.inspect} is set to :call_both the :new and :old code
|
|
63
61
|
paths, but they did not match.
|
|
64
62
|
|
data/lib/suture/surgeon/no_op.rb
CHANGED
|
@@ -9,8 +9,8 @@ module Suture::Surgeon
|
|
|
9
9
|
Suture::Util::Scalpel.new.cut(plan, :old).tap do |result|
|
|
10
10
|
dictaphone.record(result)
|
|
11
11
|
end
|
|
12
|
-
rescue
|
|
13
|
-
if plan.expected_error_types.any? {|e| error.
|
|
12
|
+
rescue => error
|
|
13
|
+
if plan.expected_error_types.any? { |e| error.is_a?(e) }
|
|
14
14
|
dictaphone.record_error(error)
|
|
15
15
|
end
|
|
16
16
|
raise error
|
|
@@ -18,4 +18,3 @@ module Suture::Surgeon
|
|
|
18
18
|
end
|
|
19
19
|
end
|
|
20
20
|
end
|
|
21
|
-
|
|
@@ -7,14 +7,12 @@ module Suture::Surgeon
|
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
def operate(plan)
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
@scalpel.cut(plan, :old)
|
|
17
|
-
end
|
|
10
|
+
@scalpel.cut(plan, :new)
|
|
11
|
+
rescue => actual_error
|
|
12
|
+
if plan.expected_error_types.any? { |e| actual_error.is_a?(e) }
|
|
13
|
+
raise actual_error
|
|
14
|
+
else
|
|
15
|
+
@scalpel.cut(plan, :old)
|
|
18
16
|
end
|
|
19
17
|
end
|
|
20
18
|
end
|
|
@@ -8,7 +8,7 @@ module Suture::Util
|
|
|
8
8
|
if expected.errored? != actual.errored?
|
|
9
9
|
false
|
|
10
10
|
elsif expected.errored?
|
|
11
|
-
actual.value.
|
|
11
|
+
actual.value.is_a?(expected.value.class) &&
|
|
12
12
|
expected.value.message == actual.value.message
|
|
13
13
|
else
|
|
14
14
|
@comparator.call(expected.value, actual.value)
|
data/lib/suture/util/env.rb
CHANGED
|
@@ -2,16 +2,16 @@ module Suture::Util
|
|
|
2
2
|
module Env
|
|
3
3
|
def self.to_map(excludes = {})
|
|
4
4
|
Hash[
|
|
5
|
-
ENV.keys
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
].reject { |(k,_)| excludes.include?(k) }
|
|
5
|
+
ENV.keys
|
|
6
|
+
.select { |k| k.start_with?("SUTURE_") }
|
|
7
|
+
.map { |k| [to_sym(k), sanitize_value(ENV[k])] }
|
|
8
|
+
].reject { |(k, _)| excludes.include?(k) }
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
# private
|
|
12
12
|
|
|
13
13
|
def self.to_sym(name)
|
|
14
|
-
name.gsub(/^
|
|
14
|
+
name.gsub(/^SUTURE_/, "").downcase.to_sym
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
def self.sanitize_value(value)
|
data/lib/suture/util/scalpel.rb
CHANGED
|
@@ -10,7 +10,7 @@ module Suture::Util
|
|
|
10
10
|
plan.send(location).call(*args).tap do |result|
|
|
11
11
|
call_after_hook(plan, location, args, result)
|
|
12
12
|
end
|
|
13
|
-
rescue
|
|
13
|
+
rescue => error
|
|
14
14
|
log_error_details(plan, location, args, error)
|
|
15
15
|
call_error_hook(plan, location, args, error)
|
|
16
16
|
raise error
|
|
@@ -20,13 +20,13 @@ module Suture::Util
|
|
|
20
20
|
private
|
|
21
21
|
|
|
22
22
|
def call_after_hook(plan, location, args, result)
|
|
23
|
-
return unless after_hook = try(plan, "after_#{location}")
|
|
23
|
+
return unless (after_hook = try(plan, "after_#{location}"))
|
|
24
24
|
after_hook.call(args, result)
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def log_error_details(plan, location, args, error)
|
|
28
28
|
return if expected_error?(plan, error)
|
|
29
|
-
log_error <<-MSG.gsub(/^ {8}/,
|
|
29
|
+
log_error <<-MSG.gsub(/^ {8}/, "")
|
|
30
30
|
Suture invoked the #{plan.name.inspect} seam's #{location.inspect} code path with args: ```
|
|
31
31
|
#{args.inspect}
|
|
32
32
|
```
|
|
@@ -38,12 +38,12 @@ module Suture::Util
|
|
|
38
38
|
|
|
39
39
|
def call_error_hook(plan, location, args, error)
|
|
40
40
|
return if expected_error?(plan, error)
|
|
41
|
-
return unless error_hook = try(plan, "on_#{location}_error")
|
|
41
|
+
return unless (error_hook = try(plan, "on_#{location}_error"))
|
|
42
42
|
error_hook.call(plan.name, args, error)
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def expected_error?(plan, error)
|
|
46
|
-
plan.expected_error_types.any? {|e| error.
|
|
46
|
+
plan.expected_error_types.any? { |e| error.is_a?(e) }
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
def args_for(plan, args_override)
|
|
@@ -62,6 +62,5 @@ module Suture::Util
|
|
|
62
62
|
return unless plan.respond_to?(method)
|
|
63
63
|
plan.send(method)
|
|
64
64
|
end
|
|
65
|
-
|
|
66
65
|
end
|
|
67
66
|
end
|
data/lib/suture/util/shuffle.rb
CHANGED
data/lib/suture/value/plan.rb
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
module Suture::Value
|
|
2
2
|
class Plan
|
|
3
3
|
attr_reader :name, :old, :new, :args, :after_new, :after_old, :on_new_error,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
:on_old_error, :database_path, :record_calls, :comparator,
|
|
5
|
+
:call_both, :raise_on_result_mismatch,
|
|
6
|
+
:return_old_on_result_mismatch, :fallback_on_error,
|
|
7
|
+
:expected_error_types, :disable, :dup_args
|
|
8
8
|
|
|
9
9
|
def initialize(attrs = {})
|
|
10
10
|
@name = attrs[:name]
|
data/lib/suture/value/result.rb
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
module Suture::Value
|
|
2
2
|
class TestPlan
|
|
3
3
|
attr_accessor :name, :subject,
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
4
|
+
:verify_only, :fail_fast, :call_limit, :time_limit,
|
|
5
|
+
:error_message_limit, :random_seed, :comparator,
|
|
6
|
+
:database_path, :after_subject, :on_subject_error,
|
|
7
|
+
:expected_error_types
|
|
8
8
|
|
|
9
9
|
def initialize(attrs = {})
|
|
10
10
|
assign_simple_ivars!(attrs, :name, :subject, :comparator,
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
:database_path, :after_subject,
|
|
12
|
+
:on_subject_error)
|
|
13
13
|
assign_integral_ivars!(attrs, :verify_only, :call_limit, :time_limit,
|
|
14
|
-
|
|
14
|
+
:error_message_limit)
|
|
15
15
|
@fail_fast = !!attrs[:fail_fast]
|
|
16
16
|
@expected_error_types = attrs[:expected_error_types] || []
|
|
17
17
|
@random_seed = determine_random_seed(attrs)
|
|
@@ -26,18 +26,18 @@ module Suture::Value
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def assign_integral_ivars!(attrs, *names)
|
|
29
|
-
assign_simple_ivars!(massage_values(attrs, names
|
|
29
|
+
assign_simple_ivars!(massage_values(attrs, names, &:to_i), *names)
|
|
30
30
|
end
|
|
31
31
|
|
|
32
|
-
def massage_values(attrs, names
|
|
32
|
+
def massage_values(attrs, names)
|
|
33
33
|
Hash[
|
|
34
|
-
attrs.select {|(k,_)| names.include?(k) }
|
|
35
|
-
|
|
34
|
+
attrs.select { |(k, _)| names.include?(k) }
|
|
35
|
+
.map { |(k, v)| [k, v.nil? ? nil : yield(v)] }
|
|
36
36
|
]
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def determine_random_seed(attrs)
|
|
40
|
-
if attrs.
|
|
40
|
+
if attrs.key?(:random_seed)
|
|
41
41
|
if attrs[:random_seed].nil? || attrs[:random_seed] == "nil"
|
|
42
42
|
nil
|
|
43
43
|
else
|
|
@@ -16,7 +16,7 @@ module Suture
|
|
|
16
16
|
:new_result => result,
|
|
17
17
|
:passed => compares_results.compare(observation.result, result)
|
|
18
18
|
}
|
|
19
|
-
rescue
|
|
19
|
+
rescue => error
|
|
20
20
|
if observation.result.errored?
|
|
21
21
|
result = Value::Result.errored(error)
|
|
22
22
|
{
|
|
@@ -24,7 +24,7 @@ module Suture
|
|
|
24
24
|
:passed => compares_results.compare(observation.result, result)
|
|
25
25
|
}
|
|
26
26
|
else
|
|
27
|
-
{
|
|
27
|
+
{:error => error, :passed => false}
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
end
|
|
@@ -4,13 +4,13 @@ require "suture/util/env"
|
|
|
4
4
|
module Suture
|
|
5
5
|
class PrescribesTestPlan
|
|
6
6
|
UN_ENV_IABLE_OPTIONS = [:name, :subject, :comparator, :after_subject,
|
|
7
|
-
|
|
7
|
+
:on_subject_error, :expected_error_types]
|
|
8
8
|
|
|
9
9
|
def prescribe(name, options = {})
|
|
10
|
-
Value::TestPlan.new(Suture.config
|
|
11
|
-
merge(options)
|
|
12
|
-
merge(:name => name)
|
|
13
|
-
merge(Suture::Util::Env.to_map(UN_ENV_IABLE_OPTIONS)))
|
|
10
|
+
Value::TestPlan.new(Suture.config
|
|
11
|
+
.merge(options)
|
|
12
|
+
.merge(:name => name)
|
|
13
|
+
.merge(Suture::Util::Env.to_map(UN_ENV_IABLE_OPTIONS)))
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
end
|
|
@@ -39,7 +39,7 @@ module Suture
|
|
|
39
39
|
|
|
40
40
|
def validate_test_plan!(test_plan)
|
|
41
41
|
if !test_plan.subject || !test_plan.subject.respond_to?(:call)
|
|
42
|
-
raise Suture::Error::InvalidTestPlan
|
|
42
|
+
raise Suture::Error::InvalidTestPlan
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
|
|
@@ -56,7 +56,7 @@ module Suture
|
|
|
56
56
|
test_plan.random_seed
|
|
57
57
|
).tap do |test_cases|
|
|
58
58
|
next if test_cases.size > 0
|
|
59
|
-
log_warn <<-MSG.gsub(/^ {10}/,
|
|
59
|
+
log_warn <<-MSG.gsub(/^ {10}/, "")
|
|
60
60
|
Suture.verify found no recorded calls for seam #{test_plan.name.inspect}.
|
|
61
61
|
As a result, verify will have no effect and cannot provide any assurance
|
|
62
62
|
that the subject is working as expected.
|
|
@@ -70,4 +70,3 @@ module Suture
|
|
|
70
70
|
end
|
|
71
71
|
end
|
|
72
72
|
end
|
|
73
|
-
|
data/lib/suture/verify.rb
CHANGED
data/lib/suture/version.rb
CHANGED
data/lib/suture/wrap/logger.rb
CHANGED
|
@@ -12,12 +12,12 @@ module Suture::Wrap
|
|
|
12
12
|
end
|
|
13
13
|
|
|
14
14
|
@logger.level = if options[:log_level]
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
::Logger.const_get(options[:log_level])
|
|
16
|
+
else
|
|
17
|
+
::Logger::INFO
|
|
18
|
+
end
|
|
19
19
|
|
|
20
|
-
@logger.formatter = proc { |_, time
|
|
20
|
+
@logger.formatter = proc { |_, time, _, msg|
|
|
21
21
|
formatted_time = time.strftime("%Y-%m-%dT%H:%M:%S.%6N")
|
|
22
22
|
"[#{formatted_time}] Suture: #{msg}\n".tap { |out|
|
|
23
23
|
puts out if options[:log_stdout]
|
|
@@ -25,19 +25,39 @@ module Suture::Wrap
|
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
@logger
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
class NullIO
|
|
32
|
-
def gets
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
def
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def
|
|
39
|
-
|
|
40
|
-
|
|
32
|
+
def gets
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def each
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def read(count = nil, _buffer = nil)
|
|
39
|
+
(count && count > 0) ? nil : ""
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def rewind
|
|
43
|
+
0
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def close
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def size
|
|
50
|
+
0
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def sync=(*args)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def puts(*args)
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def write(*args)
|
|
60
|
+
end
|
|
41
61
|
end
|
|
42
62
|
end
|
|
43
63
|
end
|
data/lib/suture/wrap/sqlite.rb
CHANGED
|
@@ -4,7 +4,7 @@ require "suture/error/schema_version"
|
|
|
4
4
|
|
|
5
5
|
module Suture::Wrap
|
|
6
6
|
module Sqlite
|
|
7
|
-
SCHEMA_VERSION=2
|
|
7
|
+
SCHEMA_VERSION = 2
|
|
8
8
|
def self.init(location)
|
|
9
9
|
full_path = File.join(Dir.getwd, location)
|
|
10
10
|
FileUtils.mkdir_p(File.dirname(full_path))
|
|
@@ -16,7 +16,7 @@ module Suture::Wrap
|
|
|
16
16
|
SQL
|
|
17
17
|
db.execute("insert or ignore into suture_schema_info values (?)", [SCHEMA_VERSION])
|
|
18
18
|
actual_schema_version = db.execute("select * from suture_schema_info").first[0]
|
|
19
|
-
if
|
|
19
|
+
if actual_schema_version != SCHEMA_VERSION
|
|
20
20
|
raise Suture::Error::SchemaVersion.new(SCHEMA_VERSION, actual_schema_version)
|
|
21
21
|
end
|
|
22
22
|
|
data/lib/suture.rb
CHANGED