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.
@@ -48,7 +48,10 @@ class SelfTestRegisteredFixture < Smartest::Fixture
48
48
  end
49
49
  end
50
50
 
51
- use_fixture SelfTestRegisteredFixture
51
+ around_suite do |suite|
52
+ use_fixture SelfTestRegisteredFixture
53
+ suite.run
54
+ end
52
55
 
53
56
  test("registers fixture classes with use_fixture") do |registered_user_name:|
54
57
  expect(registered_user_name).to eq("Alice")
@@ -76,6 +79,92 @@ test("reports expectation failures") do
76
79
  expect(output).to include("1 test, 0 passed, 1 failed")
77
80
  end
78
81
 
82
+ test("skip marks a test as skipped and stops the body") do
83
+ events = []
84
+ suite = Smartest::Suite.new
85
+ suite.tests.add(
86
+ SmartestSelfTest.test_case(
87
+ "unsupported export",
88
+ proc do
89
+ events << :before_skip
90
+ skip "firefox is not supported"
91
+ events << :after_skip
92
+ end
93
+ )
94
+ )
95
+
96
+ status, output = SmartestSelfTest.run_suite(suite)
97
+
98
+ expect(status).to eq(0)
99
+ expect(events).to eq([:before_skip])
100
+ expect(output).to include("- unsupported export (skipped: firefox is not supported)")
101
+ expect(output).to include("1 test, 0 passed, 0 failed, 1 skipped")
102
+ expect(output).not_to include("Failures:")
103
+ end
104
+
105
+ test("pending marks a failing test as pending") do
106
+ events = []
107
+ suite = Smartest::Suite.new
108
+ suite.tests.add(
109
+ SmartestSelfTest.test_case(
110
+ "bidi export",
111
+ proc do
112
+ pending "Not supported by WebDriver BiDi yet"
113
+ events << :after_pending
114
+ expect("actual").to eq("expected")
115
+ events << :after_failure
116
+ end
117
+ )
118
+ )
119
+
120
+ status, output = SmartestSelfTest.run_suite(suite)
121
+
122
+ expect(status).to eq(0)
123
+ expect(events).to eq([:after_pending])
124
+ expect(output).to include("* bidi export (pending: Not supported by WebDriver BiDi yet)")
125
+ expect(output).to include("1 test, 0 passed, 0 failed, 1 pending")
126
+ expect(output).not_to include("Failures:")
127
+ end
128
+
129
+ test("pending fails when the test passes") do
130
+ suite = Smartest::Suite.new
131
+ suite.tests.add(
132
+ SmartestSelfTest.test_case(
133
+ "fixed bidi export",
134
+ proc do
135
+ pending "Not supported by WebDriver BiDi yet"
136
+ expect("actual").to eq("actual")
137
+ end
138
+ )
139
+ )
140
+
141
+ status, output = SmartestSelfTest.run_suite(suite)
142
+
143
+ expect(status).to eq(1)
144
+ expect(output).to include("expected pending test to fail, but it passed: Not supported by WebDriver BiDi yet")
145
+ expect(output).to include("1 test, 0 passed, 1 failed")
146
+ end
147
+
148
+ test("skip and pending are not available inside fixtures") do
149
+ %i[skip pending].each do |method_name|
150
+ fixture_class = Class.new(Smartest::Fixture) do
151
+ fixture :value do
152
+ __send__(method_name, "reason")
153
+ end
154
+ end
155
+
156
+ suite = Smartest::Suite.new
157
+ suite.fixture_classes.add(fixture_class)
158
+ suite.tests.add(SmartestSelfTest.test_case("#{method_name} fixture", proc { |value:| expect(value).to eq(:value) }))
159
+
160
+ status, output = SmartestSelfTest.run_suite(suite)
161
+
162
+ expect(status).to eq(1)
163
+ expect(output).to include("NoMethodError")
164
+ expect(output).to include(method_name.to_s)
165
+ end
166
+ end
167
+
79
168
  test("supports basic matchers") do
80
169
  suite = Smartest::Suite.new
81
170
  suite.tests.add(
@@ -326,6 +415,373 @@ test("suite fixture setup failures are cached and cleaned up once") do
326
415
  expect(output.scan("RuntimeError: server setup failed").length).to eq(2)
327
416
  end
328
417
 
418
+ test("around_suite wraps tests and suite fixture cleanup") do
419
+ events = []
420
+
421
+ fixture_class = Class.new(Smartest::Fixture) do
422
+ suite_fixture :server do
423
+ events << :server_setup
424
+ cleanup { events << :server_cleanup }
425
+ :server
426
+ end
427
+ end
428
+
429
+ suite = Smartest::Suite.new
430
+ suite.fixture_classes.add(fixture_class)
431
+ suite.around_suite_hooks << proc do |suite_run|
432
+ events << :around_before
433
+ suite_run.run
434
+ events << :around_after
435
+ end
436
+ suite.tests.add(SmartestSelfTest.test_case("uses server", proc { |server:| events << :test; expect(server).to eq(:server) }))
437
+
438
+ status, = SmartestSelfTest.run_suite(suite)
439
+
440
+ expect(status).to eq(0)
441
+ expect(events).to eq(%i[around_before server_setup test server_cleanup around_after])
442
+ end
443
+
444
+ test("around_suite hooks run in registration order") do
445
+ events = []
446
+ suite = Smartest::Suite.new
447
+
448
+ suite.around_suite_hooks << proc do |suite_run|
449
+ events << :outer_before
450
+ suite_run.run
451
+ events << :outer_after
452
+ end
453
+ suite.around_suite_hooks << proc do |suite_run|
454
+ events << :inner_before
455
+ suite_run.run
456
+ events << :inner_after
457
+ end
458
+ suite.tests.add(SmartestSelfTest.test_case("passes", proc { events << :test }))
459
+
460
+ status, = SmartestSelfTest.run_suite(suite)
461
+
462
+ expect(status).to eq(0)
463
+ expect(events).to eq(%i[outer_before inner_before test inner_after outer_after])
464
+ end
465
+
466
+ test("around_suite can register fixtures before running tests") do
467
+ fixture_class = Class.new(Smartest::Fixture) do
468
+ fixture :user_name do
469
+ "Alice"
470
+ end
471
+ end
472
+
473
+ suite = Smartest::Suite.new
474
+ suite.around_suite_hooks << proc do |suite_run|
475
+ use_fixture fixture_class
476
+ suite_run.run
477
+ end
478
+ suite.tests.add(SmartestSelfTest.test_case("uses runtime fixture", proc { |user_name:| expect(user_name).to eq("Alice") }))
479
+
480
+ status, = SmartestSelfTest.run_suite(suite)
481
+
482
+ expect(status).to eq(0)
483
+ end
484
+
485
+ test("around_suite can register suite-wide around_test hooks") do
486
+ events = []
487
+ suite = Smartest::Suite.new
488
+
489
+ suite.around_suite_hooks << proc do |suite_run|
490
+ around_test do |test_run|
491
+ events << :around_test_before
492
+ test_run.run
493
+ events << :around_test_after
494
+ end
495
+
496
+ suite_run.run
497
+ end
498
+ suite.tests.add(SmartestSelfTest.test_case("passes", proc { events << :test }))
499
+
500
+ status, = SmartestSelfTest.run_suite(suite)
501
+
502
+ expect(status).to eq(0)
503
+ expect(events).to eq(%i[around_test_before test around_test_after])
504
+ end
505
+
506
+ test("around_test wraps fixture setup, test body, and cleanup") do
507
+ events = []
508
+
509
+ fixture_class = Class.new(Smartest::Fixture) do
510
+ fixture :resource do
511
+ events << :fixture_setup
512
+ cleanup { events << :fixture_cleanup }
513
+ :resource
514
+ end
515
+ end
516
+
517
+ suite = Smartest::Suite.new
518
+ suite.fixture_classes.add(fixture_class)
519
+ suite.tests.add(
520
+ Smartest::TestCase.new(
521
+ name: "uses resource",
522
+ metadata: {},
523
+ location: caller_locations(1, 1).first,
524
+ around_test_hooks: [
525
+ proc do |test_run|
526
+ events << :around_test_before
527
+ test_run.run
528
+ events << :around_test_after
529
+ end
530
+ ],
531
+ block: proc { |resource:| events << :test; expect(resource).to eq(:resource) }
532
+ )
533
+ )
534
+
535
+ status, = SmartestSelfTest.run_suite(suite)
536
+
537
+ expect(status).to eq(0)
538
+ expect(events).to eq(%i[around_test_before fixture_setup test fixture_cleanup around_test_after])
539
+ end
540
+
541
+ test("around_test can register fixtures for one test run") do
542
+ fixture_class = Class.new(Smartest::Fixture) do
543
+ fixture :local_value do
544
+ "local"
545
+ end
546
+ end
547
+
548
+ suite = Smartest::Suite.new
549
+ suite.tests.add(
550
+ Smartest::TestCase.new(
551
+ name: "uses local fixture",
552
+ metadata: {},
553
+ location: caller_locations(1, 1).first,
554
+ around_test_hooks: [
555
+ proc do |test_run|
556
+ use_fixture fixture_class
557
+ test_run.run
558
+ end
559
+ ],
560
+ block: proc { |local_value:| expect(local_value).to eq("local") }
561
+ )
562
+ )
563
+
564
+ status, = SmartestSelfTest.run_suite(suite)
565
+
566
+ expect(status).to eq(0)
567
+ end
568
+
569
+ test("around_test rejects fixture classes with suite fixtures") do
570
+ fixture_class = Class.new(Smartest::Fixture) do
571
+ suite_fixture :server do
572
+ :server
573
+ end
574
+ end
575
+
576
+ suite = Smartest::Suite.new
577
+ suite.tests.add(
578
+ Smartest::TestCase.new(
579
+ name: "rejects local suite fixture",
580
+ metadata: {},
581
+ location: caller_locations(1, 1).first,
582
+ around_test_hooks: [
583
+ proc do |test_run|
584
+ use_fixture fixture_class
585
+ test_run.run
586
+ end
587
+ ],
588
+ block: proc { |server:| expect(server).to eq(:server) }
589
+ )
590
+ )
591
+
592
+ status, output = SmartestSelfTest.run_suite(suite)
593
+
594
+ expect(status).to eq(1)
595
+ expect(output).to include("Smartest::AroundTestFixtureScopeError")
596
+ expect(output).to include("cannot be registered from around_test")
597
+ expect(output).to include("suite-scoped fixtures: :server")
598
+ expect(output).to include("Register fixture classes with suite_fixture from around_suite instead.")
599
+ end
600
+
601
+ test("around_test can register matchers for one test run") do
602
+ matcher_module = Module.new do
603
+ define_method(:equal_local) do |expected|
604
+ Class.new do
605
+ define_method(:initialize) { |value| @expected = value }
606
+ define_method(:matches?) { |actual| actual == @expected }
607
+ define_method(:failure_message) { "expected value to match" }
608
+ define_method(:negated_failure_message) { "expected value not to match" }
609
+ end.new(expected)
610
+ end
611
+ end
612
+
613
+ suite = Smartest::Suite.new
614
+ suite.tests.add(
615
+ Smartest::TestCase.new(
616
+ name: "uses local matcher",
617
+ metadata: {},
618
+ location: caller_locations(1, 1).first,
619
+ around_test_hooks: [
620
+ proc do |test_run|
621
+ use_matcher matcher_module
622
+ test_run.run
623
+ end
624
+ ],
625
+ block: proc { expect("local").to equal_local("local") }
626
+ )
627
+ )
628
+
629
+ status, = SmartestSelfTest.run_suite(suite)
630
+
631
+ expect(status).to eq(0)
632
+ end
633
+
634
+ test("around_test must call test.run") do
635
+ suite = Smartest::Suite.new
636
+ suite.tests.add(
637
+ Smartest::TestCase.new(
638
+ name: "not reached",
639
+ metadata: {},
640
+ location: caller_locations(1, 1).first,
641
+ around_test_hooks: [proc { |_test_run| nil }],
642
+ block: proc { expect(true).to eq(false) }
643
+ )
644
+ )
645
+
646
+ status, output = SmartestSelfTest.run_suite(suite)
647
+
648
+ expect(status).to eq(1)
649
+ expect(output).to include("Smartest::AroundTestRunError: around_test hook did not call test.run")
650
+ end
651
+
652
+ test("around_test can skip before test.run") do
653
+ events = []
654
+ suite = Smartest::Suite.new
655
+ suite.tests.add(
656
+ Smartest::TestCase.new(
657
+ name: "skipped by hook",
658
+ metadata: {},
659
+ location: caller_locations(1, 1).first,
660
+ around_test_hooks: [
661
+ proc do |test_run|
662
+ events << :around_before
663
+ skip "browser is not supported"
664
+ test_run.run
665
+ events << :around_after
666
+ end
667
+ ],
668
+ block: proc { events << :test_body }
669
+ )
670
+ )
671
+
672
+ status, output = SmartestSelfTest.run_suite(suite)
673
+
674
+ expect(status).to eq(0)
675
+ expect(events).to eq([:around_before])
676
+ expect(output).to include("- skipped by hook (skipped: browser is not supported)")
677
+ expect(output).to include("1 test, 0 passed, 0 failed, 1 skipped")
678
+ end
679
+
680
+ test("around_test can mark a failing test as pending") do
681
+ suite = Smartest::Suite.new
682
+ suite.tests.add(
683
+ Smartest::TestCase.new(
684
+ name: "pending by hook",
685
+ metadata: {},
686
+ location: caller_locations(1, 1).first,
687
+ around_test_hooks: [
688
+ proc do |test_run|
689
+ pending "driver bug"
690
+ test_run.run
691
+ end
692
+ ],
693
+ block: proc { expect("actual").to eq("expected") }
694
+ )
695
+ )
696
+
697
+ status, output = SmartestSelfTest.run_suite(suite)
698
+
699
+ expect(status).to eq(0)
700
+ expect(output).to include("* pending by hook (pending: driver bug)")
701
+ expect(output).to include("1 test, 0 passed, 0 failed, 1 pending")
702
+ end
703
+
704
+ test("pending around_test hooks must still call test.run") do
705
+ suite = Smartest::Suite.new
706
+ suite.tests.add(
707
+ Smartest::TestCase.new(
708
+ name: "pending hook missing run",
709
+ metadata: {},
710
+ location: caller_locations(1, 1).first,
711
+ around_test_hooks: [
712
+ proc do |_test_run|
713
+ pending "driver bug"
714
+ end
715
+ ],
716
+ block: proc { expect(true).to eq(false) }
717
+ )
718
+ )
719
+
720
+ status, output = SmartestSelfTest.run_suite(suite)
721
+
722
+ expect(status).to eq(1)
723
+ expect(output).to include("Smartest::AroundTestRunError: around_test hook did not call test.run")
724
+ expect(output).to include("1 test, 0 passed, 1 failed")
725
+ end
726
+
727
+ test("use_fixture and use_matcher are only available inside hooks") do
728
+ {
729
+ "use_fixture Object" => "use_fixture",
730
+ "use_matcher Module.new" => "use_matcher"
731
+ }.each do |registration, method_name|
732
+ Dir.mktmpdir do |dir|
733
+ smartest_dir = File.join(dir, "smartest")
734
+ FileUtils.mkdir_p(smartest_dir)
735
+ File.write(File.join(smartest_dir, "sample_test.rb"), <<~RUBY)
736
+ require "smartest/autorun"
737
+
738
+ #{registration}
739
+
740
+ test("not reached") do
741
+ expect(true).to eq(true)
742
+ end
743
+ RUBY
744
+
745
+ _stdout, stderr, status = Open3.capture3(
746
+ { "RUBYLIB" => File.expand_path("../lib", __dir__) },
747
+ "ruby",
748
+ File.expand_path("../exe/smartest", __dir__),
749
+ "smartest/sample_test.rb",
750
+ chdir: dir
751
+ )
752
+
753
+ expect(status.success?).to eq(false)
754
+ expect(stderr).to include("Error loading tests:")
755
+ expect(stderr).to include("NoMethodError")
756
+ expect(stderr).to include(method_name)
757
+ end
758
+ end
759
+ end
760
+
761
+ test("around_suite failures fail the run") do
762
+ suite = Smartest::Suite.new
763
+ suite.around_suite_hooks << proc { |_suite_run| raise "suite wrapper failed" }
764
+ suite.tests.add(SmartestSelfTest.test_case("not reached", proc { expect(true).to eq(false) }))
765
+
766
+ status, output = SmartestSelfTest.run_suite(suite)
767
+
768
+ expect(status).to eq(1)
769
+ expect(output).to include("Suite failures:")
770
+ expect(output).to include("RuntimeError: suite wrapper failed")
771
+ expect(output).to include("0 tests, 0 passed, 0 failed, 1 suite failure")
772
+ end
773
+
774
+ test("around_suite must call suite.run") do
775
+ suite = Smartest::Suite.new
776
+ suite.around_suite_hooks << proc { |_suite_run| nil }
777
+ suite.tests.add(SmartestSelfTest.test_case("not reached", proc { expect(true).to eq(false) }))
778
+
779
+ status, output = SmartestSelfTest.run_suite(suite)
780
+
781
+ expect(status).to eq(1)
782
+ expect(output).to include("Smartest::AroundSuiteRunError: around_suite hook did not call suite.run")
783
+ end
784
+
329
785
  test("suite cleanup failures fail the run") do
330
786
  fixture_class = Class.new(Smartest::Fixture) do
331
787
  suite_fixture :browser do
@@ -541,7 +997,10 @@ test("cli loads matcher files registered in test helper") do
541
997
  require matcher_file
542
998
  end
543
999
 
544
- use_matcher HaveStatusMatcher
1000
+ around_suite do |suite|
1001
+ use_matcher HaveStatusMatcher
1002
+ suite.run
1003
+ end
545
1004
  RUBY
546
1005
  File.write(File.join(matchers_dir, "have_status_matcher.rb"), <<~RUBY)
547
1006
  module HaveStatusMatcher
@@ -771,6 +1230,7 @@ test("cli initializes a runnable test scaffold") do
771
1230
  expect(helper_contents).to include('require "smartest/autorun"')
772
1231
  expect(helper_contents).to include('Dir[File.join(__dir__, "fixtures", "**", "*.rb")].sort.each')
773
1232
  expect(helper_contents).to include('Dir[File.join(__dir__, "matchers", "**", "*.rb")].sort.each')
1233
+ expect(helper_contents).to include("around_suite do |suite|")
774
1234
  expect(helper_contents).to include("use_matcher PredicateMatcher")
775
1235
  predicate_matcher_contents = File.read(File.join(dir, "smartest/matchers/predicate_matcher.rb"))
776
1236
  expect(predicate_matcher_contents).to include("module PredicateMatcher")
@@ -789,7 +1249,10 @@ test("cli initializes a runnable test scaffold") do
789
1249
  File.write(File.join(dir, "smartest/auto_loaded_fixture_test.rb"), <<~RUBY)
790
1250
  require "test_helper"
791
1251
 
792
- use_fixture AutoLoadedFixture
1252
+ around_test do |test|
1253
+ use_fixture AutoLoadedFixture
1254
+ test.run
1255
+ end
793
1256
 
794
1257
  test("auto-loaded fixture") do |auto_loaded_message:|
795
1258
  expect(auto_loaded_message).to eq("loaded from smartest/fixtures")
@@ -828,7 +1291,10 @@ test("cli initializes a runnable test scaffold") do
828
1291
  File.write(File.join(dir, "smartest/auto_loaded_matcher_test.rb"), <<~RUBY)
829
1292
  require "test_helper"
830
1293
 
831
- use_matcher AutoLoadedMatcher
1294
+ around_test do |test|
1295
+ use_matcher AutoLoadedMatcher
1296
+ test.run
1297
+ end
832
1298
 
833
1299
  test("auto-loaded matcher") do
834
1300
  expect("loaded from smartest/matchers").to auto_eq("loaded from smartest/matchers")
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smartest
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0.alpha2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yusuke Iwaki
@@ -52,6 +52,7 @@ files:
52
52
  - lib/smartest/fixture_class_registry.rb
53
53
  - lib/smartest/fixture_definition.rb
54
54
  - lib/smartest/fixture_set.rb
55
+ - lib/smartest/hook_contexts.rb
55
56
  - lib/smartest/init_generator.rb
56
57
  - lib/smartest/matcher_registry.rb
57
58
  - lib/smartest/matchers.rb
@@ -59,9 +60,12 @@ files:
59
60
  - lib/smartest/reporter.rb
60
61
  - lib/smartest/runner.rb
61
62
  - lib/smartest/suite.rb
63
+ - lib/smartest/suite_run.rb
62
64
  - lib/smartest/test_case.rb
63
65
  - lib/smartest/test_registry.rb
64
66
  - lib/smartest/test_result.rb
67
+ - lib/smartest/test_run.rb
68
+ - lib/smartest/test_run_state.rb
65
69
  - lib/smartest/version.rb
66
70
  - smartest.gemspec
67
71
  - smartest/smartest_test.rb
@@ -86,9 +90,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
86
90
  version: '3.1'
87
91
  required_rubygems_version: !ruby/object:Gem::Requirement
88
92
  requirements:
89
- - - ">="
93
+ - - ">"
90
94
  - !ruby/object:Gem::Version
91
- version: '0'
95
+ version: 1.3.1
92
96
  requirements: []
93
97
  rubygems_version: 3.4.19
94
98
  signing_key: