smartest 0.1.0 → 0.2.0.alpha2
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 +4 -4
- data/DEVELOPMENT.md +102 -10
- data/README.md +161 -34
- data/SMARTEST_DESIGN.md +137 -18
- data/lib/smartest/dsl.rb +13 -6
- data/lib/smartest/errors.rb +40 -0
- data/lib/smartest/execution_context.rb +14 -0
- data/lib/smartest/fixture.rb +6 -0
- data/lib/smartest/hook_contexts.rb +60 -0
- data/lib/smartest/init_generator.rb +4 -1
- data/lib/smartest/reporter.rb +40 -3
- data/lib/smartest/runner.rb +97 -15
- data/lib/smartest/suite.rb +34 -1
- data/lib/smartest/suite_run.rb +24 -0
- data/lib/smartest/test_case.rb +3 -2
- data/lib/smartest/test_result.rb +35 -2
- data/lib/smartest/test_run.rb +58 -0
- data/lib/smartest/test_run_state.rb +16 -0
- data/lib/smartest/version.rb +1 -1
- data/lib/smartest.rb +4 -0
- data/smartest/smartest_test.rb +470 -4
- metadata +7 -3
data/lib/smartest/suite.rb
CHANGED
|
@@ -2,12 +2,45 @@
|
|
|
2
2
|
|
|
3
3
|
module Smartest
|
|
4
4
|
class Suite
|
|
5
|
-
attr_reader :tests, :fixture_classes, :matcher_modules
|
|
5
|
+
attr_reader :tests, :fixture_classes, :matcher_modules, :around_suite_hooks, :around_test_hooks
|
|
6
6
|
|
|
7
7
|
def initialize
|
|
8
8
|
@tests = TestRegistry.new
|
|
9
9
|
@fixture_classes = FixtureClassRegistry.new
|
|
10
10
|
@matcher_modules = MatcherRegistry.new
|
|
11
|
+
@around_suite_hooks = []
|
|
12
|
+
@around_test_hooks = []
|
|
13
|
+
@around_test_hooks_by_file = Hash.new { |hash, path| hash[path] = [] }
|
|
14
|
+
@around_suite_hook_depth = 0
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def add_around_test_hook(location, hook)
|
|
18
|
+
if running_around_suite_hook?
|
|
19
|
+
@around_test_hooks << hook
|
|
20
|
+
else
|
|
21
|
+
@around_test_hooks_by_file[path_for(location)] << hook
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def around_test_hooks_for(location)
|
|
26
|
+
@around_test_hooks_by_file[path_for(location)].dup
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def around_suite_hook
|
|
30
|
+
@around_suite_hook_depth += 1
|
|
31
|
+
yield
|
|
32
|
+
ensure
|
|
33
|
+
@around_suite_hook_depth -= 1
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
private
|
|
37
|
+
|
|
38
|
+
def running_around_suite_hook?
|
|
39
|
+
@around_suite_hook_depth.positive?
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def path_for(location)
|
|
43
|
+
File.expand_path(location.absolute_path || location.path)
|
|
11
44
|
end
|
|
12
45
|
end
|
|
13
46
|
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Smartest
|
|
4
|
+
class SuiteRun
|
|
5
|
+
attr_reader :result
|
|
6
|
+
|
|
7
|
+
def initialize(&block)
|
|
8
|
+
@block = block
|
|
9
|
+
@ran = false
|
|
10
|
+
@result = nil
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def run
|
|
14
|
+
raise AroundSuiteRunError, "around_suite hook called suite.run more than once" if ran?
|
|
15
|
+
|
|
16
|
+
@ran = true
|
|
17
|
+
@result = @block.call
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def ran?
|
|
21
|
+
@ran
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
data/lib/smartest/test_case.rb
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
module Smartest
|
|
4
4
|
class TestCase
|
|
5
|
-
attr_reader :name, :metadata, :block, :location, :fixture_names
|
|
5
|
+
attr_reader :name, :metadata, :block, :location, :fixture_names, :around_test_hooks
|
|
6
6
|
|
|
7
|
-
def initialize(name:, metadata:, block:, location:)
|
|
7
|
+
def initialize(name:, metadata:, block:, location:, around_test_hooks: [])
|
|
8
8
|
raise ArgumentError, "test name is required" if name.nil? || name.to_s.empty?
|
|
9
9
|
raise ArgumentError, "test block is required" unless block
|
|
10
10
|
|
|
@@ -12,6 +12,7 @@ module Smartest
|
|
|
12
12
|
@metadata = metadata
|
|
13
13
|
@block = block
|
|
14
14
|
@location = location
|
|
15
|
+
@around_test_hooks = around_test_hooks.dup.freeze
|
|
15
16
|
@fixture_names = ParameterExtractor.required_keyword_names(block, usage: :test)
|
|
16
17
|
end
|
|
17
18
|
|
data/lib/smartest/test_result.rb
CHANGED
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
module Smartest
|
|
4
4
|
class TestResult
|
|
5
|
-
attr_reader :test_case, :status, :error, :duration, :cleanup_errors
|
|
5
|
+
attr_reader :test_case, :status, :error, :duration, :cleanup_errors, :reason
|
|
6
6
|
|
|
7
7
|
def self.passed(test_case:, duration:, cleanup_errors: [])
|
|
8
8
|
new(
|
|
9
9
|
test_case: test_case,
|
|
10
10
|
status: :passed,
|
|
11
11
|
error: nil,
|
|
12
|
+
reason: nil,
|
|
12
13
|
duration: duration,
|
|
13
14
|
cleanup_errors: cleanup_errors
|
|
14
15
|
)
|
|
@@ -19,15 +20,39 @@ module Smartest
|
|
|
19
20
|
test_case: test_case,
|
|
20
21
|
status: :failed,
|
|
21
22
|
error: error,
|
|
23
|
+
reason: nil,
|
|
22
24
|
duration: duration,
|
|
23
25
|
cleanup_errors: cleanup_errors
|
|
24
26
|
)
|
|
25
27
|
end
|
|
26
28
|
|
|
27
|
-
def
|
|
29
|
+
def self.skipped(test_case:, reason:, duration:, cleanup_errors: [])
|
|
30
|
+
new(
|
|
31
|
+
test_case: test_case,
|
|
32
|
+
status: :skipped,
|
|
33
|
+
error: nil,
|
|
34
|
+
reason: reason,
|
|
35
|
+
duration: duration,
|
|
36
|
+
cleanup_errors: cleanup_errors
|
|
37
|
+
)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.pending(test_case:, reason:, duration:, cleanup_errors: [])
|
|
41
|
+
new(
|
|
42
|
+
test_case: test_case,
|
|
43
|
+
status: :pending,
|
|
44
|
+
error: nil,
|
|
45
|
+
reason: reason,
|
|
46
|
+
duration: duration,
|
|
47
|
+
cleanup_errors: cleanup_errors
|
|
48
|
+
)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def initialize(test_case:, status:, error:, reason:, duration:, cleanup_errors:)
|
|
28
52
|
@test_case = test_case
|
|
29
53
|
@status = status
|
|
30
54
|
@error = error
|
|
55
|
+
@reason = reason
|
|
31
56
|
@duration = duration
|
|
32
57
|
@cleanup_errors = cleanup_errors
|
|
33
58
|
end
|
|
@@ -39,5 +64,13 @@ module Smartest
|
|
|
39
64
|
def failed?
|
|
40
65
|
status == :failed
|
|
41
66
|
end
|
|
67
|
+
|
|
68
|
+
def skipped?
|
|
69
|
+
status == :skipped
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def pending?
|
|
73
|
+
status == :pending
|
|
74
|
+
end
|
|
42
75
|
end
|
|
43
76
|
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Smartest
|
|
4
|
+
class TestRun
|
|
5
|
+
attr_reader :result
|
|
6
|
+
|
|
7
|
+
def initialize(fixture_classes:, matcher_modules:, &block)
|
|
8
|
+
@fixture_classes = FixtureClassRegistry.new
|
|
9
|
+
fixture_classes.each { |fixture_class| @fixture_classes.add(fixture_class) }
|
|
10
|
+
|
|
11
|
+
@matcher_modules = MatcherRegistry.new
|
|
12
|
+
matcher_modules.each { |matcher_module| @matcher_modules.add(matcher_module) }
|
|
13
|
+
|
|
14
|
+
@block = block
|
|
15
|
+
@ran = false
|
|
16
|
+
@result = nil
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def run
|
|
20
|
+
raise AroundTestRunError, "around_test hook called test.run more than once" if ran?
|
|
21
|
+
|
|
22
|
+
@ran = true
|
|
23
|
+
@result = @block.call(
|
|
24
|
+
fixture_classes: @fixture_classes,
|
|
25
|
+
matcher_modules: @matcher_modules
|
|
26
|
+
)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def ran?
|
|
30
|
+
@ran
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def add_fixture_class(klass)
|
|
34
|
+
raise AroundTestRunError, "use_fixture must be called before test.run" if ran?
|
|
35
|
+
|
|
36
|
+
reject_suite_fixture_class!(klass)
|
|
37
|
+
@fixture_classes.add(klass)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def add_matcher_module(matcher_module)
|
|
41
|
+
raise AroundTestRunError, "use_matcher must be called before test.run" if ran?
|
|
42
|
+
|
|
43
|
+
@matcher_modules.add(matcher_module)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
private
|
|
47
|
+
|
|
48
|
+
def reject_suite_fixture_class!(klass)
|
|
49
|
+
return unless klass.is_a?(Class) && klass <= Fixture
|
|
50
|
+
|
|
51
|
+
suite_fixture_names = klass.fixture_definitions.each_value.filter_map do |definition|
|
|
52
|
+
definition.name if definition.scope == :suite
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
raise AroundTestFixtureScopeError.new(klass, suite_fixture_names) if suite_fixture_names.any?
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Smartest
|
|
4
|
+
class TestRunState
|
|
5
|
+
attr_reader :pending_reason
|
|
6
|
+
|
|
7
|
+
def pending(reason = nil)
|
|
8
|
+
@pending_reason = StatusReason.normalize(reason)
|
|
9
|
+
nil
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def pending?
|
|
13
|
+
!@pending_reason.nil?
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
data/lib/smartest/version.rb
CHANGED
data/lib/smartest.rb
CHANGED
|
@@ -11,6 +11,10 @@ require_relative "smartest/fixture_class_registry"
|
|
|
11
11
|
require_relative "smartest/matcher_registry"
|
|
12
12
|
require_relative "smartest/fixture_set"
|
|
13
13
|
require_relative "smartest/suite"
|
|
14
|
+
require_relative "smartest/suite_run"
|
|
15
|
+
require_relative "smartest/test_run_state"
|
|
16
|
+
require_relative "smartest/test_run"
|
|
17
|
+
require_relative "smartest/hook_contexts"
|
|
14
18
|
require_relative "smartest/expectations"
|
|
15
19
|
require_relative "smartest/expectation_target"
|
|
16
20
|
require_relative "smartest/matchers"
|