smartest 0.3.3.alpha4 → 0.5.0.alpha1
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/CHANGELOG.md +22 -17
- data/DEVELOPMENT.md +48 -28
- data/README.md +69 -29
- data/SMARTEST_DESIGN.md +53 -36
- data/exe/smartest +50 -11
- data/lib/smartest/cli_arguments.rb +26 -3
- data/lib/smartest/constant_stub_helpers.rb +4 -4
- data/lib/smartest/fixture.rb +5 -5
- data/lib/smartest/fixture_set.rb +7 -7
- data/lib/smartest/init_browser_generator.rb +3 -3
- data/lib/smartest/reporter.rb +12 -12
- data/lib/smartest/runner.rb +14 -14
- data/lib/smartest/test_result.rb +11 -11
- data/lib/smartest/version.rb +1 -1
- data/smartest/simple_stub_test.rb +18 -18
- data/smartest/smartest_test.rb +133 -27
- data/smartest.gemspec +10 -3
- metadata +12 -7
data/SMARTEST_DESIGN.md
CHANGED
|
@@ -30,7 +30,7 @@ Fixture definitions:
|
|
|
30
30
|
class WebFixture < Smartest::Fixture
|
|
31
31
|
fixture :server do
|
|
32
32
|
server = TestServer.start
|
|
33
|
-
|
|
33
|
+
on_teardown { server.stop }
|
|
34
34
|
|
|
35
35
|
server.wait_until_ready!
|
|
36
36
|
server
|
|
@@ -195,12 +195,12 @@ server teardown
|
|
|
195
195
|
|
|
196
196
|
This is especially complex when fixtures depend on other fixtures.
|
|
197
197
|
|
|
198
|
-
Smartest instead chooses `
|
|
198
|
+
Smartest instead chooses `on_teardown` for the MVP:
|
|
199
199
|
|
|
200
200
|
```ruby
|
|
201
201
|
fixture :server do
|
|
202
202
|
server = TestServer.start
|
|
203
|
-
|
|
203
|
+
on_teardown { server.stop }
|
|
204
204
|
|
|
205
205
|
server.wait_until_ready!
|
|
206
206
|
server
|
|
@@ -214,7 +214,7 @@ This has several advantages:
|
|
|
214
214
|
- teardown is local to the fixture that owns the resource
|
|
215
215
|
- implementation is simple
|
|
216
216
|
- fixture dependencies remain ordinary recursive resolution
|
|
217
|
-
-
|
|
217
|
+
- teardown runs in `ensure`
|
|
218
218
|
|
|
219
219
|
Not every fixture needs teardown, so teardown should not shape the entire fixture API.
|
|
220
220
|
|
|
@@ -236,12 +236,12 @@ fixture :article do |user:|
|
|
|
236
236
|
end
|
|
237
237
|
```
|
|
238
238
|
|
|
239
|
-
A fixture may register
|
|
239
|
+
A fixture may register teardown.
|
|
240
240
|
|
|
241
241
|
```ruby
|
|
242
242
|
fixture :temp_dir do
|
|
243
243
|
dir = Dir.mktmpdir
|
|
244
|
-
|
|
244
|
+
on_teardown { FileUtils.rm_rf(dir) }
|
|
245
245
|
dir
|
|
246
246
|
end
|
|
247
247
|
```
|
|
@@ -316,7 +316,7 @@ Runner
|
|
|
316
316
|
├── creates FixtureSet
|
|
317
317
|
├── resolves keyword fixtures
|
|
318
318
|
├── executes test body
|
|
319
|
-
├── runs
|
|
319
|
+
├── runs teardown
|
|
320
320
|
└── reports TestResult
|
|
321
321
|
```
|
|
322
322
|
|
|
@@ -343,7 +343,7 @@ end
|
|
|
343
343
|
|
|
344
344
|
fixture :server do
|
|
345
345
|
server = TestServer.start
|
|
346
|
-
|
|
346
|
+
on_teardown { server.stop }
|
|
347
347
|
server
|
|
348
348
|
end
|
|
349
349
|
|
|
@@ -363,7 +363,7 @@ resolve logged_in_client
|
|
|
363
363
|
requires server
|
|
364
364
|
resolve server
|
|
365
365
|
evaluate server block
|
|
366
|
-
register
|
|
366
|
+
register teardown
|
|
367
367
|
cache server
|
|
368
368
|
evaluate client block with server:
|
|
369
369
|
cache client
|
|
@@ -376,7 +376,7 @@ resolve logged_in_client
|
|
|
376
376
|
|
|
377
377
|
execute test body with logged_in_client:
|
|
378
378
|
|
|
379
|
-
run
|
|
379
|
+
run teardown stack in reverse order
|
|
380
380
|
```
|
|
381
381
|
|
|
382
382
|
## Fixture caching
|
|
@@ -397,33 +397,33 @@ shared for the runner lifetime.
|
|
|
397
397
|
This keeps regular fixtures isolated while allowing explicit suite fixtures for
|
|
398
398
|
expensive shared resources.
|
|
399
399
|
|
|
400
|
-
##
|
|
400
|
+
## Teardown stack
|
|
401
401
|
|
|
402
|
-
`FixtureSet` owns a
|
|
402
|
+
`FixtureSet` owns a teardown stack for one fixture scope.
|
|
403
403
|
|
|
404
404
|
```ruby
|
|
405
|
-
@
|
|
405
|
+
@teardowns = []
|
|
406
406
|
```
|
|
407
407
|
|
|
408
408
|
Fixture blocks can call:
|
|
409
409
|
|
|
410
410
|
```ruby
|
|
411
|
-
|
|
411
|
+
on_teardown { resource.close }
|
|
412
412
|
```
|
|
413
413
|
|
|
414
414
|
This delegates to:
|
|
415
415
|
|
|
416
416
|
```ruby
|
|
417
|
-
fixture_set.
|
|
417
|
+
fixture_set.add_teardown(&block)
|
|
418
418
|
```
|
|
419
419
|
|
|
420
|
-
For test-scoped fixtures,
|
|
420
|
+
For test-scoped fixtures, teardown runs after the test in reverse order:
|
|
421
421
|
|
|
422
422
|
```ruby
|
|
423
|
-
@
|
|
423
|
+
@teardowns.reverse_each(&:call)
|
|
424
424
|
```
|
|
425
425
|
|
|
426
|
-
For suite-scoped fixtures,
|
|
426
|
+
For suite-scoped fixtures, teardown runs after all tests. Reverse order matters
|
|
427
427
|
because later resources may depend on earlier ones.
|
|
428
428
|
|
|
429
429
|
Example:
|
|
@@ -431,18 +431,18 @@ Example:
|
|
|
431
431
|
```ruby
|
|
432
432
|
fixture :server do
|
|
433
433
|
server = TestServer.start
|
|
434
|
-
|
|
434
|
+
on_teardown { server.stop }
|
|
435
435
|
server
|
|
436
436
|
end
|
|
437
437
|
|
|
438
438
|
fixture :browser do |server:|
|
|
439
439
|
browser = Browser.launch(server.url)
|
|
440
|
-
|
|
440
|
+
on_teardown { browser.close }
|
|
441
441
|
browser
|
|
442
442
|
end
|
|
443
443
|
```
|
|
444
444
|
|
|
445
|
-
|
|
445
|
+
Teardown should run:
|
|
446
446
|
|
|
447
447
|
```text
|
|
448
448
|
browser.close
|
|
@@ -669,7 +669,7 @@ Fixture block execution happens on the fixture instance:
|
|
|
669
669
|
fixture_instance.instance_exec(**dependencies, &definition.block)
|
|
670
670
|
```
|
|
671
671
|
|
|
672
|
-
This allows fixture helper methods and `
|
|
672
|
+
This allows fixture helper methods and `on_teardown` to be private instance methods.
|
|
673
673
|
|
|
674
674
|
## Helper methods in fixtures
|
|
675
675
|
|
|
@@ -856,7 +856,24 @@ If no paths are given:
|
|
|
856
856
|
bundle exec smartest
|
|
857
857
|
```
|
|
858
858
|
|
|
859
|
-
should default to
|
|
859
|
+
should default to `smartest/**/*_test.rb` when `smartest/` exists. If the
|
|
860
|
+
directory does not exist, the CLI should print scaffold guidance and exit with
|
|
861
|
+
status `1`:
|
|
862
|
+
|
|
863
|
+
```text
|
|
864
|
+
No smartest/ directory found.
|
|
865
|
+
|
|
866
|
+
To create a Smartest test scaffold:
|
|
867
|
+
bundle exec smartest --init
|
|
868
|
+
|
|
869
|
+
For browser tests:
|
|
870
|
+
bundle exec smartest --init-browser
|
|
871
|
+
|
|
872
|
+
See all commands:
|
|
873
|
+
bundle exec smartest --help
|
|
874
|
+
```
|
|
875
|
+
|
|
876
|
+
Default paths:
|
|
860
877
|
|
|
861
878
|
```text
|
|
862
879
|
smartest/**/*_test.rb
|
|
@@ -877,8 +894,8 @@ arguments.files.each { |file| load File.expand_path(file) }
|
|
|
877
894
|
exit Smartest::Runner.new(tests: arguments.select_tests(Smartest.suite.tests)).run
|
|
878
895
|
```
|
|
879
896
|
|
|
880
|
-
`Smartest::CLIArguments` should support file paths,
|
|
881
|
-
and `path:start-end` filters.
|
|
897
|
+
`Smartest::CLIArguments` should support file paths, directory paths, shell
|
|
898
|
+
globs, `path:line`, and `path:start-end` filters.
|
|
882
899
|
|
|
883
900
|
`smartest/autorun` should use `at_exit`.
|
|
884
901
|
|
|
@@ -947,7 +964,7 @@ end
|
|
|
947
964
|
```
|
|
948
965
|
|
|
949
966
|
`around_suite` wraps the full suite body, including all tests and suite fixture
|
|
950
|
-
|
|
967
|
+
teardown. The hook receives a run target and must call `suite.run` exactly once.
|
|
951
968
|
Multiple hooks compose in registration order, with the first hook as the
|
|
952
969
|
outermost wrapper.
|
|
953
970
|
|
|
@@ -996,7 +1013,7 @@ For `around_test`, those registrations are test-run local and must happen before
|
|
|
996
1013
|
`test.run`.
|
|
997
1014
|
|
|
998
1015
|
Fixture classes registered from `around_test` must not define `suite_fixture`.
|
|
999
|
-
Suite-scoped fixtures need suite-level cache and
|
|
1016
|
+
Suite-scoped fixtures need suite-level cache and teardown ownership, so classes
|
|
1000
1017
|
with suite-scoped fixtures must be registered from `around_suite`.
|
|
1001
1018
|
|
|
1002
1019
|
Potential simpler per-test API:
|
|
@@ -1019,7 +1036,7 @@ Order:
|
|
|
1019
1036
|
before hooks
|
|
1020
1037
|
fixture setup
|
|
1021
1038
|
test body
|
|
1022
|
-
fixture
|
|
1039
|
+
fixture teardown
|
|
1023
1040
|
after hooks
|
|
1024
1041
|
```
|
|
1025
1042
|
|
|
@@ -1030,12 +1047,12 @@ fixture setup
|
|
|
1030
1047
|
before hooks
|
|
1031
1048
|
test body
|
|
1032
1049
|
after hooks
|
|
1033
|
-
fixture
|
|
1050
|
+
fixture teardown
|
|
1034
1051
|
```
|
|
1035
1052
|
|
|
1036
1053
|
This needs a final decision later.
|
|
1037
1054
|
|
|
1038
|
-
Fixture
|
|
1055
|
+
Fixture teardown already handles resource-specific teardown.
|
|
1039
1056
|
|
|
1040
1057
|
### Around-test parallelism note
|
|
1041
1058
|
|
|
@@ -1069,7 +1086,7 @@ Expensive shared resources can use `suite_fixture`:
|
|
|
1069
1086
|
```ruby
|
|
1070
1087
|
suite_fixture :server do
|
|
1071
1088
|
server = TestServer.start
|
|
1072
|
-
|
|
1089
|
+
on_teardown { server.stop }
|
|
1073
1090
|
server
|
|
1074
1091
|
end
|
|
1075
1092
|
```
|
|
@@ -1082,7 +1099,7 @@ Supported scopes:
|
|
|
1082
1099
|
`fixture :name do ... end` creates a test-scoped fixture.
|
|
1083
1100
|
|
|
1084
1101
|
`suite_fixture :name do ... end` creates a suite-scoped fixture. It is lazy:
|
|
1085
|
-
setup runs the first time a test requests it, and
|
|
1102
|
+
setup runs the first time a test requests it, and teardown runs after all tests.
|
|
1086
1103
|
|
|
1087
1104
|
Test-scoped fixtures may depend on suite-scoped fixtures. Suite-scoped fixtures
|
|
1088
1105
|
may depend only on other suite-scoped fixtures.
|
|
@@ -1119,7 +1136,7 @@ Benefits:
|
|
|
1119
1136
|
- reusable fixture modules
|
|
1120
1137
|
- clearer organization
|
|
1121
1138
|
- fewer global definitions
|
|
1122
|
-
- natural place for
|
|
1139
|
+
- natural place for teardown helper
|
|
1123
1140
|
|
|
1124
1141
|
Example:
|
|
1125
1142
|
|
|
@@ -1180,7 +1197,7 @@ Pros:
|
|
|
1180
1197
|
- easy dependency extraction
|
|
1181
1198
|
- easy duplicate detection
|
|
1182
1199
|
- easy source locations
|
|
1183
|
-
- easy
|
|
1200
|
+
- easy teardown integration
|
|
1184
1201
|
|
|
1185
1202
|
### `fixture def user`
|
|
1186
1203
|
|
|
@@ -1224,7 +1241,7 @@ Reason:
|
|
|
1224
1241
|
|
|
1225
1242
|
- requires around-chain execution
|
|
1226
1243
|
- complicates dependency handling
|
|
1227
|
-
- not needed if `
|
|
1244
|
+
- not needed if `on_teardown` exists
|
|
1228
1245
|
- makes fixture API more complex
|
|
1229
1246
|
|
|
1230
1247
|
Could be added later as advanced API.
|
|
@@ -1254,7 +1271,7 @@ class AppFixture < Smartest::Fixture
|
|
|
1254
1271
|
|
|
1255
1272
|
fixture :server do
|
|
1256
1273
|
server = TestServer.start
|
|
1257
|
-
|
|
1274
|
+
on_teardown { server.stop }
|
|
1258
1275
|
server
|
|
1259
1276
|
end
|
|
1260
1277
|
|
data/exe/smartest
CHANGED
|
@@ -7,18 +7,51 @@ require "smartest"
|
|
|
7
7
|
|
|
8
8
|
usage = <<~USAGE
|
|
9
9
|
Usage:
|
|
10
|
-
smartest [
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
smartest
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
10
|
+
bundle exec smartest [options] [paths...]
|
|
11
|
+
|
|
12
|
+
Common commands:
|
|
13
|
+
bundle exec smartest
|
|
14
|
+
Run tests under smartest/**/*_test.rb
|
|
15
|
+
|
|
16
|
+
bundle exec smartest smartest/suite1/
|
|
17
|
+
Run test files matching smartest/suite1/**/*_test.rb
|
|
18
|
+
|
|
19
|
+
bundle exec smartest smartest/user_test.rb
|
|
20
|
+
Run one test file
|
|
21
|
+
|
|
22
|
+
bundle exec smartest smartest/user_test.rb:12
|
|
23
|
+
Run tests around line 12
|
|
24
|
+
|
|
25
|
+
bundle exec smartest --init
|
|
26
|
+
Generate a basic Smartest scaffold
|
|
27
|
+
|
|
28
|
+
bundle exec smartest --init-browser
|
|
29
|
+
Generate a Playwright browser-test scaffold
|
|
30
|
+
|
|
31
|
+
Options:
|
|
32
|
+
--profile N
|
|
33
|
+
Print the N slowest tests. Defaults to 5.
|
|
34
|
+
|
|
35
|
+
--version, -v
|
|
36
|
+
Print the installed Smartest version.
|
|
37
|
+
|
|
38
|
+
--help, -h
|
|
39
|
+
Print this help.
|
|
20
40
|
USAGE
|
|
21
41
|
|
|
42
|
+
missing_smartest_directory_message = <<~MESSAGE
|
|
43
|
+
No smartest/ directory found.
|
|
44
|
+
|
|
45
|
+
To create a Smartest test scaffold:
|
|
46
|
+
bundle exec smartest --init
|
|
47
|
+
|
|
48
|
+
For browser tests:
|
|
49
|
+
bundle exec smartest --init-browser
|
|
50
|
+
|
|
51
|
+
See all commands:
|
|
52
|
+
bundle exec smartest --help
|
|
53
|
+
MESSAGE
|
|
54
|
+
|
|
22
55
|
command = :run
|
|
23
56
|
|
|
24
57
|
begin
|
|
@@ -45,10 +78,16 @@ begin
|
|
|
45
78
|
Smartest.disable_autorun!
|
|
46
79
|
Smartest.install_dsl!
|
|
47
80
|
test_load_path = File.expand_path("smartest", Dir.pwd)
|
|
48
|
-
$LOAD_PATH.unshift(test_load_path) if Dir.exist?(test_load_path) && !$LOAD_PATH.include?(test_load_path)
|
|
49
81
|
|
|
50
82
|
arguments = Smartest::CLIArguments.new(ARGV)
|
|
51
83
|
|
|
84
|
+
if arguments.default_paths? && !Dir.exist?(test_load_path)
|
|
85
|
+
puts missing_smartest_directory_message
|
|
86
|
+
exit 1
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
$LOAD_PATH.unshift(test_load_path) if Dir.exist?(test_load_path) && !$LOAD_PATH.include?(test_load_path)
|
|
90
|
+
|
|
52
91
|
arguments.files.each do |file|
|
|
53
92
|
load File.expand_path(file)
|
|
54
93
|
end
|
|
@@ -5,6 +5,7 @@ require "set"
|
|
|
5
5
|
module Smartest
|
|
6
6
|
class CLIArguments
|
|
7
7
|
DEFAULT_PROFILE_COUNT = 5
|
|
8
|
+
DEFAULT_PATHS = ["smartest/**/*_test.rb"].freeze
|
|
8
9
|
|
|
9
10
|
attr_reader :files, :line_filters, :profile_count
|
|
10
11
|
|
|
@@ -13,15 +14,25 @@ module Smartest
|
|
|
13
14
|
@whole_files = Set.new
|
|
14
15
|
@line_filters = Hash.new { |hash, key| hash[key] = Set.new }
|
|
15
16
|
@profile_count = DEFAULT_PROFILE_COUNT
|
|
17
|
+
@default_paths = false
|
|
16
18
|
|
|
17
19
|
paths = extract_options(argv)
|
|
18
|
-
|
|
20
|
+
if paths.empty?
|
|
21
|
+
@default_paths = true
|
|
22
|
+
paths = DEFAULT_PATHS
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
parse_paths(paths)
|
|
19
26
|
end
|
|
20
27
|
|
|
21
28
|
def filter_tests?
|
|
22
29
|
@line_filters.any?
|
|
23
30
|
end
|
|
24
31
|
|
|
32
|
+
def default_paths?
|
|
33
|
+
@default_paths
|
|
34
|
+
end
|
|
35
|
+
|
|
25
36
|
def select_tests(tests)
|
|
26
37
|
return tests unless filter_tests?
|
|
27
38
|
|
|
@@ -64,8 +75,7 @@ module Smartest
|
|
|
64
75
|
def parse_paths(paths)
|
|
65
76
|
paths.each do |argument|
|
|
66
77
|
pattern, line_filter = split_line_filter(argument)
|
|
67
|
-
|
|
68
|
-
files = matches.empty? ? [pattern] : matches
|
|
78
|
+
files = expand_path_pattern(pattern)
|
|
69
79
|
|
|
70
80
|
files.each do |file|
|
|
71
81
|
@files << file
|
|
@@ -82,6 +92,19 @@ module Smartest
|
|
|
82
92
|
@files.uniq!
|
|
83
93
|
end
|
|
84
94
|
|
|
95
|
+
def expand_path_pattern(pattern)
|
|
96
|
+
matches = Dir[pattern]
|
|
97
|
+
return [pattern] if matches.empty?
|
|
98
|
+
|
|
99
|
+
matches.flat_map do |match|
|
|
100
|
+
if File.directory?(match)
|
|
101
|
+
Dir[File.join(match, "**", "*_test.rb")]
|
|
102
|
+
else
|
|
103
|
+
match
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
85
108
|
def split_line_filter(argument)
|
|
86
109
|
match = argument.match(/\A(.+):(\d+)(?:-(\d+))?\z/)
|
|
87
110
|
return [argument, nil] unless match
|
|
@@ -4,10 +4,10 @@ module Smartest
|
|
|
4
4
|
module ConstantStubHelpers
|
|
5
5
|
private
|
|
6
6
|
|
|
7
|
-
def
|
|
8
|
-
raise ArgumentError, "
|
|
7
|
+
def with_stub_const(constant_path, value)
|
|
8
|
+
raise ArgumentError, "with_stub_const block is required" unless block_given?
|
|
9
9
|
|
|
10
|
-
owner, constant_name =
|
|
10
|
+
owner, constant_name = resolve_with_stub_constant(constant_path)
|
|
11
11
|
original_defined = owner.const_defined?(constant_name, false)
|
|
12
12
|
original_value = owner.const_get(constant_name, false) if original_defined
|
|
13
13
|
|
|
@@ -22,7 +22,7 @@ module Smartest
|
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
|
|
25
|
-
def
|
|
25
|
+
def resolve_with_stub_constant(constant_path)
|
|
26
26
|
unless constant_path.is_a?(String) || constant_path.is_a?(Symbol)
|
|
27
27
|
raise ArgumentError, "constant path must be a String or Symbol"
|
|
28
28
|
end
|
data/lib/smartest/fixture.rb
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
module Smartest
|
|
4
4
|
class Fixture
|
|
5
|
-
RESERVED_CONTEXT_METHODS = %i[skip pending
|
|
5
|
+
RESERVED_CONTEXT_METHODS = %i[skip pending with_stub_const].freeze
|
|
6
6
|
|
|
7
7
|
class << self
|
|
8
8
|
def fixture(name, scope: :test, &block)
|
|
@@ -59,10 +59,10 @@ module Smartest
|
|
|
59
59
|
|
|
60
60
|
private
|
|
61
61
|
|
|
62
|
-
def
|
|
63
|
-
raise ArgumentError, "
|
|
62
|
+
def on_teardown(&block)
|
|
63
|
+
raise ArgumentError, "on_teardown block is required" unless block
|
|
64
64
|
|
|
65
|
-
@fixture_set.
|
|
65
|
+
@fixture_set.add_teardown(&block)
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
def simple_stub_any_instance_of(klass, method_name, &block)
|
|
@@ -75,7 +75,7 @@ module Smartest
|
|
|
75
75
|
|
|
76
76
|
def apply_simple_stub(stub)
|
|
77
77
|
stub.apply!
|
|
78
|
-
|
|
78
|
+
on_teardown { stub.reset }
|
|
79
79
|
stub
|
|
80
80
|
end
|
|
81
81
|
|
data/lib/smartest/fixture_set.rb
CHANGED
|
@@ -9,7 +9,7 @@ module Smartest
|
|
|
9
9
|
@parent = parent
|
|
10
10
|
@cache = {}
|
|
11
11
|
@setup_errors = {}
|
|
12
|
-
@
|
|
12
|
+
@teardowns = []
|
|
13
13
|
@resolving = []
|
|
14
14
|
|
|
15
15
|
build_fixture_index
|
|
@@ -49,17 +49,17 @@ module Smartest
|
|
|
49
49
|
@resolving.pop if @resolving.last == symbol_name
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
-
def
|
|
53
|
-
raise ArgumentError, "
|
|
52
|
+
def add_teardown(&block)
|
|
53
|
+
raise ArgumentError, "on_teardown block is required" unless block
|
|
54
54
|
|
|
55
|
-
@
|
|
55
|
+
@teardowns << block
|
|
56
56
|
end
|
|
57
57
|
|
|
58
|
-
def
|
|
58
|
+
def run_teardowns
|
|
59
59
|
errors = []
|
|
60
60
|
|
|
61
|
-
@
|
|
62
|
-
|
|
61
|
+
@teardowns.reverse_each do |teardown|
|
|
62
|
+
teardown.call
|
|
63
63
|
rescue Exception => error
|
|
64
64
|
raise if Smartest.fatal_exception?(error)
|
|
65
65
|
|
|
@@ -14,7 +14,7 @@ module Smartest
|
|
|
14
14
|
runtime = Playwright.create(
|
|
15
15
|
playwright_cli_executable_path: "./node_modules/.bin/playwright",
|
|
16
16
|
)
|
|
17
|
-
|
|
17
|
+
on_teardown { runtime.stop }
|
|
18
18
|
runtime.playwright
|
|
19
19
|
end
|
|
20
20
|
|
|
@@ -35,13 +35,13 @@ module Smartest
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
browser = playwright.send(browser_type).launch(**launch_options)
|
|
38
|
-
|
|
38
|
+
on_teardown { browser.close }
|
|
39
39
|
browser
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
fixture :page do |browser:|
|
|
43
43
|
context = browser.new_context
|
|
44
|
-
|
|
44
|
+
on_teardown { context.close }
|
|
45
45
|
context.new_page
|
|
46
46
|
end
|
|
47
47
|
end
|
data/lib/smartest/reporter.rb
CHANGED
|
@@ -21,14 +21,14 @@ module Smartest
|
|
|
21
21
|
@io.puts record_line(result)
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
-
def finish(results,
|
|
24
|
+
def finish(results, suite_teardown_errors: [], suite_errors: [])
|
|
25
25
|
failures = results.select(&:failed?)
|
|
26
26
|
skipped = results.select(&:skipped?)
|
|
27
27
|
pending = results.select(&:pending?)
|
|
28
28
|
|
|
29
29
|
report_failures(failures) if failures.any?
|
|
30
30
|
report_suite_errors(suite_errors) if suite_errors.any?
|
|
31
|
-
|
|
31
|
+
report_suite_teardown_errors(suite_teardown_errors) if suite_teardown_errors.any?
|
|
32
32
|
report_profile(results) if @profile_count && @profile_count.positive?
|
|
33
33
|
|
|
34
34
|
@io.puts
|
|
@@ -39,9 +39,9 @@ module Smartest
|
|
|
39
39
|
suite_label = suite_errors.count == 1 ? "suite failure" : "suite failures"
|
|
40
40
|
summary = "#{summary}, #{suite_errors.count} #{suite_label}"
|
|
41
41
|
end
|
|
42
|
-
if
|
|
43
|
-
|
|
44
|
-
summary = "#{summary}, #{
|
|
42
|
+
if suite_teardown_errors.any?
|
|
43
|
+
teardown_label = suite_teardown_errors.count == 1 ? "suite teardown" : "suite teardowns"
|
|
44
|
+
summary = "#{summary}, #{suite_teardown_errors.count} #{teardown_label} failed"
|
|
45
45
|
end
|
|
46
46
|
@io.puts summary
|
|
47
47
|
end
|
|
@@ -72,7 +72,7 @@ module Smartest
|
|
|
72
72
|
@io.puts "#{index + 1}) #{result.test_case.name}"
|
|
73
73
|
report_location(result.test_case.location)
|
|
74
74
|
report_error(result.error) if result.error
|
|
75
|
-
result.
|
|
75
|
+
result.teardown_errors.each { |error| report_teardown_error(error) }
|
|
76
76
|
@io.puts
|
|
77
77
|
end
|
|
78
78
|
end
|
|
@@ -89,14 +89,14 @@ module Smartest
|
|
|
89
89
|
end
|
|
90
90
|
end
|
|
91
91
|
|
|
92
|
-
def
|
|
92
|
+
def report_suite_teardown_errors(errors)
|
|
93
93
|
@io.puts
|
|
94
|
-
@io.puts "Suite
|
|
94
|
+
@io.puts "Suite teardown failures:"
|
|
95
95
|
@io.puts
|
|
96
96
|
|
|
97
97
|
errors.each_with_index do |error, index|
|
|
98
|
-
@io.puts "#{index + 1}) suite
|
|
99
|
-
|
|
98
|
+
@io.puts "#{index + 1}) suite teardown"
|
|
99
|
+
report_teardown_error(error)
|
|
100
100
|
@io.puts
|
|
101
101
|
end
|
|
102
102
|
end
|
|
@@ -148,8 +148,8 @@ module Smartest
|
|
|
148
148
|
report_backtrace(error)
|
|
149
149
|
end
|
|
150
150
|
|
|
151
|
-
def
|
|
152
|
-
@io.puts "
|
|
151
|
+
def report_teardown_error(error)
|
|
152
|
+
@io.puts " teardown failed: #{error.class}: #{error.message}"
|
|
153
153
|
report_backtrace(error)
|
|
154
154
|
end
|
|
155
155
|
|