suture 0.5.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +3 -2
- data/CHANGELOG.md +22 -1
- data/README.md +192 -4
- data/Rakefile +13 -1
- data/lib/suture/adapter/log.rb +1 -1
- data/lib/suture/comparator.rb +47 -1
- data/lib/suture/error/invalid_test_plan.rb +7 -0
- data/lib/suture/error/result_mismatch.rb +1 -2
- data/lib/suture/error/verification_failed.rb +7 -5
- data/lib/suture/util/numbers.rb +7 -0
- data/lib/suture/value/result.rb +2 -0
- data/lib/suture/verify/tests_patient.rb +8 -0
- data/lib/suture/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65850d2b933384f85c0cd13ec67fe92efcb08320
|
4
|
+
data.tar.gz: ba005e2f0e87b693f89948102559dfccfba7720b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7132a9cfa0499d89c786c7ccea1c7ed3da896ec786d3249b1aa3d00433eb0387d3be8917e3bb589f917f888624ab4bab71dc3c2f751a599a100422c09b717f2f
|
7
|
+
data.tar.gz: cd7f1fea872d8887a51f8b65d03cd5bff5189d9d4032141c0862c02265aec1c2acd4552e24e77e611fbb10e57ebd62796d2a956edf754c6dcde57df43438f0ff
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -2,7 +2,28 @@
|
|
2
2
|
|
3
3
|
## [Unreleased](https://github.com/testdouble/suture/tree/HEAD)
|
4
4
|
|
5
|
-
[Full Changelog](https://github.com/testdouble/suture/compare/v0.
|
5
|
+
[Full Changelog](https://github.com/testdouble/suture/compare/v0.4.0...HEAD)
|
6
|
+
|
7
|
+
**Implemented enhancements:**
|
8
|
+
|
9
|
+
- API to delete a seam's recordings from the database [\#32](https://github.com/testdouble/suture/issues/32)
|
10
|
+
|
11
|
+
**Closed issues:**
|
12
|
+
|
13
|
+
- Justification for building a custom Docker image instead of using the canonical Ruby one [\#57](https://github.com/testdouble/suture/issues/57)
|
14
|
+
- staging/prod: dup arguments [\#56](https://github.com/testdouble/suture/issues/56)
|
15
|
+
- Add progress bar [\#54](https://github.com/testdouble/suture/issues/54)
|
16
|
+
- warn if no calls are found for the provided seam name [\#51](https://github.com/testdouble/suture/issues/51)
|
17
|
+
- Log out an error every time a suture raises [\#50](https://github.com/testdouble/suture/issues/50)
|
18
|
+
- Validate test plans [\#28](https://github.com/testdouble/suture/issues/28)
|
19
|
+
- Support permitted error types [\#24](https://github.com/testdouble/suture/issues/24)
|
20
|
+
|
21
|
+
**Merged pull requests:**
|
22
|
+
|
23
|
+
- Remove an unnecessary space \[ci skip\] [\#52](https://github.com/testdouble/suture/pull/52) ([JuanitoFatas](https://github.com/JuanitoFatas))
|
24
|
+
|
25
|
+
## [v0.4.0](https://github.com/testdouble/suture/tree/v0.4.0) (2016-08-29)
|
26
|
+
[Full Changelog](https://github.com/testdouble/suture/compare/v0.3.3...v0.4.0)
|
6
27
|
|
7
28
|
**Closed issues:**
|
8
29
|
|
data/README.md
CHANGED
@@ -262,7 +262,7 @@ unit tests around new units that shook out from the activity. Having good tests
|
|
262
262
|
for well-factored code is the best guard against seeing it slip once again into
|
263
263
|
poorly-understood "legacy" code.
|
264
264
|
|
265
|
-
##
|
265
|
+
## Staging
|
266
266
|
|
267
267
|
Once you've changed the code, you still may not be confident enough to delete it
|
268
268
|
entirely. It's possible (even likely) that your local exploratory testing didn't
|
@@ -292,7 +292,7 @@ implementations, and will raise an error if they don't return the same value.
|
|
292
292
|
Obviously, this setting is only helpful if the paths don't trigger major or
|
293
293
|
destructive side effects.
|
294
294
|
|
295
|
-
##
|
295
|
+
## Production
|
296
296
|
|
297
297
|
You're _almost_ ready to delete the old code path and switch production over to
|
298
298
|
the new one, but fear lingers: maybe there's an edge case your testing to this
|
@@ -408,11 +408,155 @@ where you call Suture, like `Suture.create(:foo, { :comparator => my_thing })`
|
|
408
408
|
|
409
409
|
#### Suture.create
|
410
410
|
|
411
|
-
|
411
|
+
`Suture.create(name, [options hash])`
|
412
|
+
|
413
|
+
* _name_ (Required) - a unique name for the seam, by which any recordings will be
|
414
|
+
identified. This should match the name used for any calls to `Suture.verify` by
|
415
|
+
your automated tests
|
416
|
+
|
417
|
+
* _old_ - (Required) - something that responds to `call` for the provided `args`
|
418
|
+
of the seam and either is the legacy code path (e.g.
|
419
|
+
`OldCode.new.method(:old_path)`) or invokes it (inside an anonymous Proc or
|
420
|
+
lambda)
|
421
|
+
|
422
|
+
* _args_ - (Required) - an array of arguments to be passed to the `old` or `new`
|
423
|
+
|
424
|
+
* _new_ - like old, but either references or invokes the code path designed to
|
425
|
+
replace the `old` legacy code path. When set, Suture will default to invoking
|
426
|
+
the `new` path at the exclusion of the `old` path (unless a mode flag like
|
427
|
+
`record_calls`, `call_both`, or `fallback_on_error` suggests differently)
|
428
|
+
|
429
|
+
* _database_path_ - (Default: `"db/suture.sqlite3"`) - a path relative to the
|
430
|
+
current working directory to the Sqlite3 database Suture uses to record and
|
431
|
+
playback calls
|
432
|
+
|
433
|
+
* _record_calls_ - (Default: false) - when set to true, the `old` path is called
|
434
|
+
(regardless of whether `new` is set) and its arguments and result (be it a return
|
435
|
+
value or an expected raised error) is recorded into the Suture database for the
|
436
|
+
purpose of more coverage for calls to `Suture.verify`. [Read
|
437
|
+
more](#3-record-the-current-behavior)
|
438
|
+
|
439
|
+
* _call_both_ - (Default: false) - when set to true, the `new` path is invoked,
|
440
|
+
then the `old` path is invoked, each with the seam's `args`. The return value
|
441
|
+
from each is compared with the `comparator`, and if they are not equivalent, then
|
442
|
+
a `Suture::Error::ResultMismatch` is raised. Intended after the `new` path is
|
443
|
+
initially developed and to be run in pre-production environments. [Read
|
444
|
+
more](#staging)
|
445
|
+
|
446
|
+
* _fallback_on_error_ - (Default: false) - designed to be run in production after
|
447
|
+
the initial development of the new code path, when set to true, Suture will
|
448
|
+
invoke the `new` code path. If `new` raises an error that isn't an
|
449
|
+
`expected_error_type`, then Suture will invoke the `old` path with the same args
|
450
|
+
in an attempt to recover a working state for the user. [Read more](#production)
|
451
|
+
|
452
|
+
* _raise_on_result_mismatch_ - (Default: true) - when set to true, the
|
453
|
+
`call_both` mode will merely log incidents of result mismatches, as opposed to
|
454
|
+
raising `Suture::Error::ResultMismatch`.
|
455
|
+
|
456
|
+
* _comparator_ - (Default: `Suture::Comparator.new`) - determines how return
|
457
|
+
values from the Suture are compared when invoking `Suture.verify` or when
|
458
|
+
`call_both` mode is activated. By default, results will be considered equivalent
|
459
|
+
if `==` returns true or if they `Marshal.dump` to the same string. If this
|
460
|
+
default isn't appropriate for the return value of your seam, [read
|
461
|
+
on](#creating-a-custom-comparator)
|
462
|
+
|
463
|
+
* _expected_error_types_ - (Default: `[]`) - if the seam is expected to raise
|
464
|
+
certain types of errors, don't consider them to be exceptional cases. For
|
465
|
+
example, if your `:widget` seam is known to raise `WidgetError` objects in
|
466
|
+
certain cases, setting `:expected_error_types => [WidgetError]` will result in:
|
467
|
+
* `Suture.create` will record expected errors when `record_calls` is enabled
|
468
|
+
* `Suture.verify` will compare recorded and actual raised errors that are
|
469
|
+
`kind_of?` any recorded error type (regardless of whether `Suture.verify` is
|
470
|
+
passed a redundant list of `expected_error_types`)
|
471
|
+
* `Suture.create`, when `fallback_on_error` is enabled, will allow expected
|
472
|
+
errors raised by the `new` path to propogate, as opposed to logging &
|
473
|
+
rescuing them before calling the `old` path as a fallback
|
474
|
+
* Additionally, `Suture.verify` can be passed `expected_error_types` to squelch
|
475
|
+
warning logs that result from unexpectedly raised errors
|
476
|
+
|
477
|
+
* _disable_ - (Default: false) - when enabled, Suture will attempt to revert to
|
478
|
+
the original behavior of the `old` path and take no special action. Useful in
|
479
|
+
cases where a bug is discovered in a deployed environment and you simply want
|
480
|
+
to hit the brakes on any new code path experiments by setting
|
481
|
+
`SUTURE_DISABLE=true` globally
|
482
|
+
|
483
|
+
* _dup_args_ - (Default: false) - when enabled, Suture will call `dup` on each
|
484
|
+
of the args passed to the `old` and/or `new` code paths. Useful when the code
|
485
|
+
path(s) mutate the arguments in such a way as to prevent `call_both` or
|
486
|
+
`fallback_on_error` from being effective
|
487
|
+
|
488
|
+
* _after_new_ - a `call`-able hook that runs after `new` is invoked. If `new`
|
489
|
+
raises an error, it is not invoked
|
490
|
+
|
491
|
+
* _after_old_ - a `call`-able hook that runs after `old` is invoked. If `old`
|
492
|
+
raises an error, it is not invoked
|
493
|
+
|
494
|
+
* _on_new_error_ - a `call`-able hook that is invoked after `new` raises an
|
495
|
+
unexpected error (see `expected_error_types`).
|
496
|
+
|
497
|
+
* _on_old_error_ - a `call`-able hook that is invoked after `old` raises an
|
498
|
+
unexpected error (see `expected_error_types`).
|
412
499
|
|
413
500
|
#### Suture.verify
|
414
501
|
|
415
|
-
|
502
|
+
Many of the settings for `Suture.verify` are analogous to the same settings in
|
503
|
+
`Suture.create` and are generally expected to be configured in the same way, as
|
504
|
+
if symmetrically with the `Suture.create` call of the seam under test:
|
505
|
+
|
506
|
+
* _name_ - (Required) - should be the same name as a seam for which some number
|
507
|
+
of recorded calls exist
|
508
|
+
|
509
|
+
* _subject_ - (Required) - a `call`-able that will be invoked with each recorded
|
510
|
+
set of `args` and have its result compared to that of each recording. This is
|
511
|
+
used in lieu of `old` or `new`, since the subject of a `Suture.verify` test might
|
512
|
+
be either (or neither!)
|
513
|
+
|
514
|
+
* _verify_only_ - (Default: nil) - when set to an ID, Suture.verify` will only
|
515
|
+
run against recorded calls for the matching ID. This option is meant to be used
|
516
|
+
to focus work on resolving a single verification failure
|
517
|
+
|
518
|
+
* _fail_fast_ - (Default: false) - `Suture.verify` will, by default, run against
|
519
|
+
every single recording, aggregating and reporting on all errors (just like, say,
|
520
|
+
RSpec or Minitest would). However, if the seam is slow to invoke or if you
|
521
|
+
confidently expect all of the recordings to pass verification, `fail_fast` is an
|
522
|
+
appropriate option to set.
|
523
|
+
|
524
|
+
* _call_limit_ - (Default: nil) - when set to a number, Suture will only verify
|
525
|
+
up to the set number of recorded calls. Because Suture randomizes the order of
|
526
|
+
verifications by default, you can see this as setting Suture.verify to sample a
|
527
|
+
random smattering of `call_limit` recordings as a smell test. Potentially useful
|
528
|
+
when a seam is very slow
|
529
|
+
|
530
|
+
* _time_limit_ - (Default: nil) - when set to a number (in seconds), Suture will
|
531
|
+
stop running verifications against recordings once `time_limit` seconds has
|
532
|
+
elapsed. Useful when a seam is very slow to invoke
|
533
|
+
|
534
|
+
* _error_message_limit_ - (Default: nil) - when set to a number, Suture will only
|
535
|
+
print up to `error_message_limit` failure messages. That way, if you currently
|
536
|
+
have hundreds of verifications failing, your console isn't overwhelmed by them on
|
537
|
+
each run of `Suture.verify`
|
538
|
+
|
539
|
+
* _random_seed_ - (Default: it's random!) - a randomized seed used to shuffle
|
540
|
+
the recordings before verifying them against the `subject` code path. If set to
|
541
|
+
`nil`, the recordings will be invoked in insertion-order. If set to a specific
|
542
|
+
number, that number will be used as the random seed (useful when re-running a
|
543
|
+
particular verification failure that can't be reproduced otherwise)
|
544
|
+
|
545
|
+
* _comparator_ - (Default: `Suture::Comparator`) - If a custom comparator is used
|
546
|
+
by the seam in `Suture.create`, then the same comparator should probably be
|
547
|
+
used by `Suture.verify` to ensure the results are comparable. [Read
|
548
|
+
more](#creating-a-custom-comparator) on creating custom comparators
|
549
|
+
)
|
550
|
+
|
551
|
+
* _database_path_ - (Default: `"db/suture.sqlite3"`) - as with `Suture.create`, a
|
552
|
+
custom database path can be set for almost any invocation of Suture, and
|
553
|
+
`Suture.verify is no exception`
|
554
|
+
|
555
|
+
* _after_subject_ - a `call`-able hook that runs after `subject` is invoked. If
|
556
|
+
`subject` raises an error, it is not invoked
|
557
|
+
|
558
|
+
* _on_new_subject_ - a `call`-able hook that is invoked after `subject` raises an
|
559
|
+
unexpected error (see `expected_error_types`)
|
416
560
|
|
417
561
|
### Creating a custom comparator
|
418
562
|
|
@@ -472,6 +616,50 @@ Suture.verify(:my_type, {
|
|
472
616
|
})
|
473
617
|
```
|
474
618
|
|
619
|
+
#### Comparing two ActiveRecord objects
|
620
|
+
|
621
|
+
Let's face it, a massive proportion of legacy Ruby code in the wild involves
|
622
|
+
ActiveRecord objects to some extent, and it's important that Suture be equipped
|
623
|
+
to compare them gracefully. If Suture's default comparator (`Suture::Comparator`)
|
624
|
+
detects two ActiveRecord model instances being compared, it will behave
|
625
|
+
differently, by this logic:
|
626
|
+
|
627
|
+
1. Instead of comparing the objects with `==` (which returns true so long as the
|
628
|
+
`id` attribute matdhes), Suture will compare the objects' `attributes` hashes
|
629
|
+
instead
|
630
|
+
2. The built-in `updated_at` and `created_at` will typically differ when code
|
631
|
+
is executed at different times and are usually not meaningful to application
|
632
|
+
logic, Suture will ignore these attributes by default
|
633
|
+
|
634
|
+
Other attributes may or may not matter (for instance, other timestamp fields,
|
635
|
+
or the `id` of the object), in those cases, you can instantiate the comparator
|
636
|
+
yourself and tell it which attributes to exclude, like so:
|
637
|
+
|
638
|
+
``` ruby
|
639
|
+
Suture.verify :thing,
|
640
|
+
:subject => Thing.new.method(:stuff),
|
641
|
+
:comparator => Suture::Comparator.new(
|
642
|
+
:active_record_excluded_attributes => [
|
643
|
+
:id,
|
644
|
+
:quality,
|
645
|
+
:created_at,
|
646
|
+
:updated_at
|
647
|
+
]
|
648
|
+
)
|
649
|
+
```
|
650
|
+
|
651
|
+
If `Thing#stuff` returns an instance of an ActiveRecord model, the four
|
652
|
+
attributes listed above will be ignored when comparing with recorded results.
|
653
|
+
|
654
|
+
In all of the above cases, `:comparator` can be set on both `Suture.create` and
|
655
|
+
`Suture.verify` and typically ought to be symmetrical for most seams.
|
656
|
+
|
657
|
+
## Examples
|
658
|
+
|
659
|
+
This repository contains these examples available for your perusal:
|
660
|
+
|
661
|
+
* [A Rails app of the Gilded Rose kata](example/rails_app)
|
662
|
+
|
475
663
|
## Troubleshooting
|
476
664
|
|
477
665
|
Some ideas if you can't get a particular verification to work or if you keep
|
data/Rakefile
CHANGED
@@ -26,6 +26,18 @@ Rake::TestTask.new(:test) do |t|
|
|
26
26
|
]
|
27
27
|
end
|
28
28
|
|
29
|
+
task :example do
|
30
|
+
Dir.chdir("example/rails_app") do
|
31
|
+
passed = system <<-SH
|
32
|
+
BUNDLE_GEMFILE="$PWD/Gemfile" bundle install --quiet
|
33
|
+
BUNDLE_GEMFILE="$PWD/Gemfile" bundle exec rake suture
|
34
|
+
SH
|
35
|
+
if !passed
|
36
|
+
raise StandardError.new("Rails example failed!")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
29
41
|
if Gem.ruby_version >= Gem::Version.new("2.2.2")
|
30
42
|
require 'github_changelog_generator/task'
|
31
43
|
GitHubChangelogGenerator::RakeTask.new :changelog
|
@@ -39,4 +51,4 @@ if Gem.ruby_version >= Gem::Version.new("2.2.2")
|
|
39
51
|
end
|
40
52
|
|
41
53
|
|
42
|
-
task :default => :test
|
54
|
+
task :default => [:test, :example]
|
data/lib/suture/adapter/log.rb
CHANGED
data/lib/suture/comparator.rb
CHANGED
@@ -1,7 +1,53 @@
|
|
1
1
|
module Suture
|
2
2
|
class Comparator
|
3
|
+
DEFAULT_ACTIVE_RECORD_EXCLUDED_ATTRIBUTES = [:updated_at, :created_at]
|
4
|
+
|
5
|
+
def initialize(options = {})
|
6
|
+
@options = {
|
7
|
+
:active_record_excluded_attributes => (
|
8
|
+
options[:active_record_excluded_attributes] ||
|
9
|
+
DEFAULT_ACTIVE_RECORD_EXCLUDED_ATTRIBUTES
|
10
|
+
).map(&:to_s)
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
3
14
|
def call(recorded, actual)
|
4
|
-
recorded
|
15
|
+
is_equalivalent?(recorded, actual) ||
|
16
|
+
Marshal.dump(recorded) == Marshal.dump(actual)
|
17
|
+
end
|
18
|
+
|
19
|
+
def inspect
|
20
|
+
"#{self.class}.new(#{@options.inspect})"
|
21
|
+
end
|
22
|
+
|
23
|
+
protected
|
24
|
+
|
25
|
+
def compare_active_record(recorded, actual)
|
26
|
+
actual.kind_of?(recorded.class) &&
|
27
|
+
without_excluded_attrs(recorded.attributes) ==
|
28
|
+
without_excluded_attrs(actual.attributes)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def without_excluded_attrs(hash)
|
34
|
+
hash.reject do |k, v|
|
35
|
+
@options[:active_record_excluded_attributes].include?(k.to_s)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def is_equalivalent?(recorded, actual)
|
40
|
+
if is_active_record?(recorded, actual)
|
41
|
+
compare_active_record(recorded, actual)
|
42
|
+
else
|
43
|
+
recorded == actual
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def is_active_record?(recorded, actual)
|
48
|
+
defined?(ActiveRecord::Base) &&
|
49
|
+
recorded.kind_of?(ActiveRecord::Base) &&
|
50
|
+
actual.kind_of?(ActiveRecord::Base)
|
5
51
|
end
|
6
52
|
end
|
7
53
|
end
|
@@ -7,7 +7,7 @@ module Suture::Error
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def message
|
10
|
-
|
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
|
@@ -52,7 +52,6 @@ module Suture::Error
|
|
52
52
|
too disruptive and logging is sufficient for monitoring results, you may
|
53
53
|
disable this error by setting `:raise_on_result_mismatch` to false.
|
54
54
|
MSG
|
55
|
-
|
56
55
|
end
|
57
56
|
end
|
58
57
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require "suture/adapter/progress_bar"
|
2
|
+
require "suture/util/numbers"
|
2
3
|
|
3
4
|
module Suture::Error
|
4
5
|
class VerificationFailed < StandardError
|
@@ -47,6 +48,7 @@ module Suture::Error
|
|
47
48
|
results.passed.size,
|
48
49
|
results.all.size
|
49
50
|
)
|
51
|
+
percent = Suture::Util::Numbers.percent(results.passed.size, results.all.size)
|
50
52
|
<<-MSG.gsub(/^ {8}/,'')
|
51
53
|
## Progress
|
52
54
|
|
@@ -54,7 +56,7 @@ module Suture::Error
|
|
54
56
|
|
55
57
|
#{bar}
|
56
58
|
|
57
|
-
Of #{results.all.size} recorded interactions, #{results.passed.size} are currently passing.
|
59
|
+
Of #{results.all.size} recorded interactions, #{results.passed.size} are currently passing. That's #{percent}%!
|
58
60
|
MSG
|
59
61
|
end
|
60
62
|
|
@@ -66,13 +68,13 @@ module Suture::Error
|
|
66
68
|
|
67
69
|
```
|
68
70
|
{
|
69
|
-
:comparator => #{describe_comparator(plan.comparator)}
|
70
71
|
:database_path => #{plan.database_path.inspect},
|
71
72
|
:fail_fast => #{plan.fail_fast},
|
72
73
|
:call_limit => #{plan.call_limit.inspect},#{" # (no limit)" if plan.call_limit.nil?}
|
73
74
|
:time_limit => #{plan.time_limit.inspect},#{plan.time_limit.nil? ? " # (no limit)" : " # (in seconds)"}
|
74
75
|
:error_message_limit => #{plan.error_message_limit.inspect},#{" # (no limit)" if plan.error_message_limit.nil?}
|
75
|
-
:random_seed => #{plan.random_seed.inspect}
|
76
|
+
:random_seed => #{plan.random_seed.inspect},#{" # (insertion order)" if plan.random_seed.nil?}
|
77
|
+
:comparator => #{describe_comparator(plan.comparator)}
|
76
78
|
}
|
77
79
|
```
|
78
80
|
MSG
|
@@ -80,9 +82,9 @@ module Suture::Error
|
|
80
82
|
|
81
83
|
def describe_comparator(comparator)
|
82
84
|
if comparator.kind_of?(Proc)
|
83
|
-
"Proc
|
85
|
+
"Proc # (in: `#{describe_source_location(*comparator.source_location)}`)"
|
84
86
|
elsif comparator.respond_to?(:method) && comparator.method(:call)
|
85
|
-
"#{comparator.
|
87
|
+
"#{comparator.inspect}.new, # (in: `#{describe_source_location(*comparator.method(:call).source_location)}`)"
|
86
88
|
end
|
87
89
|
end
|
88
90
|
|
data/lib/suture/value/result.rb
CHANGED
@@ -4,6 +4,7 @@ require "suture/adapter/dictaphone"
|
|
4
4
|
require "suture/value/test_results"
|
5
5
|
require "suture/util/shuffle"
|
6
6
|
require "suture/util/timer"
|
7
|
+
require "suture/error/invalid_test_plan"
|
7
8
|
require "backports/1.9.2/random"
|
8
9
|
|
9
10
|
module Suture
|
@@ -15,6 +16,7 @@ module Suture
|
|
15
16
|
end
|
16
17
|
|
17
18
|
def test(test_plan)
|
19
|
+
validate_test_plan!(test_plan)
|
18
20
|
experienced_failure_in_life = false
|
19
21
|
timer = Suture::Util::Timer.new(test_plan.time_limit) unless test_plan.time_limit.nil?
|
20
22
|
test_cases = build_test_cases(test_plan)
|
@@ -35,6 +37,12 @@ module Suture
|
|
35
37
|
|
36
38
|
private
|
37
39
|
|
40
|
+
def validate_test_plan!(test_plan)
|
41
|
+
if !test_plan.subject || !test_plan.subject.respond_to?(:call)
|
42
|
+
raise Suture::Error::InvalidTestPlan.new
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
38
46
|
def should_skip?(test_plan, failed_fast, call_count, timer)
|
39
47
|
(test_plan.fail_fast && failed_fast) ||
|
40
48
|
(test_plan.call_limit && call_count >= test_plan.call_limit) ||
|
data/lib/suture/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: suture
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Justin Searls
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-09-
|
11
|
+
date: 2016-09-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sqlite3
|
@@ -197,6 +197,7 @@ files:
|
|
197
197
|
- lib/suture/create/validates_plan.rb
|
198
198
|
- lib/suture/delete.rb
|
199
199
|
- lib/suture/error/invalid_plan.rb
|
200
|
+
- lib/suture/error/invalid_test_plan.rb
|
200
201
|
- lib/suture/error/observation_conflict.rb
|
201
202
|
- lib/suture/error/result_mismatch.rb
|
202
203
|
- lib/suture/error/schema_version.rb
|
@@ -208,6 +209,7 @@ files:
|
|
208
209
|
- lib/suture/surgeon/remediator.rb
|
209
210
|
- lib/suture/util/compares_results.rb
|
210
211
|
- lib/suture/util/env.rb
|
212
|
+
- lib/suture/util/numbers.rb
|
211
213
|
- lib/suture/util/scalpel.rb
|
212
214
|
- lib/suture/util/shuffle.rb
|
213
215
|
- lib/suture/util/timer.rb
|