test-unit 3.4.4 → 3.4.8

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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -3
  3. data/Rakefile +0 -9
  4. data/doc/text/getting-started.md +1 -1
  5. data/doc/text/news.md +54 -1
  6. data/lib/test/unit/assertion-failed-error.rb +35 -0
  7. data/lib/test/unit/assertions.rb +93 -17
  8. data/lib/test/unit/autorunner.rb +13 -1
  9. data/lib/test/unit/collector/descendant.rb +1 -0
  10. data/lib/test/unit/collector/dir.rb +4 -2
  11. data/lib/test/unit/collector/load.rb +2 -0
  12. data/lib/test/unit/collector/objectspace.rb +1 -0
  13. data/lib/test/unit/collector.rb +31 -0
  14. data/lib/test/unit/testcase.rb +34 -1
  15. data/lib/test/unit/testsuite.rb +1 -1
  16. data/lib/test/unit/util/memory-usage.rb +47 -0
  17. data/lib/test/unit/version.rb +1 -1
  18. data/lib/test/unit.rb +4 -4
  19. metadata +6 -83
  20. data/test/collector/test-descendant.rb +0 -182
  21. data/test/collector/test-load.rb +0 -475
  22. data/test/collector/test_dir.rb +0 -407
  23. data/test/collector/test_objectspace.rb +0 -102
  24. data/test/fixtures/header-label.csv +0 -3
  25. data/test/fixtures/header-label.tsv +0 -3
  26. data/test/fixtures/header.csv +0 -3
  27. data/test/fixtures/header.tsv +0 -3
  28. data/test/fixtures/no-header.csv +0 -2
  29. data/test/fixtures/no-header.tsv +0 -2
  30. data/test/fixtures/plus.csv +0 -3
  31. data/test/run-test.rb +0 -22
  32. data/test/test-assertions.rb +0 -2281
  33. data/test/test-attribute-matcher.rb +0 -38
  34. data/test/test-attribute.rb +0 -123
  35. data/test/test-code-snippet.rb +0 -79
  36. data/test/test-color-scheme.rb +0 -123
  37. data/test/test-color.rb +0 -47
  38. data/test/test-data.rb +0 -419
  39. data/test/test-diff.rb +0 -518
  40. data/test/test-emacs-runner.rb +0 -60
  41. data/test/test-error.rb +0 -26
  42. data/test/test-failure.rb +0 -33
  43. data/test/test-fault-location-detector.rb +0 -163
  44. data/test/test-fixture.rb +0 -713
  45. data/test/test-notification.rb +0 -33
  46. data/test/test-omission.rb +0 -81
  47. data/test/test-pending.rb +0 -70
  48. data/test/test-priority.rb +0 -184
  49. data/test/test-test-case.rb +0 -1284
  50. data/test/test-test-result.rb +0 -113
  51. data/test/test-test-suite-creator.rb +0 -97
  52. data/test/test-test-suite.rb +0 -151
  53. data/test/testunit-test-util.rb +0 -33
  54. data/test/ui/test_testrunmediator.rb +0 -20
  55. data/test/util/test-method-owner-finder.rb +0 -38
  56. data/test/util/test-output.rb +0 -11
  57. data/test/util/test_backtracefilter.rb +0 -52
  58. data/test/util/test_observable.rb +0 -102
  59. data/test/util/test_procwrapper.rb +0 -36
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4bf06d094c228d2826f3ffd368b7587dad9844cb59429790157c1d00f963e527
4
- data.tar.gz: d5d07e063a929674b11047dee03b185fdf73f926e48aa8830f2f2fa7d4c88b58
3
+ metadata.gz: 6f71beead19a58b6dd15eadbce6ba5f773a25dc5e8a69cdfc5e0b227fe60bfef
4
+ data.tar.gz: c845b3d680a4f8d4d835bbfa3c3d86fdc5b1aa2faa21b9f6ebcb5635628a7e47
5
5
  SHA512:
6
- metadata.gz: 63d7fa4261919b37f31bd412335cc086778622f4ff63e6f645baf7c8440493e3dc2be0206bff51f5a24bb0f5f90122a61db5cbe31b2499360045092069164605
7
- data.tar.gz: 50238b29eda4de9e4ece1c64fe3cd9a583ceeb7cb965c4e6660d39017ded8a27579723dfe206f434ff0bbd71dba9085e4af987d83d6bf76cf3ef16a475f31e4b
6
+ metadata.gz: 52534de6505e9b791d185d52ac4f8cfba7799c3f937f1fabe9a2419cb43cfae0fef1224727e25f8cb1a69fcef220c49a5a42b57c2b580dee7438d0c8ec64e390
7
+ data.tar.gz: 233aca4112351087c13b900cf64261d5d730fa16fe2b7ab9c14a8be81a43e1032849e3fcc90f1589528738879ccb9fa5d117b5328345967e0b17693d55105afc
data/README.md CHANGED
@@ -1,7 +1,8 @@
1
1
  # test-unit
2
2
 
3
- [![](https://badge.fury.io/rb/test-unit.svg)](http://badge.fury.io/rb/test-unit)
4
- [![](https://travis-ci.org/test-unit/test-unit.svg?branch=master)](https://travis-ci.org/test-unit/test-unit)
3
+ [![Gem Version](https://badge.fury.io/rb/test-unit.png)](http://badge.fury.io/rb/test-unit)
4
+ [![Build Status for Ruby 2.1+](https://github.com/test-unit/test-unit/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/test-unit/test-unit/actions/workflows/test.yml?query=branch%3Amaster+)
5
+ [![Build Status for Ruby 1.9 and 2.0](https://travis-ci.com/test-unit/test-unit.svg?branch=master)](https://travis-ci.com/test-unit/test-unit)
5
6
 
6
7
  * http://test-unit.github.io/
7
8
  * https://github.com/test-unit/test-unit
@@ -24,7 +25,7 @@ writing tests, checking results and automated testing in Ruby.
24
25
  to radically change very soon).
25
26
 
26
27
  * test-unit will be improved actively and may break
27
- compatiblity with test-unit 1.2.3. (We will not hope it
28
+ compatibility with test-unit 1.2.3. (We will not hope it
28
29
  if it isn't needed.)
29
30
 
30
31
  * Some features exist as separated gems like GUI test
data/Rakefile CHANGED
@@ -24,7 +24,6 @@ require "packnga"
24
24
  task :default => :test
25
25
 
26
26
  base_dir = File.dirname(__FILE__)
27
- html_base_dir = File.join(base_dir, "doc", "html")
28
27
 
29
28
  helper = Bundler::GemHelper.new(base_dir)
30
29
  def helper.version_tag
@@ -53,14 +52,6 @@ def rake(*arguments)
53
52
  ruby($0, *arguments)
54
53
  end
55
54
 
56
- namespace :html do
57
- desc "Publish HTML to Web site."
58
- task :publish do
59
- # FIXME Do nothing for now
60
- #rsync_to_rubyforge(spec, "#{html_base_dir}/", "")
61
- end
62
- end
63
-
64
55
  task :test do
65
56
  ruby("test/run-test.rb")
66
57
  end
@@ -239,7 +239,7 @@ module Sub
239
239
  end
240
240
  ~~~
241
241
 
242
- ## 7. For more inforomation
242
+ ## 7. For more information
243
243
 
244
244
  Let's read the official document.
245
245
 
data/doc/text/news.md CHANGED
@@ -1,10 +1,63 @@
1
1
  # News
2
2
 
3
+ ## 3.4.8 - 2021-10-11 {#version-3-4-8}
4
+
5
+ ### Improvements
6
+
7
+ * Added support for omitting Ractor tests on Ruby 2.7 or earlier
8
+ automatically.
9
+
10
+ ## 3.4.7 - 2021-09-14 {#version-3-4-7}
11
+
12
+ ### Fixes
13
+
14
+ * Suppressed a warning on Ruby 2.
15
+ [GitHub#205][Patch by Kenichi Kamiya]
16
+
17
+ ### Thanks
18
+
19
+ * Kenichi Kamiya
20
+
21
+ ## 3.4.6 - 2021-09-11 {#version-3-4-6}
22
+
23
+ ### Improvements
24
+
25
+ * Added support for tests that use Ractor. Use
26
+ `Test::Unit::TestCase.ractor` to declare that these tests use
27
+ Ractor.
28
+
29
+ * Added `--debug-on-failure` option.
30
+
31
+ ## 3.4.5 - 2021-09-04 {#version-3-4-5}
32
+
33
+ ### Improvements
34
+
35
+ * Added more metadata to gemspec.
36
+ [GitHub#183][Patch by Kenichi Kamiya]
37
+
38
+ * Removed needless files from gem.
39
+ [GitHub#184][Patch by Kenichi Kamiya]
40
+
41
+ * Updated documents.
42
+ [GitHub#191][GitHub#192][GitHub#193][GitHub#199][GitHub#200]
43
+ [GitHub#201][Patch by Kenichi Kamiya]
44
+
45
+ * Added `assert_nothing_leaked_memory`.
46
+
47
+ ### Fixes
48
+
49
+ * Fixed typos in documents.
50
+ [GitHub#189][GitHub#190][GitHub#195][GitHub#197][Patch by Kenichi Kamiya]
51
+
52
+ ### Thanks
53
+
54
+ * Kenichi Kamiya
55
+
3
56
  ## 3.4.4 - 2021-06-04 {#version-3-4-4}
4
57
 
5
58
  ### Improvements
6
59
 
7
- * Rename `assert_all?` to `assert_all`. `assert_all?` is deprecated
60
+ * Renamed `assert_all?` to `assert_all`. `assert_all?` is deprecated
8
61
  but is available.
9
62
 
10
63
  ## 3.4.3 - 2021-06-04 {#version-3-4-3}
@@ -9,6 +9,17 @@ module Test
9
9
 
10
10
  # Thrown by Test::Unit::Assertions when an assertion fails.
11
11
  class AssertionFailedError < StandardError
12
+ @debug_on_failure = false
13
+ class << self
14
+ def debug_on_failure=(boolean)
15
+ @debug_on_failure = boolean
16
+ end
17
+
18
+ def debug_on_failure?
19
+ @debug_on_failure
20
+ end
21
+ end
22
+
12
23
  attr_accessor :expected, :actual, :user_message
13
24
  attr_accessor :inspected_expected, :inspected_actual
14
25
  def initialize(message=nil, options=nil)
@@ -19,6 +30,30 @@ module Test
19
30
  @inspected_actual = options[:inspected_actual]
20
31
  @user_message = options[:user_message]
21
32
  super(message)
33
+ debug_on_failure
34
+ end
35
+
36
+ private
37
+ def debug_on_failure
38
+ return unless self.class.debug_on_failure?
39
+
40
+ begin
41
+ require "debug"
42
+ rescue LoadError
43
+ return
44
+ end
45
+
46
+ return unless binding.respond_to?(:break)
47
+
48
+ frames = caller(0)
49
+ pre = nil
50
+ Util::BacktraceFilter.filter_backtrace(frames).each do |location|
51
+ frame_index = frames.index(location)
52
+ next if frame_index.nil?
53
+ pre = "frame #{frame_index}"
54
+ break
55
+ end
56
+ binding.break(pre: pre)
22
57
  end
23
58
  end
24
59
  end
@@ -5,6 +5,7 @@
5
5
 
6
6
  require 'test/unit/assertion-failed-error'
7
7
  require 'test/unit/util/backtracefilter'
8
+ require 'test/unit/util/memory-usage'
8
9
  require 'test/unit/util/method-owner-finder'
9
10
  require 'test/unit/diff'
10
11
 
@@ -43,7 +44,7 @@ module Test
43
44
 
44
45
  ##
45
46
  # The assertion upon which all other assertions are based. Passes if the
46
- # block yields true.
47
+ # block yields not false nor nil.
47
48
  #
48
49
  # @example
49
50
  # assert_block "Couldn't do the thing" do
@@ -454,7 +455,7 @@ EOT
454
455
  alias_method :refute_instance_of, :assert_not_instance_of
455
456
 
456
457
  ##
457
- # Passes if `object` is nil.
458
+ # Passes if `object`.nil?.
458
459
  #
459
460
  # @example
460
461
  # assert_nil [1, 2].uniq!
@@ -627,7 +628,7 @@ EOT
627
628
  ##
628
629
  # Compares the `object1` with `object2` using `operator`.
629
630
  #
630
- # Passes if object1.__send__(operator, object2) is true.
631
+ # Passes if object1.__send__(operator, object2) is not false nor nil.
631
632
  #
632
633
  # @example
633
634
  # assert_operator 5, :>=, 4
@@ -647,7 +648,7 @@ EOT
647
648
  ##
648
649
  # Compares the `object1` with `object2` using `operator`.
649
650
  #
650
- # Passes if object1.__send__(operator, object2) is not true.
651
+ # Passes if object1.__send__(operator, object2) is false or nil.
651
652
  #
652
653
  # @example
653
654
  # assert_not_operator(5, :<, 4) # => pass
@@ -787,7 +788,7 @@ EOT
787
788
  alias_method :refute_match, :assert_not_match
788
789
 
789
790
  ##
790
- # Deprecated. Use #assert_not_match instead.
791
+ # @deprecated Use {#assert_not_match} instead.
791
792
  #
792
793
  # Passes if `regexp` !~ `string`
793
794
  #
@@ -1177,7 +1178,7 @@ EOT
1177
1178
 
1178
1179
  public
1179
1180
  ##
1180
- # Passes if the method send returns a true value.
1181
+ # Passes if the method `__send__` returns not false nor nil.
1181
1182
  #
1182
1183
  # `send_array` is composed of:
1183
1184
  # * A receiver
@@ -1217,7 +1218,7 @@ EOT
1217
1218
  end
1218
1219
 
1219
1220
  ##
1220
- # Passes if the method send doesn't return a true value.
1221
+ # Passes if the method `__send__` returns false or nil.
1221
1222
  #
1222
1223
  # `send_array` is composed of:
1223
1224
  # * A receiver
@@ -1267,7 +1268,7 @@ EOT
1267
1268
  assert_block(build_message(message,
1268
1269
  "<true> or <false> expected but was\n<?>",
1269
1270
  actual)) do
1270
- [true, false].include?(actual)
1271
+ true == actual || false == actual
1271
1272
  end
1272
1273
  end
1273
1274
  end
@@ -1283,7 +1284,7 @@ EOT
1283
1284
  assert_block(build_message(message,
1284
1285
  "<true> expected but was\n<?>",
1285
1286
  actual)) do
1286
- actual == true
1287
+ true == actual
1287
1288
  end
1288
1289
  end
1289
1290
  end
@@ -1299,14 +1300,14 @@ EOT
1299
1300
  assert_block(build_message(message,
1300
1301
  "<false> expected but was\n<?>",
1301
1302
  actual)) do
1302
- actual == false
1303
+ false == actual
1303
1304
  end
1304
1305
  end
1305
1306
  end
1306
1307
 
1307
1308
  ##
1308
1309
  # Passes if expression "`expected` `operator`
1309
- # `actual`" is true.
1310
+ # `actual`" is not false nor nil.
1310
1311
  #
1311
1312
  # @example
1312
1313
  # assert_compare(1, "<", 10) # -> pass
@@ -1435,7 +1436,7 @@ EOT
1435
1436
  end
1436
1437
 
1437
1438
  ##
1438
- # Passes if `object`.`predicate` is _true_.
1439
+ # Passes if `object`.`predicate` is not false nor nil.
1439
1440
  #
1440
1441
  # @example
1441
1442
  # assert_predicate([], :empty?) # -> pass
@@ -1457,7 +1458,7 @@ EOT
1457
1458
  end
1458
1459
 
1459
1460
  ##
1460
- # Passes if `object`.`predicate` is not _true_.
1461
+ # Passes if `object`.`predicate` is false or nil.
1461
1462
  #
1462
1463
  # @example
1463
1464
  # assert_not_predicate([1], :empty?) # -> pass
@@ -1686,12 +1687,12 @@ EOT
1686
1687
  # with any `block`.
1687
1688
  #
1688
1689
  # @example Pass patterns
1689
- # assert_all?([1, 2, 3]) {|item| item > 0} # => pass
1690
- # assert_all?([1, 2, 3], &:positive?) # => pass
1691
- # assert_all?([]) {|item| false} # => pass
1690
+ # assert_all([1, 2, 3]) {|item| item > 0} # => pass
1691
+ # assert_all([1, 2, 3], &:positive?) # => pass
1692
+ # assert_all([]) {|item| false} # => pass
1692
1693
  #
1693
1694
  # @example Failure pattern
1694
- # assert_all?([0, 1, 2], &:zero?) # => failure
1695
+ # assert_all([0, 1, 2], &:zero?) # => failure
1695
1696
  #
1696
1697
  # @param [#each] collection The check target.
1697
1698
  # @param [String] message The additional user message. It is
@@ -1729,6 +1730,81 @@ EOT
1729
1730
  # @since 3.4.3
1730
1731
  alias_method :assert_all?, :assert_all
1731
1732
 
1733
+ # @overload assert_nothing_leaked_memory(max_increasable_size, target=:physical, message=nil, &block)
1734
+ #
1735
+ # Asserts that increased memory usage by `block.call` is less
1736
+ # than `max_increasable_size`. `GC.start` is called before and
1737
+ # after `block.call`.
1738
+ #
1739
+ # This assertion may be fragile. Because memory usage is
1740
+ # depends on the current Ruby process's memory
1741
+ # usage. Launching a new Ruby process for this will produce
1742
+ # more stable result but we need to specify target code as
1743
+ # `String` instead of block for the approach. We choose easy
1744
+ # to write API approach rather than more stable result
1745
+ # approach for this case.
1746
+ #
1747
+ # @example Pass pattern
1748
+ # require "objspace"
1749
+ # size_per_object = ObjectSpace.memsize_of("Hello")
1750
+ # # If memory isn't leaked, physical memory of almost created objects
1751
+ # # (1000 - 10 objects) must be freed.
1752
+ # assert_nothing_leaked_memory(size_per_object * 10) do
1753
+ # 1_000.times do
1754
+ # "Hello".dup
1755
+ # end
1756
+ # end # => pass
1757
+ #
1758
+ # @example Failure pattern
1759
+ # require "objspace"
1760
+ # size_per_object = ObjectSpace.memsize_of("Hello")
1761
+ # strings = []
1762
+ # assert_nothing_leaked_memory(size_per_object * 10) do
1763
+ # 10_000.times do
1764
+ # # Created objects aren't GC-ed because they are referred.
1765
+ # strings << "Hello".dup
1766
+ # end
1767
+ # end # => failure
1768
+ #
1769
+ # @param target [:physical, :virtual] which memory usage is
1770
+ # used for comparing. `:physical` means physical memory usage
1771
+ # also known as Resident Set Size (RSS). `:virtual` means
1772
+ # virtual memory usage.
1773
+ # @yield [] do anything you want to measure memory usage
1774
+ # in the block.
1775
+ # @yieldreturn [void]
1776
+ # @return [void]
1777
+ #
1778
+ # @since 3.4.5
1779
+ def assert_nothing_leaked_memory(max_increasable_size,
1780
+ target=:physical,
1781
+ message=nil)
1782
+ _wrap_assertion do
1783
+ GC.start
1784
+ before = Util::MemoryUsage.new
1785
+ unless before.collected?
1786
+ omit("memory usage collection isn't supported on this platform")
1787
+ end
1788
+ yield
1789
+ GC.start
1790
+ after = Util::MemoryUsage.new
1791
+ before_value = before.__send__(target)
1792
+ after_value = after.__send__(target)
1793
+ actual_increased_size = after_value - before_value
1794
+ template = <<-TEMPLATE
1795
+ <?> was expected to be less than
1796
+ <?>.
1797
+ TEMPLATE
1798
+ full_message = build_message(message,
1799
+ template,
1800
+ actual_increased_size,
1801
+ max_increasable_size)
1802
+ assert_block(full_message) do
1803
+ actual_increased_size < max_increasable_size
1804
+ end
1805
+ end
1806
+ end
1807
+
1732
1808
  ##
1733
1809
  # Builds a failure message. `user_message` is added before the
1734
1810
  # `template` and `arguments` replaces the '?'s positionally in
@@ -1,10 +1,10 @@
1
1
  require "English"
2
+ require "optparse"
2
3
 
3
4
  require "test/unit/color-scheme"
4
5
  require "test/unit/priority"
5
6
  require "test/unit/attribute-matcher"
6
7
  require "test/unit/testcase"
7
- require "optparse"
8
8
 
9
9
  module Test
10
10
  module Unit
@@ -144,6 +144,7 @@ module Test
144
144
  attr_accessor :pattern, :exclude, :base, :workdir
145
145
  attr_accessor :color_scheme, :listeners
146
146
  attr_writer :stop_on_failure
147
+ attr_writer :debug_on_failure
147
148
  attr_writer :runner, :collector
148
149
 
149
150
  def initialize(standalone)
@@ -159,6 +160,7 @@ module Test
159
160
  @workdir = nil
160
161
  @listeners = []
161
162
  @stop_on_failure = false
163
+ @debug_on_failure = false
162
164
  config_file = "test-unit.yml"
163
165
  if File.exist?(config_file)
164
166
  load_config(config_file)
@@ -172,6 +174,10 @@ module Test
172
174
  @stop_on_failure
173
175
  end
174
176
 
177
+ def debug_on_failure?
178
+ @debug_on_failure
179
+ end
180
+
175
181
  def prepare
176
182
  PREPARE_HOOKS.each do |handler|
177
183
  handler.call(self)
@@ -381,6 +387,12 @@ module Test
381
387
  @stop_on_failure = boolean
382
388
  end
383
389
 
390
+ o.on("--[no-]debug-on-failure",
391
+ "Run debugger if available on failure",
392
+ "(#{AssertionFailedError.debug_on_failure?})") do |boolean|
393
+ AssertionFailedError.debug_on_failure = boolean
394
+ end
395
+
384
396
  ADDITIONAL_OPTIONS.each do |option_builder|
385
397
  option_builder.call(self, o)
386
398
  end
@@ -11,6 +11,7 @@ module Test
11
11
  def collect(name=NAME)
12
12
  suite = TestSuite.new(name)
13
13
  add_test_cases(suite, TestCase::DESCENDANTS)
14
+ adjust_ractor_tests(suite)
14
15
  suite
15
16
  end
16
17
  end
@@ -25,9 +25,9 @@ module Test
25
25
  basedir = @base
26
26
  $:.push(basedir) if basedir
27
27
  if(from.empty?)
28
- recursive_collect('.', find_test_cases)
28
+ suite = recursive_collect('.', find_test_cases)
29
29
  elsif(from.size == 1)
30
- recursive_collect(from.first, find_test_cases)
30
+ suite = recursive_collect(from.first, find_test_cases)
31
31
  else
32
32
  suites = []
33
33
  from.each do |f|
@@ -38,6 +38,8 @@ module Test
38
38
  sort(suites).each{|s| suite << s}
39
39
  suite
40
40
  end
41
+ adjust_ractor_tests(suite)
42
+ suite
41
43
  ensure
42
44
  $:.delete_at($:.rindex(basedir)) if basedir
43
45
  end
@@ -60,6 +60,8 @@ module Test
60
60
  test_suite = test_suites.first
61
61
  end
62
62
 
63
+ adjust_ractor_tests(test_suite)
64
+
63
65
  test_suite
64
66
  end
65
67
  end
@@ -26,6 +26,7 @@ module Test
26
26
  end
27
27
  end
28
28
  sort(sub_suites).each{|s| suite << s}
29
+ adjust_ractor_tests(suite)
29
30
  suite
30
31
  end
31
32
  end
@@ -68,6 +68,37 @@ module Test
68
68
  suite << sub_suite
69
69
  end
70
70
  end
71
+
72
+ def adjust_ractor_tests(suite)
73
+ return if suite.nil?
74
+ ractor_suites = extract_ractor_tests(suite)
75
+ ractor_suites.each do |ractor_suite|
76
+ suite << ractor_suite
77
+ end
78
+ end
79
+
80
+ def extract_ractor_tests(suite)
81
+ ractor_suites = []
82
+ ractor_tests = []
83
+ suite.tests.each do |test|
84
+ case test
85
+ when TestSuite
86
+ ractor_suites.concat(extract_ractor_tests(test))
87
+ else
88
+ next unless test[:ractor]
89
+ ractor_tests << test
90
+ end
91
+ end
92
+ unless ractor_tests.empty?
93
+ suite.delete_tests(ractor_tests)
94
+ ractor_suite = TestSuite.new(suite.name, suite.test_case)
95
+ ractor_tests.each do |ractor_test|
96
+ ractor_suite << ractor_test
97
+ end
98
+ ractor_suites << ractor_suite
99
+ end
100
+ ractor_suites
101
+ end
71
102
  end
72
103
  end
73
104
  end
@@ -351,6 +351,36 @@ module Test
351
351
  attribute(:description, value, {}, *targets)
352
352
  end
353
353
 
354
+ # Declares that the following test uses Ractor.
355
+ #
356
+ # Tests that use Ractor are executed at the end. Because multi
357
+ # Ractor mode is enabled in the current process and it's not
358
+ # disabled even when only one Ractor is running after running
359
+ # a test that uses Ractor on Ruby 3.0. It will be solved in
360
+ # Ruby 3.1.
361
+ #
362
+ # This is implemented by setting the `:ractor` attribute of
363
+ # the test to `true`.
364
+ #
365
+ # @param options [Hash] See {Attribute::ClassMethods#attribute}
366
+ # for details.
367
+ #
368
+ # @return [void]
369
+ #
370
+ # @example Declares that test_do_something_with_ractor uses Ractor
371
+ #
372
+ # ractor
373
+ # def test_do_something_with_ractor
374
+ # Ractor.new do
375
+ # # ...
376
+ # end
377
+ # end
378
+ #
379
+ # @since 3.4.6
380
+ def ractor(options={})
381
+ attribute(:ractor, true, options)
382
+ end
383
+
354
384
  # Defines a sub test case.
355
385
  #
356
386
  # This is a syntax sugar. The both of the following codes are
@@ -447,7 +477,7 @@ module Test
447
477
  # @private
448
478
  @@method_locations = {}
449
479
  # @private
450
- @@method_location_mutex = Mutex.new
480
+ @@method_location_mutex = Thread::Mutex.new
451
481
 
452
482
  # @private
453
483
  def method_locations
@@ -821,6 +851,9 @@ module Test
821
851
  notify("<#{signature}> was redefined",
822
852
  :backtrace => redefined_info[:backtrace])
823
853
  end
854
+ if self[:ractor] and not defined?(::Ractor)
855
+ omit("<#{signature}> requires Ractor")
856
+ end
824
857
  if @internal_data.have_test_data?
825
858
  test_method = method(@method_name)
826
859
  arity = test_method.arity
@@ -77,7 +77,7 @@ module Test
77
77
  @tests -= tests
78
78
  end
79
79
 
80
- # Retuns the rolled up number of tests in this suite;
80
+ # Returns the rolled up number of tests in this suite;
81
81
  # i.e. if the suite contains other suites, it counts the
82
82
  # tests within those suites, not the suites themselves.
83
83
  def size
@@ -0,0 +1,47 @@
1
+ module Test
2
+ module Unit
3
+ module Util
4
+ class MemoryUsage
5
+ attr_reader :virtual
6
+ attr_reader :physical
7
+ def initialize
8
+ @virtual = nil
9
+ @physical = nil
10
+ collect_data
11
+ end
12
+
13
+ def collected?
14
+ return false if @virtual.nil?
15
+ return false if @physical.nil?
16
+ true
17
+ end
18
+
19
+ private
20
+ def collect_data
21
+ collect_data_proc
22
+ end
23
+
24
+ def collect_data_proc
25
+ status_file = "/proc/self/status"
26
+ return false unless File.exist?(status_file)
27
+
28
+ data = File.binread(status_file)
29
+ data.each_line do |line|
30
+ case line
31
+ when /\AVm(Size|RSS):\s*(\d+)\s*kB/
32
+ name = $1
33
+ value = Integer($2, 10) * 1024
34
+ case name
35
+ when "Size"
36
+ @virtual = value
37
+ when "RSS"
38
+ @physical = value
39
+ end
40
+ end
41
+ end
42
+ collected?
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -1,5 +1,5 @@
1
1
  module Test
2
2
  module Unit
3
- VERSION = "3.4.4"
3
+ VERSION = "3.4.8"
4
4
  end
5
5
  end