smartest 0.4.0 → 0.5.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3d2b5aeaf51e6e6878eac74601d634daab2e423cede641216856a79188c28554
4
- data.tar.gz: 4f90e558f84062585a0a8b3596c91f9507f9fec09430a86c6782ae7a3ba92bb7
3
+ metadata.gz: e192221b36307c61da97572a41e866b137f1a668bb9db26bda75fbd6489df89a
4
+ data.tar.gz: eb3ee1b6ffae15eaf27b88ffbe4d01bfedbb763a7a1d52bb99bae34bd7e8dc97
5
5
  SHA512:
6
- metadata.gz: 687150dcb8a16d475d76b9840fecf63b7705fc0b5e123380d6ffe3fe415a77ed89228bdbc098e66db22d67164f4b43412229e47311be15b6ab09643bf00aa43f
7
- data.tar.gz: 037f50862bd76bcb86e4511227a8a5f2ce943e37fdce3d823124ff90872efa1a808bb7eee4a2ab9c0985c685baf2db451c304074e6797f88d1c2f370390adea6
6
+ metadata.gz: 916737afbb7af9447c571d16de7c08e73ea52686462a2b99c4378a118e38d613fdbe3152f13fbf089fd518b8930c3e8f927451678e58e23777150a3d98158608
7
+ data.tar.gz: fe618761cbe53ad37bde38182018835b7566d7a205d0edd92c7e43547d002b131771bce65f2f82a66b7dc3afa770c190d3d8ccfd4e374398e0e2341aa22baf98
data/CHANGELOG.md CHANGED
@@ -1,19 +1,24 @@
1
1
  # Changelog
2
2
 
3
- ## 0.1.0 - Unreleased
4
-
5
- - Add the initial Smartest test runner.
6
- - Support top-level `test` definitions.
7
- - Support class-based fixtures through `Smartest::Fixture`.
8
- - Support required keyword-argument fixture injection and fixture dependencies.
9
- - Support per-test fixture caching and cleanup.
10
- - Support suite-scoped fixtures through `suite_fixture`.
11
- - Support `eq`, `include`, `start_with`, `end_with`, `be_nil`, `raise_error`, and `change` matchers.
12
- - Support custom matcher modules through `use_matcher`.
13
- - Generate an opt-in `PredicateMatcher` custom matcher for `be_<predicate>` calls.
14
- - Add the `smartest` CLI.
15
- - Add `--help` and `--version` CLI options.
16
- - Use `smartest/**/*_test.rb` as the default CLI glob so Smartest can coexist with Minitest files under `test/`.
17
- - Add gem packaging metadata and release tasks.
18
- - Add Docusaurus documentation.
19
- - Add `smartest --init-browser` with a Playwright init scaffold, fixture setup, matcher generation, and dependency installation.
3
+ ## 0.5.0
4
+
5
+ ### Breaking Changes
6
+
7
+ - Rename the fixture teardown registration API from `cleanup` to
8
+ `on_teardown`. The old `cleanup` method is no longer available.
9
+ - Rename teardown failure output from cleanup terminology to teardown
10
+ terminology.
11
+
12
+ ## 0.4.0
13
+
14
+ ### New Features
15
+
16
+ - Add fixture-scoped method stub helpers: `simple_stub_any_instance_of` and
17
+ `simple_stub`.
18
+ - Add `with_stub_const` for block-scoped constant stubbing in test bodies,
19
+ `around_test`, and `around_suite`.
20
+ - Support Ruby 2.7 and newer.
21
+
22
+ ## 0.1.0 - 0.3.2
23
+
24
+ - Initial release.
data/DEVELOPMENT.md CHANGED
@@ -13,7 +13,7 @@ Smartest is a Ruby test runner focused on:
13
13
  - top-level test definitions
14
14
  - class-based fixtures
15
15
  - explicit keyword-argument fixture dependencies
16
- - optional cleanup for fixtures that need teardown
16
+ - optional teardown for fixtures that need teardown
17
17
  - suite-scoped fixtures for expensive shared resources
18
18
  - a small internal architecture that is easy to reason about
19
19
 
@@ -224,7 +224,7 @@ Responsibilities:
224
224
  - class-level `suite_fixture` DSL for suite-scoped fixtures
225
225
  - stores fixture definitions
226
226
  - supports inheritance
227
- - exposes `cleanup` to fixture blocks
227
+ - exposes `on_teardown` to fixture blocks
228
228
  - optionally delegates helper methods to `ExecutionContext`
229
229
  - does not delegate `skip` or `pending` to fixture blocks
230
230
 
@@ -293,8 +293,8 @@ Responsibilities:
293
293
  - find fixture definitions
294
294
  - resolve fixture dependencies
295
295
  - cache fixture values for its scope
296
- - collect cleanup blocks
297
- - run cleanup blocks in reverse order
296
+ - collect teardown blocks
297
+ - run teardown blocks in reverse order
298
298
  - detect duplicate fixture names
299
299
  - detect circular dependencies
300
300
 
@@ -332,9 +332,9 @@ Responsibilities:
332
332
  - create a fresh `FixtureSet` per test
333
333
  - resolve test keyword fixtures
334
334
  - run test body
335
- - run cleanup in `ensure`
335
+ - run teardown in `ensure`
336
336
  - track skipped and pending test state
337
- - run suite fixture cleanup after all tests
337
+ - run suite fixture teardown after all tests
338
338
  - produce `TestResult`
339
339
  - notify reporter
340
340
 
@@ -373,7 +373,7 @@ rescue Exception => error
373
373
  TestResult.failed(test_case, error)
374
374
  end
375
375
  ensure
376
- fixture_set&.run_cleanups
376
+ fixture_set&.run_teardowns
377
377
  end
378
378
  ```
379
379
 
@@ -424,7 +424,7 @@ end
424
424
 
425
425
  fixture :server do
426
426
  server = TestServer.start
427
- cleanup { server.stop }
427
+ on_teardown { server.stop }
428
428
  server
429
429
  end
430
430
 
@@ -456,12 +456,12 @@ resolve :logged_in_client
456
456
  evaluate logged_in_client
457
457
  cache logged_in_client
458
458
  run test body
459
- run cleanup stack
459
+ run teardown stack
460
460
  ```
461
461
 
462
- ## Cleanup behavior
462
+ ## Teardown behavior
463
463
 
464
- Fixture cleanup is optional.
464
+ Fixture teardown is optional.
465
465
 
466
466
  Fixture without teardown:
467
467
 
@@ -476,33 +476,33 @@ Fixture with teardown:
476
476
  ```ruby
477
477
  fixture :server do
478
478
  server = TestServer.start
479
- cleanup { server.stop }
479
+ on_teardown { server.stop }
480
480
 
481
481
  server.wait_until_ready!
482
482
  server
483
483
  end
484
484
  ```
485
485
 
486
- `cleanup` should register a block on the current fixture set. Regular fixture
487
- cleanups run after the test. `suite_fixture` cleanups run after all tests.
486
+ `on_teardown` should register a block on the current fixture set. Regular fixture
487
+ teardown blocks run after the test. `suite_fixture` teardown blocks run after all tests.
488
488
 
489
- Cleanup blocks must run:
489
+ Teardown blocks must run:
490
490
 
491
491
  - after the test body
492
492
  - after the suite for suite-scoped fixtures
493
493
  - after failed tests
494
- - after fixture setup errors, if cleanup was already registered
494
+ - after fixture setup errors, if teardown was already registered
495
495
  - in reverse registration order
496
496
 
497
497
  Implementation:
498
498
 
499
499
  ```ruby
500
- def add_cleanup(&block)
501
- @cleanups << block
500
+ def add_teardown(&block)
501
+ @teardowns << block
502
502
  end
503
503
 
504
- def run_cleanups
505
- @cleanups.reverse_each(&:call)
504
+ def run_teardowns
505
+ @teardowns.reverse_each(&:call)
506
506
  end
507
507
  ```
508
508
 
@@ -621,17 +621,17 @@ A practical approach:
621
621
  - recursive fixture resolution
622
622
  - per-test caching
623
623
 
624
- ### Phase 4: Cleanup
624
+ ### Phase 4: Teardown
625
625
 
626
- - `cleanup { ... }`
627
- - cleanup stack on `FixtureSet`
628
- - cleanup in `ensure`
626
+ - `on_teardown { ... }`
627
+ - teardown stack on `FixtureSet`
628
+ - teardown in `ensure`
629
629
 
630
630
  ### Phase 5: Suite-scoped fixtures
631
631
 
632
632
  - `suite_fixture :name do ... end`
633
633
  - suite-level fixture cache
634
- - suite cleanup after all tests
634
+ - suite teardown after all tests
635
635
  - test fixtures may depend on suite fixtures
636
636
  - suite fixtures may not depend on test fixtures
637
637
 
@@ -662,14 +662,14 @@ A practical approach:
662
662
 
663
663
  - `around_suite do |suite| ... end`
664
664
  - run hooks around the full suite body
665
- - include suite fixture cleanup inside the wrapped body
665
+ - include suite fixture teardown inside the wrapped body
666
666
  - report hook failures as suite failures
667
667
 
668
668
  ### Phase 8: Test hooks
669
669
 
670
670
  - `around_test do |test| ... end`
671
671
  - snapshot file-local hooks when each test is registered
672
- - run hooks around fixture setup, test body, and fixture cleanup
672
+ - run hooks around fixture setup, test body, and fixture teardown
673
673
  - expose `use_fixture` and `use_matcher` only inside hook contexts
674
674
  - make `around_test` registered from `around_suite` suite-wide
675
675
 
@@ -720,7 +720,7 @@ end
720
720
  ```
721
721
 
722
722
  ```ruby
723
- cleanup { ... }
723
+ on_teardown { ... }
724
724
  ```
725
725
 
726
726
  ```ruby
@@ -843,6 +843,22 @@ Before releasing:
843
843
  - run a sample project against the installed gem
844
844
  - push the release tag
845
845
 
846
+ ### Changelog updates
847
+
848
+ Update `CHANGELOG.md` from the actual diff between released versions, not from
849
+ commit messages. For an already tagged release, compare the previous release tag
850
+ to the release tag and inspect the code/docs changes, for example:
851
+
852
+ ```bash
853
+ git diff --stat 0.4.0..0.5.0
854
+ git diff 0.4.0..0.5.0
855
+ ```
856
+
857
+ Before the new tag exists, compare the latest release tag to the release branch
858
+ or working tree and inspect the same kind of diff. Only document breaking
859
+ changes and notable new features. Do not copy every commit message or list
860
+ documentation-only maintenance changes unless they materially affect users.
861
+
846
862
  Example commands:
847
863
 
848
864
  ```bash
data/README.md CHANGED
@@ -1,7 +1,10 @@
1
- # Smartest introduces Pytest-style fixtures for Ruby
1
+ # Smartest
2
2
 
3
- Smartest is a small Ruby test runner that brings pytest-style fixture
4
- injection, explicit fixture dependencies, and fixture cleanup to Ruby tests.
3
+ [![Gem Version](https://badge.fury.io/rb/smartest.svg)](https://rubygems.org/gems/smartest)
4
+
5
+ Smartest is a Ruby test runner that brings pytest-style fixtures to Ruby,
6
+ with explicit fixture dependencies, automatic teardown, and Playwright-friendly
7
+ browser testing.
5
8
 
6
9
  Tests request fixtures with Ruby keyword arguments. Fixtures define their own
7
10
  dependencies the same way:
@@ -10,7 +13,7 @@ dependencies the same way:
10
13
  class WebFixture < Smartest::Fixture
11
14
  fixture :server do
12
15
  server = TestServer.start
13
- cleanup { server.stop }
16
+ on_teardown { server.stop }
14
17
  server
15
18
  end
16
19
 
@@ -45,7 +48,7 @@ idea: tests should explicitly declare their dependencies.
45
48
  RSpec `let` is useful when examples need lazy helper methods. Minitest `setup`
46
49
  is simple for xUnit-style setup. Rails fixtures and FactoryBot are great for
47
50
  test data. Smartest is aimed at tests where setup resources, dependency graphs,
48
- and cleanup should be visible in the test signature and fixture definitions.
51
+ and teardown should be visible in the test signature and fixture definitions.
49
52
 
50
53
  ```ruby
51
54
  test("GET /me") do |logged_in_client:|
@@ -67,6 +70,9 @@ end
67
70
 
68
71
  Smartest requires Ruby 2.7 or newer.
69
72
 
73
+ Smartest is published as the `smartest` RubyGem:
74
+ [Smartest on RubyGems](https://rubygems.org/gems/smartest).
75
+
70
76
  Add this line to your application's Gemfile:
71
77
 
72
78
  ```ruby
@@ -477,7 +483,7 @@ released after the full suite finishes:
477
483
  class BrowserFixture < Smartest::Fixture
478
484
  suite_fixture :browser do
479
485
  browser = Browser.launch
480
- cleanup { browser.close }
486
+ on_teardown { browser.close }
481
487
  browser
482
488
  end
483
489
 
@@ -488,7 +494,7 @@ end
488
494
  ```
489
495
 
490
496
  Suite fixtures are lazy: setup runs the first time a test requests the fixture,
491
- and cleanup runs once after all tests finish. Test-scoped fixtures can depend on
497
+ and teardown runs once after all tests finish. Test-scoped fixtures can depend on
492
498
  suite fixtures, but suite fixtures cannot depend on test-scoped fixtures.
493
499
 
494
500
  ## Suite hooks
@@ -504,8 +510,8 @@ end
504
510
  ```
505
511
 
506
512
  The hook receives a run target and must call `suite.run` exactly once. The block
507
- wraps every test, test-scoped fixture setup and cleanup, suite fixture setup, and
508
- suite fixture cleanup.
513
+ wraps every test, test-scoped fixture setup and teardown, suite fixture setup, and
514
+ suite fixture teardown.
509
515
 
510
516
  Fixture and matcher registrations made before `suite.run` are applied to that
511
517
  run:
@@ -546,7 +552,7 @@ end
546
552
  ```
547
553
 
548
554
  The hook receives a run target and must call `test.run` exactly once. It wraps
549
- fixture setup, the test body, and fixture cleanup.
555
+ fixture setup, the test body, and fixture teardown.
550
556
 
551
557
  `around_test` is file-scoped when it is written directly in a test file. Smartest
552
558
  copies the current file's `around_test` hooks when each `test` is registered, so
@@ -580,20 +586,20 @@ end
580
586
 
581
587
  Fixture classes registered from `around_test` must define only test-scoped
582
588
  fixtures. If a class defines `suite_fixture`, register it from `around_suite`
583
- instead so its cache and cleanup belong to the suite lifecycle.
589
+ instead so its cache and teardown belong to the suite lifecycle.
584
590
 
585
591
  `use_fixture` and `use_matcher` are only available inside `around_suite` or
586
592
  `around_test` blocks. They are not top-level DSL methods.
587
593
 
588
594
  ## Fixtures with teardown
589
595
 
590
- Not every fixture needs teardown. For fixtures that do, use `cleanup`.
596
+ Not every fixture needs teardown. For fixtures that do, use `on_teardown`.
591
597
 
592
598
  ```ruby
593
599
  class WebFixture < Smartest::Fixture
594
600
  fixture :server do
595
601
  server = TestServer.start
596
- cleanup { server.stop }
602
+ on_teardown { server.stop }
597
603
 
598
604
  server.wait_until_ready!
599
605
  server
@@ -605,8 +611,8 @@ class WebFixture < Smartest::Fixture
605
611
  end
606
612
  ```
607
613
 
608
- `cleanup` blocks run after the fixture's scope finishes. For regular fixtures
609
- that means after the test. For `suite_fixture`, cleanup runs after the full
614
+ `on_teardown` blocks run after the fixture's scope finishes. For regular fixtures
615
+ that means after the test. For `suite_fixture`, teardown runs after the full
610
616
  suite.
611
617
 
612
618
  They are executed in reverse order of registration.
@@ -614,7 +620,7 @@ They are executed in reverse order of registration.
614
620
  ```ruby
615
621
  fixture :temp_dir do
616
622
  dir = Dir.mktmpdir
617
- cleanup { FileUtils.rm_rf(dir) }
623
+ on_teardown { FileUtils.rm_rf(dir) }
618
624
 
619
625
  dir
620
626
  end
@@ -625,19 +631,19 @@ Recommended pattern:
625
631
  ```ruby
626
632
  fixture :server do
627
633
  server = TestServer.start
628
- cleanup { server.stop }
634
+ on_teardown { server.stop }
629
635
 
630
636
  server.wait_until_ready!
631
637
  server
632
638
  end
633
639
  ```
634
640
 
635
- Register cleanup immediately after acquiring the resource, before later setup steps that may fail.
641
+ Register teardown immediately after acquiring the resource, before later setup steps that may fail.
636
642
 
637
643
  ## Stubs
638
644
 
639
645
  Use simple stub helpers when a fixture needs to temporarily replace a Ruby
640
- method and reset it during cleanup:
646
+ method and reset it during teardown:
641
647
 
642
648
  ```ruby
643
649
  class PaymentFixture < Smartest::Fixture
@@ -678,7 +684,7 @@ constants in test bodies, `around_test`, or `around_suite`. Constant stubs are
678
684
  process-global; avoid concurrent tests that stub the same constant.
679
685
 
680
686
  The method stub helpers call `Smartest::SimpleStub` internally, apply the stub,
681
- register `cleanup { stub.reset }`, and return the stub object.
687
+ register `on_teardown { stub.reset }`, and return the stub object.
682
688
  `with_stub_const` records the previous constant value, replaces it, yields to
683
689
  the block, and restores or removes the constant with `ensure`.
684
690
 
@@ -695,7 +701,7 @@ the current Fiber, and `reset!` raises
695
701
  class WebFixture < Smartest::Fixture
696
702
  fixture :server do
697
703
  server = TestServer.start
698
- cleanup { server.stop }
704
+ on_teardown { server.stop }
699
705
 
700
706
  server.wait_until_ready!
701
707
  server
@@ -755,7 +761,7 @@ client setup
755
761
  user setup
756
762
  logged_in_client setup
757
763
  test body
758
- server cleanup
764
+ server teardown
759
765
  ```
760
766
 
761
767
  ## Registering fixture classes
@@ -784,15 +790,15 @@ Fixture names must be unique across registered fixture classes.
784
790
 
785
791
  If two fixture classes define the same fixture name, Smartest raises an error.
786
792
 
787
- ## Suite hooks and fixture cleanup
793
+ ## Suite hooks and fixture teardown
788
794
 
789
- Suite hooks are separate from fixture cleanup. Use fixture cleanup for
795
+ Suite hooks are separate from fixture teardown. Use fixture teardown for
790
796
  resource-specific teardown:
791
797
 
792
798
  ```ruby
793
799
  fixture :server do
794
800
  server = TestServer.start
795
- cleanup { server.stop }
801
+ on_teardown { server.stop }
796
802
  server
797
803
  end
798
804
  ```
@@ -849,7 +855,7 @@ Example:
849
855
  class WebFixture < Smartest::Fixture
850
856
  fixture :server do
851
857
  server = TestServer.start
852
- cleanup { server.stop }
858
+ on_teardown { server.stop }
853
859
  server
854
860
  end
855
861
 
@@ -912,7 +918,7 @@ Smartest currently focuses on a small runner API:
912
918
  - class-based fixtures
913
919
  - keyword-argument fixture injection
914
920
  - fixture dependencies through keyword arguments
915
- - fixture cleanup
921
+ - fixture teardown
916
922
  - suite-scoped fixtures through `suite_fixture`
917
923
  - fixture-scoped method stubs and block-scoped constant stubs
918
924
  - suite hooks with `around_suite`
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
- cleanup { server.stop }
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 `cleanup` for the MVP:
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
- cleanup { server.stop }
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
- - cleanup runs in `ensure`
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 cleanup.
239
+ A fixture may register teardown.
240
240
 
241
241
  ```ruby
242
242
  fixture :temp_dir do
243
243
  dir = Dir.mktmpdir
244
- cleanup { FileUtils.rm_rf(dir) }
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 cleanup
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
- cleanup { server.stop }
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 cleanup
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 cleanup stack in reverse order
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
- ## Cleanup stack
400
+ ## Teardown stack
401
401
 
402
- `FixtureSet` owns a cleanup stack for one fixture scope.
402
+ `FixtureSet` owns a teardown stack for one fixture scope.
403
403
 
404
404
  ```ruby
405
- @cleanups = []
405
+ @teardowns = []
406
406
  ```
407
407
 
408
408
  Fixture blocks can call:
409
409
 
410
410
  ```ruby
411
- cleanup { resource.close }
411
+ on_teardown { resource.close }
412
412
  ```
413
413
 
414
414
  This delegates to:
415
415
 
416
416
  ```ruby
417
- fixture_set.add_cleanup(&block)
417
+ fixture_set.add_teardown(&block)
418
418
  ```
419
419
 
420
- For test-scoped fixtures, cleanup runs after the test in reverse order:
420
+ For test-scoped fixtures, teardown runs after the test in reverse order:
421
421
 
422
422
  ```ruby
423
- @cleanups.reverse_each(&:call)
423
+ @teardowns.reverse_each(&:call)
424
424
  ```
425
425
 
426
- For suite-scoped fixtures, cleanup runs after all tests. Reverse order matters
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
- cleanup { server.stop }
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
- cleanup { browser.close }
440
+ on_teardown { browser.close }
441
441
  browser
442
442
  end
443
443
  ```
444
444
 
445
- Cleanup should run:
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 `cleanup` to be private instance methods.
672
+ This allows fixture helper methods and `on_teardown` to be private instance methods.
673
673
 
674
674
  ## Helper methods in fixtures
675
675
 
@@ -964,7 +964,7 @@ end
964
964
  ```
965
965
 
966
966
  `around_suite` wraps the full suite body, including all tests and suite fixture
967
- cleanup. The hook receives a run target and must call `suite.run` exactly once.
967
+ teardown. The hook receives a run target and must call `suite.run` exactly once.
968
968
  Multiple hooks compose in registration order, with the first hook as the
969
969
  outermost wrapper.
970
970
 
@@ -1013,7 +1013,7 @@ For `around_test`, those registrations are test-run local and must happen before
1013
1013
  `test.run`.
1014
1014
 
1015
1015
  Fixture classes registered from `around_test` must not define `suite_fixture`.
1016
- Suite-scoped fixtures need suite-level cache and cleanup ownership, so classes
1016
+ Suite-scoped fixtures need suite-level cache and teardown ownership, so classes
1017
1017
  with suite-scoped fixtures must be registered from `around_suite`.
1018
1018
 
1019
1019
  Potential simpler per-test API:
@@ -1036,7 +1036,7 @@ Order:
1036
1036
  before hooks
1037
1037
  fixture setup
1038
1038
  test body
1039
- fixture cleanup
1039
+ fixture teardown
1040
1040
  after hooks
1041
1041
  ```
1042
1042
 
@@ -1047,12 +1047,12 @@ fixture setup
1047
1047
  before hooks
1048
1048
  test body
1049
1049
  after hooks
1050
- fixture cleanup
1050
+ fixture teardown
1051
1051
  ```
1052
1052
 
1053
1053
  This needs a final decision later.
1054
1054
 
1055
- Fixture cleanup already handles resource-specific teardown.
1055
+ Fixture teardown already handles resource-specific teardown.
1056
1056
 
1057
1057
  ### Around-test parallelism note
1058
1058
 
@@ -1086,7 +1086,7 @@ Expensive shared resources can use `suite_fixture`:
1086
1086
  ```ruby
1087
1087
  suite_fixture :server do
1088
1088
  server = TestServer.start
1089
- cleanup { server.stop }
1089
+ on_teardown { server.stop }
1090
1090
  server
1091
1091
  end
1092
1092
  ```
@@ -1099,7 +1099,7 @@ Supported scopes:
1099
1099
  `fixture :name do ... end` creates a test-scoped fixture.
1100
1100
 
1101
1101
  `suite_fixture :name do ... end` creates a suite-scoped fixture. It is lazy:
1102
- setup runs the first time a test requests it, and cleanup runs after all tests.
1102
+ setup runs the first time a test requests it, and teardown runs after all tests.
1103
1103
 
1104
1104
  Test-scoped fixtures may depend on suite-scoped fixtures. Suite-scoped fixtures
1105
1105
  may depend only on other suite-scoped fixtures.
@@ -1136,7 +1136,7 @@ Benefits:
1136
1136
  - reusable fixture modules
1137
1137
  - clearer organization
1138
1138
  - fewer global definitions
1139
- - natural place for cleanup helper
1139
+ - natural place for teardown helper
1140
1140
 
1141
1141
  Example:
1142
1142
 
@@ -1197,7 +1197,7 @@ Pros:
1197
1197
  - easy dependency extraction
1198
1198
  - easy duplicate detection
1199
1199
  - easy source locations
1200
- - easy cleanup integration
1200
+ - easy teardown integration
1201
1201
 
1202
1202
  ### `fixture def user`
1203
1203
 
@@ -1241,7 +1241,7 @@ Reason:
1241
1241
 
1242
1242
  - requires around-chain execution
1243
1243
  - complicates dependency handling
1244
- - not needed if `cleanup` exists
1244
+ - not needed if `on_teardown` exists
1245
1245
  - makes fixture API more complex
1246
1246
 
1247
1247
  Could be added later as advanced API.
@@ -1271,7 +1271,7 @@ class AppFixture < Smartest::Fixture
1271
1271
 
1272
1272
  fixture :server do
1273
1273
  server = TestServer.start
1274
- cleanup { server.stop }
1274
+ on_teardown { server.stop }
1275
1275
  server
1276
1276
  end
1277
1277
 
@@ -59,10 +59,10 @@ module Smartest
59
59
 
60
60
  private
61
61
 
62
- def cleanup(&block)
63
- raise ArgumentError, "cleanup block is required" unless block
62
+ def on_teardown(&block)
63
+ raise ArgumentError, "on_teardown block is required" unless block
64
64
 
65
- @fixture_set.add_cleanup(&block)
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
- cleanup { stub.reset }
78
+ on_teardown { stub.reset }
79
79
  stub
80
80
  end
81
81
 
@@ -9,7 +9,7 @@ module Smartest
9
9
  @parent = parent
10
10
  @cache = {}
11
11
  @setup_errors = {}
12
- @cleanups = []
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 add_cleanup(&block)
53
- raise ArgumentError, "cleanup block is required" unless block
52
+ def add_teardown(&block)
53
+ raise ArgumentError, "on_teardown block is required" unless block
54
54
 
55
- @cleanups << block
55
+ @teardowns << block
56
56
  end
57
57
 
58
- def run_cleanups
58
+ def run_teardowns
59
59
  errors = []
60
60
 
61
- @cleanups.reverse_each do |cleanup|
62
- cleanup.call
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
- cleanup { runtime.stop }
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
- cleanup { browser.close }
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
- cleanup { context.close }
44
+ on_teardown { context.close }
45
45
  context.new_page
46
46
  end
47
47
  end
@@ -21,14 +21,14 @@ module Smartest
21
21
  @io.puts record_line(result)
22
22
  end
23
23
 
24
- def finish(results, suite_cleanup_errors: [], suite_errors: [])
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
- report_suite_cleanup_errors(suite_cleanup_errors) if suite_cleanup_errors.any?
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 suite_cleanup_errors.any?
43
- cleanup_label = suite_cleanup_errors.count == 1 ? "suite cleanup" : "suite cleanups"
44
- summary = "#{summary}, #{suite_cleanup_errors.count} #{cleanup_label} failed"
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.cleanup_errors.each { |error| report_cleanup_error(error) }
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 report_suite_cleanup_errors(errors)
92
+ def report_suite_teardown_errors(errors)
93
93
  @io.puts
94
- @io.puts "Suite cleanup failures:"
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 cleanup"
99
- report_cleanup_error(error)
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 report_cleanup_error(error)
152
- @io.puts " cleanup failed: #{error.class}: #{error.message}"
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
 
@@ -10,7 +10,7 @@ module Smartest
10
10
 
11
11
  def run
12
12
  results = []
13
- suite_cleanup_errors = []
13
+ suite_teardown_errors = []
14
14
  suite_errors = []
15
15
  @suite_fixture_set = nil
16
16
 
@@ -18,7 +18,7 @@ module Smartest
18
18
 
19
19
  begin
20
20
  run_around_suite_hooks(@suite.around_suite_hooks.dup) do
21
- run_tests(results, suite_cleanup_errors)
21
+ run_tests(results, suite_teardown_errors)
22
22
  end
23
23
  rescue Exception => error
24
24
  raise if Smartest.fatal_exception?(error)
@@ -28,16 +28,16 @@ module Smartest
28
28
 
29
29
  @reporter.finish(
30
30
  results,
31
- suite_cleanup_errors: suite_cleanup_errors,
31
+ suite_teardown_errors: suite_teardown_errors,
32
32
  suite_errors: suite_errors
33
33
  )
34
34
 
35
- results.any?(&:failed?) || suite_cleanup_errors.any? || suite_errors.any? ? 1 : 0
35
+ results.any?(&:failed?) || suite_teardown_errors.any? || suite_errors.any? ? 1 : 0
36
36
  end
37
37
 
38
38
  private
39
39
 
40
- def run_tests(results, suite_cleanup_errors)
40
+ def run_tests(results, suite_teardown_errors)
41
41
  begin
42
42
  @tests.each do |test_case|
43
43
  result = run_one(test_case)
@@ -45,7 +45,7 @@ module Smartest
45
45
  @reporter.record(result)
46
46
  end
47
47
  ensure
48
- suite_cleanup_errors.concat(@suite_fixture_set.run_cleanups) if @suite_fixture_set
48
+ suite_teardown_errors.concat(@suite_fixture_set.run_teardowns) if @suite_fixture_set
49
49
  @suite_fixture_set = nil
50
50
  end
51
51
  end
@@ -68,13 +68,13 @@ module Smartest
68
68
  started_at = now
69
69
  error = nil
70
70
  skipped = nil
71
- cleanup_errors = []
71
+ teardown_errors = []
72
72
  run_state = TestRunState.new
73
73
  test_run = TestRun.new(
74
74
  fixture_classes: @suite.fixture_classes,
75
75
  matcher_modules: @suite.matcher_modules
76
76
  ) do |fixture_classes:, matcher_modules:, helper_modules:|
77
- run_test_body(test_case, fixture_classes, matcher_modules, helper_modules, run_state, cleanup_errors)
77
+ run_test_body(test_case, fixture_classes, matcher_modules, helper_modules, run_state, teardown_errors)
78
78
  end
79
79
 
80
80
  begin
@@ -89,12 +89,12 @@ module Smartest
89
89
 
90
90
  duration = now - started_at
91
91
 
92
- return TestResult.failed(test_case: test_case, error: nil, duration: duration, cleanup_errors: cleanup_errors) if skipped && cleanup_errors.any?
92
+ return TestResult.failed(test_case: test_case, error: nil, duration: duration, teardown_errors: teardown_errors) if skipped && teardown_errors.any?
93
93
  return TestResult.skipped(test_case: test_case, reason: skipped.reason, duration: duration) if skipped
94
94
 
95
95
  if run_state.pending?
96
96
  if error && !around_test_protocol_error?(error)
97
- return TestResult.failed(test_case: test_case, error: nil, duration: duration, cleanup_errors: cleanup_errors) if cleanup_errors.any?
97
+ return TestResult.failed(test_case: test_case, error: nil, duration: duration, teardown_errors: teardown_errors) if teardown_errors.any?
98
98
 
99
99
  return TestResult.pending(test_case: test_case, reason: run_state.pending_reason, duration: duration)
100
100
  end
@@ -102,19 +102,19 @@ module Smartest
102
102
  error ||= PendingPassedError.new(run_state.pending_reason)
103
103
  end
104
104
 
105
- if error || cleanup_errors.any?
105
+ if error || teardown_errors.any?
106
106
  TestResult.failed(
107
107
  test_case: test_case,
108
108
  error: error,
109
109
  duration: duration,
110
- cleanup_errors: cleanup_errors
110
+ teardown_errors: teardown_errors
111
111
  )
112
112
  else
113
113
  TestResult.passed(test_case: test_case, duration: duration)
114
114
  end
115
115
  end
116
116
 
117
- def run_test_body(test_case, fixture_classes, matcher_modules, helper_modules, run_state, cleanup_errors)
117
+ def run_test_body(test_case, fixture_classes, matcher_modules, helper_modules, run_state, teardown_errors)
118
118
  context = build_context(matcher_modules, run_state, helper_modules)
119
119
  fixture_set = nil
120
120
 
@@ -123,7 +123,7 @@ module Smartest
123
123
  fixtures = fixture_set.resolve_keywords(test_case.fixture_names)
124
124
  context.instance_exec(**fixtures, &test_case.block)
125
125
  ensure
126
- cleanup_errors.concat(fixture_set.run_cleanups) if fixture_set
126
+ teardown_errors.concat(fixture_set.run_teardowns) if fixture_set
127
127
  end
128
128
  end
129
129
 
@@ -2,59 +2,59 @@
2
2
 
3
3
  module Smartest
4
4
  class TestResult
5
- attr_reader :test_case, :status, :error, :duration, :cleanup_errors, :reason
5
+ attr_reader :test_case, :status, :error, :duration, :teardown_errors, :reason
6
6
 
7
- def self.passed(test_case:, duration:, cleanup_errors: [])
7
+ def self.passed(test_case:, duration:, teardown_errors: [])
8
8
  new(
9
9
  test_case: test_case,
10
10
  status: :passed,
11
11
  error: nil,
12
12
  reason: nil,
13
13
  duration: duration,
14
- cleanup_errors: cleanup_errors
14
+ teardown_errors: teardown_errors
15
15
  )
16
16
  end
17
17
 
18
- def self.failed(test_case:, error:, duration:, cleanup_errors: [])
18
+ def self.failed(test_case:, error:, duration:, teardown_errors: [])
19
19
  new(
20
20
  test_case: test_case,
21
21
  status: :failed,
22
22
  error: error,
23
23
  reason: nil,
24
24
  duration: duration,
25
- cleanup_errors: cleanup_errors
25
+ teardown_errors: teardown_errors
26
26
  )
27
27
  end
28
28
 
29
- def self.skipped(test_case:, reason:, duration:, cleanup_errors: [])
29
+ def self.skipped(test_case:, reason:, duration:, teardown_errors: [])
30
30
  new(
31
31
  test_case: test_case,
32
32
  status: :skipped,
33
33
  error: nil,
34
34
  reason: reason,
35
35
  duration: duration,
36
- cleanup_errors: cleanup_errors
36
+ teardown_errors: teardown_errors
37
37
  )
38
38
  end
39
39
 
40
- def self.pending(test_case:, reason:, duration:, cleanup_errors: [])
40
+ def self.pending(test_case:, reason:, duration:, teardown_errors: [])
41
41
  new(
42
42
  test_case: test_case,
43
43
  status: :pending,
44
44
  error: nil,
45
45
  reason: reason,
46
46
  duration: duration,
47
- cleanup_errors: cleanup_errors
47
+ teardown_errors: teardown_errors
48
48
  )
49
49
  end
50
50
 
51
- def initialize(test_case:, status:, error:, reason:, duration:, cleanup_errors:)
51
+ def initialize(test_case:, status:, error:, reason:, duration:, teardown_errors:)
52
52
  @test_case = test_case
53
53
  @status = status
54
54
  @error = error
55
55
  @reason = reason
56
56
  @duration = duration
57
- @cleanup_errors = cleanup_errors
57
+ @teardown_errors = teardown_errors
58
58
  end
59
59
 
60
60
  def passed?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Smartest
4
- VERSION = "0.4.0"
4
+ VERSION = "0.5.0"
5
5
  end
@@ -96,7 +96,7 @@ test("simple stub can be reset from a fresh stub object") do
96
96
  expect(SimpleStubSelfTestSubject.new("Alice").greeting("Hi")).to eq("Hi, Alice")
97
97
  end
98
98
 
99
- test("simple_stub_any_instance_of applies and resets from fixture cleanup") do
99
+ test("simple_stub_any_instance_of applies and resets from fixture teardown") do
100
100
  fixture_class = Class.new(Smartest::Fixture) do
101
101
  fixture :stubbed_name do
102
102
  simple_stub_any_instance_of(SimpleStubSelfTestSubject, :name) { "fixture #{@name}" }
@@ -127,7 +127,7 @@ test("simple_stub_any_instance_of applies and resets from fixture cleanup") do
127
127
  expect(status).to eq(0)
128
128
  end
129
129
 
130
- test("simple_stub applies and resets singleton methods from fixture cleanup") do
130
+ test("simple_stub applies and resets singleton methods from fixture teardown") do
131
131
  fixture_class = Class.new(Smartest::Fixture) do
132
132
  fixture :stubbed_time do
133
133
  simple_stub(SimpleStubSelfTestClock, :now) { :stubbed_now }
@@ -697,7 +697,7 @@ test("caches fixture values within one test") do
697
697
  expect(calls).to eq(1)
698
698
  end
699
699
 
700
- test("suite fixtures are created once and cleaned up after the suite") do
700
+ test("suite fixtures are created once and torn down after the suite") do
701
701
  events = []
702
702
  servers = []
703
703
 
@@ -705,7 +705,7 @@ test("suite fixtures are created once and cleaned up after the suite") do
705
705
  suite_fixture :server do
706
706
  events << :server_setup
707
707
  server = Object.new
708
- cleanup { events << :server_cleanup }
708
+ on_teardown { events << :server_teardown }
709
709
  server
710
710
  end
711
711
  end
@@ -718,7 +718,7 @@ test("suite fixtures are created once and cleaned up after the suite") do
718
718
  status, = SmartestSelfTest.run_suite(suite)
719
719
 
720
720
  expect(status).to eq(0)
721
- expect(events).to eq(%i[server_setup first second server_cleanup])
721
+ expect(events).to eq(%i[server_setup first second server_teardown])
722
722
  expect(servers.length).to eq(2)
723
723
  expect(servers[0].object_id).to eq(servers[1].object_id)
724
724
  end
@@ -773,14 +773,14 @@ test("suite fixtures cannot depend on test fixtures") do
773
773
  expect(output).to include("suite-scoped fixture server cannot depend on test-scoped fixture user")
774
774
  end
775
775
 
776
- test("suite fixture setup failures are cached and cleaned up once") do
776
+ test("suite fixture setup failures are cached and torn down once") do
777
777
  calls = 0
778
778
  events = []
779
779
 
780
780
  fixture_class = Class.new(Smartest::Fixture) do
781
781
  suite_fixture :server do
782
782
  calls += 1
783
- cleanup { events << :server_cleanup }
783
+ on_teardown { events << :server_teardown }
784
784
  raise "server setup failed"
785
785
  end
786
786
  end
@@ -794,17 +794,17 @@ test("suite fixture setup failures are cached and cleaned up once") do
794
794
 
795
795
  expect(status).to eq(1)
796
796
  expect(calls).to eq(1)
797
- expect(events).to eq([:server_cleanup])
797
+ expect(events).to eq([:server_teardown])
798
798
  expect(output.scan("RuntimeError: server setup failed").length).to eq(2)
799
799
  end
800
800
 
801
- test("around_suite wraps tests and suite fixture cleanup") do
801
+ test("around_suite wraps tests and suite fixture teardown") do
802
802
  events = []
803
803
 
804
804
  fixture_class = Class.new(Smartest::Fixture) do
805
805
  suite_fixture :server do
806
806
  events << :server_setup
807
- cleanup { events << :server_cleanup }
807
+ on_teardown { events << :server_teardown }
808
808
  :server
809
809
  end
810
810
  end
@@ -821,7 +821,7 @@ test("around_suite wraps tests and suite fixture cleanup") do
821
821
  status, = SmartestSelfTest.run_suite(suite)
822
822
 
823
823
  expect(status).to eq(0)
824
- expect(events).to eq(%i[around_before server_setup test server_cleanup around_after])
824
+ expect(events).to eq(%i[around_before server_setup test server_teardown around_after])
825
825
  end
826
826
 
827
827
  test("around_suite hooks run in registration order") do
@@ -886,13 +886,13 @@ test("around_suite can register suite-wide around_test hooks") do
886
886
  expect(events).to eq(%i[around_test_before test around_test_after])
887
887
  end
888
888
 
889
- test("around_test wraps fixture setup, test body, and cleanup") do
889
+ test("around_test wraps fixture setup, test body, and teardown") do
890
890
  events = []
891
891
 
892
892
  fixture_class = Class.new(Smartest::Fixture) do
893
893
  fixture :resource do
894
894
  events << :fixture_setup
895
- cleanup { events << :fixture_cleanup }
895
+ on_teardown { events << :fixture_teardown }
896
896
  :resource
897
897
  end
898
898
  end
@@ -918,7 +918,7 @@ test("around_test wraps fixture setup, test body, and cleanup") do
918
918
  status, = SmartestSelfTest.run_suite(suite)
919
919
 
920
920
  expect(status).to eq(0)
921
- expect(events).to eq(%i[around_test_before fixture_setup test fixture_cleanup around_test_after])
921
+ expect(events).to eq(%i[around_test_before fixture_setup test fixture_teardown around_test_after])
922
922
  end
923
923
 
924
924
  test("around_test can register fixtures for one test run") do
@@ -1232,10 +1232,10 @@ test("around_suite must call suite.run") do
1232
1232
  expect(output).to include("Smartest::AroundSuiteRunError: around_suite hook did not call suite.run")
1233
1233
  end
1234
1234
 
1235
- test("suite cleanup failures fail the run") do
1235
+ test("suite teardown failures fail the run") do
1236
1236
  fixture_class = Class.new(Smartest::Fixture) do
1237
1237
  suite_fixture :browser do
1238
- cleanup { raise "browser close failed" }
1238
+ on_teardown { raise "browser close failed" }
1239
1239
  :browser
1240
1240
  end
1241
1241
  end
@@ -1247,22 +1247,22 @@ test("suite cleanup failures fail the run") do
1247
1247
  status, output = SmartestSelfTest.run_suite(suite)
1248
1248
 
1249
1249
  expect(status).to eq(1)
1250
- expect(output).to include("Suite cleanup failures:")
1251
- expect(output).to include("cleanup failed: RuntimeError: browser close failed")
1252
- expect(output).to include("1 test, 1 passed, 0 failed, 1 suite cleanup failed")
1250
+ expect(output).to include("Suite teardown failures:")
1251
+ expect(output).to include("teardown failed: RuntimeError: browser close failed")
1252
+ expect(output).to include("1 test, 1 passed, 0 failed, 1 suite teardown failed")
1253
1253
  end
1254
1254
 
1255
- test("runs cleanup in reverse order after failures") do
1255
+ test("runs teardown in reverse order after failures") do
1256
1256
  events = []
1257
1257
 
1258
1258
  fixture_class = Class.new(Smartest::Fixture) do
1259
1259
  fixture :server do
1260
- cleanup { events << :server }
1260
+ on_teardown { events << :server }
1261
1261
  :server
1262
1262
  end
1263
1263
 
1264
1264
  fixture :browser do |server:|
1265
- cleanup { events << :browser }
1265
+ on_teardown { events << :browser }
1266
1266
  server
1267
1267
  end
1268
1268
  end
@@ -1277,12 +1277,12 @@ test("runs cleanup in reverse order after failures") do
1277
1277
  expect(events).to eq(%i[browser server])
1278
1278
  end
1279
1279
 
1280
- test("runs cleanup when fixture setup fails after cleanup registration") do
1280
+ test("runs teardown when fixture setup fails after teardown registration") do
1281
1281
  events = []
1282
1282
 
1283
1283
  fixture_class = Class.new(Smartest::Fixture) do
1284
1284
  fixture :server do
1285
- cleanup { events << :server }
1285
+ on_teardown { events << :server }
1286
1286
  raise "server setup failed"
1287
1287
  end
1288
1288
  end
@@ -1298,6 +1298,25 @@ test("runs cleanup when fixture setup fails after cleanup registration") do
1298
1298
  expect(output).to include("RuntimeError: server setup failed")
1299
1299
  end
1300
1300
 
1301
+ test("does not keep cleanup as a fixture teardown alias") do
1302
+ fixture_class = Class.new(Smartest::Fixture) do
1303
+ fixture :server do
1304
+ cleanup { :server }
1305
+ :server
1306
+ end
1307
+ end
1308
+
1309
+ suite = Smartest::Suite.new
1310
+ suite.fixture_classes.add(fixture_class)
1311
+ suite.tests.add(SmartestSelfTest.test_case("needs server", proc { |server:| expect(server).to eq(:server) }))
1312
+
1313
+ status, output = SmartestSelfTest.run_suite(suite)
1314
+
1315
+ expect(status).to eq(1)
1316
+ expect(output).to include("NoMethodError")
1317
+ expect(output).to include("cleanup")
1318
+ end
1319
+
1301
1320
  test("duplicate fixture names fail the test") do
1302
1321
  first_fixture = Class.new(Smartest::Fixture) do
1303
1322
  fixture(:user) { "Alice" }
data/smartest.gemspec CHANGED
@@ -7,8 +7,15 @@ Gem::Specification.new do |spec|
7
7
  spec.version = Smartest::VERSION
8
8
  spec.authors = ["Yusuke Iwaki"]
9
9
 
10
- spec.summary = "Pytest-style fixtures for Ruby."
11
- spec.description = "Smartest is a Ruby test runner with pytest-style fixture injection. Tests request fixtures using keyword arguments, fixtures can depend on other fixtures, and cleanup is registered only when needed."
10
+ spec.summary = "A Ruby test runner with pytest-style fixtures and Playwright-friendly browser testing."
11
+ spec.description = <<~TEXT
12
+ Smartest is a Ruby test runner that brings pytest-style fixture injection
13
+ to Ruby. Tests declare dependencies with keyword arguments, fixtures can
14
+ depend on other fixtures, and teardown is handled explicitly when needed.
15
+
16
+ Smartest is designed for readable Ruby tests, Rails system tests, and
17
+ Playwright-powered browser testing.
18
+ TEXT
12
19
  spec.homepage = "https://smartest-rb.vercel.app"
13
20
  spec.license = "MIT"
14
21
  spec.required_ruby_version = ">= 2.7"
@@ -17,7 +24,7 @@ Gem::Specification.new do |spec|
17
24
  "allowed_push_host" => "https://rubygems.org",
18
25
  "bug_tracker_uri" => "https://github.com/YusukeIwaki/smartest/issues",
19
26
  "changelog_uri" => "https://github.com/YusukeIwaki/smartest/blob/main/CHANGELOG.md",
20
- "documentation_uri" => "https://smartest-rb.vercel.app/docs/fixtures",
27
+ "documentation_uri" => "https://smartest-rb.vercel.app/docs",
21
28
  "homepage_uri" => spec.homepage,
22
29
  "rubygems_mfa_required" => "true",
23
30
  "source_code_uri" => "https://github.com/YusukeIwaki/smartest"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smartest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yusuke Iwaki
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2026-05-06 00:00:00.000000000 Z
11
+ date: 2026-05-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -24,9 +24,13 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '13.0'
27
- description: Smartest is a Ruby test runner with pytest-style fixture injection. Tests
28
- request fixtures using keyword arguments, fixtures can depend on other fixtures,
29
- and cleanup is registered only when needed.
27
+ description: |
28
+ Smartest is a Ruby test runner that brings pytest-style fixture injection
29
+ to Ruby. Tests declare dependencies with keyword arguments, fixtures can
30
+ depend on other fixtures, and teardown is handled explicitly when needed.
31
+
32
+ Smartest is designed for readable Ruby tests, Rails system tests, and
33
+ Playwright-powered browser testing.
30
34
  email:
31
35
  executables:
32
36
  - smartest
@@ -82,7 +86,7 @@ metadata:
82
86
  allowed_push_host: https://rubygems.org
83
87
  bug_tracker_uri: https://github.com/YusukeIwaki/smartest/issues
84
88
  changelog_uri: https://github.com/YusukeIwaki/smartest/blob/main/CHANGELOG.md
85
- documentation_uri: https://smartest-rb.vercel.app/docs/fixtures
89
+ documentation_uri: https://smartest-rb.vercel.app/docs
86
90
  homepage_uri: https://smartest-rb.vercel.app
87
91
  rubygems_mfa_required: 'true'
88
92
  source_code_uri: https://github.com/YusukeIwaki/smartest
@@ -104,5 +108,6 @@ requirements: []
104
108
  rubygems_version: 3.4.19
105
109
  signing_key:
106
110
  specification_version: 4
107
- summary: Pytest-style fixtures for Ruby.
111
+ summary: A Ruby test runner with pytest-style fixtures and Playwright-friendly browser
112
+ testing.
108
113
  test_files: []