tldr 0.6.0 → 0.6.2

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: 4be82f4551acdf8d4312b512a1c12d2a857cb1d1420b4eebc6d7a74632eecd19
4
- data.tar.gz: 8f10cecb4d4701fb24f84c36ec78f6b91fe4b381bcf6c86f02f2743f93b61a1f
3
+ metadata.gz: 82e76ebc309cbf643c22244a1674aa3a7ae32578006ce05fac262aec15292bec
4
+ data.tar.gz: 99610ebabba0d069f3618f6fa7cf79793c44491c4764463283e304fe329c7247
5
5
  SHA512:
6
- metadata.gz: 8262b1e6ee4fd4154d9c46d883d1d49b76026a3752b5d26a4ea520fa8b0c0b786019cb3c770b319bd22130c1f194883d02cefbb38b9f171a4571b91ab1793d5f
7
- data.tar.gz: 125b89ee409f0080a61ceb00232464c455213223883ce10502742a90a825c0a208ed625e5608ecd585a26a900bc49dd8d6a1b49202a88684386c455d9eb313a0
6
+ metadata.gz: de39822a1208f86b69a45ac1185d2c6de22462282a6fa2f59054e84bfa55b135f61279ae3b9be2f61463557a2a04516397bd02083a6c2c8a26c8e627875a44d1
7
+ data.tar.gz: ae0c0ed4ec84f2969a0b223a668351ce475536121fb59e2b56a4fbd7be18be844d5fec3aaf3d5ebfd5cf37ddb6a0a02afeef1f0e1f2f975c7d2796d322ab0ccb
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ ## [0.6.2]
2
+
3
+ * Since TLDR runs fine on 3.1, reduce the gem requirement
4
+
5
+ ## [0.6.1]
6
+
7
+ * Correctly report the number of test classes that run
8
+ * Finish planning the test run before starting the clock on the timer (that's
9
+ a millisecond or two in savings!)
10
+
1
11
  ## [0.6.0]
2
12
 
3
13
  * When `dont_run_these_in_parallel!` and `run_these_together!` are called from a
data/Rakefile CHANGED
@@ -6,6 +6,7 @@ require "rake/testtask"
6
6
  Rake::TestTask.new(:test) do |t|
7
7
  t.libs << "tests"
8
8
  t.libs << "lib"
9
+ t.warning = true
9
10
  t.test_files = FileList["tests/**/*_test.rb"]
10
11
  end
11
12
 
@@ -1,26 +1,20 @@
1
1
  class TLDR
2
- class Parallelizer
2
+ class Executor
3
3
  def initialize
4
- @strategizer = Strategizer.new
5
4
  @thread_pool = Concurrent::ThreadPoolExecutor.new(
6
5
  name: "tldr",
7
6
  auto_terminate: true
8
7
  )
9
8
  end
10
9
 
11
- def parallelize all_tests, config, &blk
12
- return run_in_sequence(all_tests, &blk) if all_tests.size < 2 || !config.parallel
13
-
14
- strategy = @strategizer.strategize(
15
- all_tests,
16
- GROUPED_TESTS,
17
- THREAD_UNSAFE_TESTS,
18
- (config.no_prepend ? [] : config.prepend_paths)
19
- )
20
-
21
- run_in_sequence(strategy.prepend_thread_unsafe_tests, &blk) +
22
- run_in_parallel(strategy.parallel_tests_and_groups, &blk) +
23
- run_in_sequence(strategy.thread_unsafe_tests, &blk)
10
+ def execute plan, &blk
11
+ if plan.strategy.parallel?
12
+ run_in_sequence(plan.strategy.prepend_sequential_tests, &blk) +
13
+ run_in_parallel(plan.strategy.parallel_tests_and_groups, &blk) +
14
+ run_in_sequence(plan.strategy.append_sequential_tests, &blk)
15
+ else
16
+ run_in_sequence(plan.tests, &blk)
17
+ end
24
18
  end
25
19
 
26
20
  private
data/lib/tldr/planner.rb CHANGED
@@ -2,6 +2,10 @@ require "pathname"
2
2
 
3
3
  class TLDR
4
4
  class Planner
5
+ def initialize
6
+ @strategizer = Strategizer.new
7
+ end
8
+
5
9
  def plan config
6
10
  $VERBOSE = config.warnings
7
11
  search_locations = PathUtil.expand_paths config.paths, globs: false
@@ -12,8 +16,7 @@ class TLDR
12
16
 
13
17
  tests = gather_tests
14
18
  config.update_after_gathering_tests! tests
15
-
16
- Plan.new prepend(
19
+ tests_to_run = prepend(
17
20
  shuffle(
18
21
  exclude_by_path(
19
22
  exclude_by_name(
@@ -29,6 +32,15 @@ class TLDR
29
32
  ),
30
33
  config
31
34
  )
35
+
36
+ strategy = @strategizer.strategize(
37
+ tests_to_run,
38
+ GROUPED_TESTS,
39
+ THREAD_UNSAFE_TESTS,
40
+ config
41
+ )
42
+
43
+ Plan.new tests_to_run, strategy
32
44
  end
33
45
 
34
46
  private
@@ -68,7 +80,7 @@ class TLDR
68
80
 
69
81
  tests.reject { |test|
70
82
  name_excludes.any? { |filter|
71
- filter === test.method.to_s || filter === "#{test.klass}##{test.method}"
83
+ filter === test.method_name.to_s || filter === "#{test.test_class}##{test.method_name}"
72
84
  }
73
85
  }
74
86
  end
@@ -89,7 +101,7 @@ class TLDR
89
101
 
90
102
  tests.select { |test|
91
103
  name_filters.any? { |filter|
92
- filter === test.method.to_s || filter === "#{test.klass}##{test.method}"
104
+ filter === test.method_name.to_s || filter === "#{test.test_class}##{test.method_name}"
93
105
  }
94
106
  }
95
107
  end
@@ -87,7 +87,7 @@ class TLDR
87
87
  @out.print "Finished in #{duration}ms."
88
88
 
89
89
  @out.print "\n\n"
90
- class_count = test_results.uniq { |result| result.test.class }.size
90
+ class_count = test_results.uniq { |result| result.test.test_class }.size
91
91
  test_count = test_results.size
92
92
  @out.print [
93
93
  plural(class_count, "test class", "test classes"),
@@ -127,7 +127,7 @@ class TLDR
127
127
  end
128
128
 
129
129
  def describe test, location = test.location
130
- "#{test.klass}##{test.method} [#{location.locator}]"
130
+ "#{test.test_class}##{test.method_name} [#{location.locator}]"
131
131
  end
132
132
 
133
133
  def plural count, singular, plural = "#{singular}s"
data/lib/tldr/runner.rb CHANGED
@@ -3,7 +3,7 @@ require "irb"
3
3
  class TLDR
4
4
  class Runner
5
5
  def initialize
6
- @parallelizer = Parallelizer.new
6
+ @executor = Executor.new
7
7
  @wip = Concurrent::Array.new
8
8
  @results = Concurrent::Array.new
9
9
  @run_aborted = Concurrent::AtomicBoolean.new false
@@ -12,8 +12,8 @@ class TLDR
12
12
  def run config, plan
13
13
  @wip.clear
14
14
  @results.clear
15
- reporter = config.reporter.new config
16
- reporter.before_suite plan.tests
15
+ reporter = config.reporter.new(config)
16
+ reporter.before_suite(plan.tests)
17
17
 
18
18
  time_bomb = Thread.new {
19
19
  explode = proc do
@@ -34,34 +34,8 @@ class TLDR
34
34
  end
35
35
  }
36
36
 
37
- results = @parallelizer.parallelize(plan.tests, config) { |test|
38
- e = nil
39
- start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :microsecond)
40
- wip_test = WIPTest.new test, start_time
41
- @wip << wip_test
42
- runtime = time_it(start_time) do
43
- instance = test.klass.new
44
- instance.setup if instance.respond_to? :setup
45
- if instance.respond_to? :around
46
- did_run = false
47
- instance.around {
48
- did_run = true
49
- instance.send(test.method)
50
- }
51
- raise Error, "#{test.klass}#around failed to yield or call the passed test block" unless did_run
52
- else
53
- instance.send(test.method)
54
- end
55
- instance.teardown if instance.respond_to? :teardown
56
- rescue Skip, Failure, StandardError => e
57
- end
58
- TestResult.new(test, e, runtime).tap do |result|
59
- next if @run_aborted.true?
60
- @results << result
61
- @wip.delete wip_test
62
- reporter.after_test result
63
- fail_fast reporter, plan, result if result.failing? && config.fail_fast
64
- end
37
+ results = @executor.execute(plan) { |test|
38
+ run_test(test, config, plan, reporter)
65
39
  }.tap do
66
40
  time_bomb.kill
67
41
  end
@@ -74,6 +48,36 @@ class TLDR
74
48
 
75
49
  private
76
50
 
51
+ def run_test test, config, plan, reporter
52
+ e = nil
53
+ start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :microsecond)
54
+ wip_test = WIPTest.new test, start_time
55
+ @wip << wip_test
56
+ runtime = time_it(start_time) do
57
+ instance = test.test_class.new
58
+ instance.setup if instance.respond_to? :setup
59
+ if instance.respond_to? :around
60
+ did_run = false
61
+ instance.around {
62
+ did_run = true
63
+ instance.send(test.method_name)
64
+ }
65
+ raise Error, "#{test.test_class}#around failed to yield or call the passed test block" unless did_run
66
+ else
67
+ instance.send(test.method_name)
68
+ end
69
+ instance.teardown if instance.respond_to? :teardown
70
+ rescue Skip, Failure, StandardError => e
71
+ end
72
+ TestResult.new(test, e, runtime).tap do |result|
73
+ next if @run_aborted.true?
74
+ @results << result
75
+ @wip.delete wip_test
76
+ reporter.after_test result
77
+ fail_fast reporter, plan, result if result.failing? && config.fail_fast
78
+ end
79
+ end
80
+
77
81
  def fail_fast reporter, plan, fast_failed_result
78
82
  unless @run_aborted.true?
79
83
  @run_aborted.make_true
@@ -1,6 +1,8 @@
1
1
  class TLDR
2
2
  class Strategizer
3
- Strategy = Struct.new :prepend_thread_unsafe_tests, :parallel_tests_and_groups, :thread_unsafe_tests
3
+ Strategy = Struct.new :parallel?, :prepend_sequential_tests,
4
+ :parallel_tests_and_groups, :append_sequential_tests,
5
+ keyword_init: true
4
6
 
5
7
  # Combine all discovered test methods with any methods grouped by run_these_together!
6
8
  #
@@ -8,13 +10,15 @@ class TLDR
8
10
  # - Map over tests to build out groups in order to retain shuffle order
9
11
  # (group will run in position of first test in the group)
10
12
  # - If a test is in multiple groups, only run it once
11
- def strategize all_tests, run_these_together_groups, thread_unsafe_test_groups, prepend_paths
13
+ def strategize all_tests, run_these_together_groups, thread_unsafe_test_groups, config
14
+ return Strategy.new(parallel?: false) if run_sequentially?(all_tests, config)
15
+
12
16
  thread_unsafe_tests, thread_safe_tests = partition_unsafe(all_tests, thread_unsafe_test_groups)
13
- prepend_thread_unsafe_tests, thread_unsafe_tests = partition_prepend(thread_unsafe_tests, prepend_paths)
17
+ prepend_sequential_tests, append_sequential_tests = partition_prepend(thread_unsafe_tests, config)
14
18
 
15
- grouped_tests = prepare_run_together_groups run_these_together_groups, thread_safe_tests, thread_unsafe_tests
19
+ grouped_tests = prepare_run_together_groups run_these_together_groups, thread_safe_tests, append_sequential_tests
16
20
  already_included_groups = []
17
- Strategy.new prepend_thread_unsafe_tests, thread_safe_tests.map { |test|
21
+ parallel_tests_and_groups = thread_safe_tests.map { |test|
18
22
  if (group = grouped_tests.find { |group| group.tests.include? test })
19
23
  if already_included_groups.include? group
20
24
  next
@@ -28,11 +32,21 @@ class TLDR
28
32
  else
29
33
  test
30
34
  end
31
- }.compact, thread_unsafe_tests
35
+ }.compact
36
+ Strategy.new(
37
+ parallel?: true,
38
+ prepend_sequential_tests:,
39
+ parallel_tests_and_groups:,
40
+ append_sequential_tests:
41
+ )
32
42
  end
33
43
 
34
44
  private
35
45
 
46
+ def run_sequentially? all_tests, config
47
+ all_tests.size < 2 || !config.parallel
48
+ end
49
+
36
50
  def partition_unsafe tests, thread_unsafe_test_groups
37
51
  tests.partition { |test|
38
52
  thread_unsafe_test_groups.any? { |group| group.tests.include? test }
@@ -41,7 +55,8 @@ class TLDR
41
55
 
42
56
  # Sadly duplicative with Planner.rb, necessitating the extraction of PathUtil
43
57
  # Suboptimal, but we do indeed need to do this work in two places ¯\_(ツ)_/¯
44
- def partition_prepend thread_unsafe_tests, prepend_paths
58
+ def partition_prepend thread_unsafe_tests, config
59
+ prepend_paths = config.no_prepend ? [] : config.prepend_paths
45
60
  locations = PathUtil.expand_paths prepend_paths
46
61
 
47
62
  thread_unsafe_tests.partition { |test|
@@ -1,3 +1,3 @@
1
1
  class TLDR
2
- Plan = Struct.new :tests
2
+ Plan = Struct.new :tests, :strategy
3
3
  end
@@ -1,17 +1,17 @@
1
1
  class TLDR
2
- Test = Struct.new :klass, :method do
2
+ Test = Struct.new :test_class, :method_name do
3
3
  attr_reader :file, :line, :location
4
4
 
5
5
  def initialize(*args)
6
6
  super
7
- @file, @line = SorbetCompatibility.unwrap_method(klass.instance_method(method)).source_location
7
+ @file, @line = SorbetCompatibility.unwrap_method(test_class.instance_method(method_name)).source_location
8
8
  @location = Location.new file, line
9
9
  end
10
10
 
11
11
  # Memoizing at call time, because re-parsing isn't free and isn't usually necessary
12
12
  def end_line
13
13
  @end_line ||= begin
14
- test_method = SorbetCompatibility.unwrap_method klass.instance_method(method)
14
+ test_method = SorbetCompatibility.unwrap_method test_class.instance_method(method_name)
15
15
  RubyVM::AbstractSyntaxTree.of(test_method).last_lineno
16
16
  end
17
17
  end
data/lib/tldr/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class TLDR
2
- VERSION = "0.6.0"
2
+ VERSION = "0.6.2"
3
3
  end
data/lib/tldr.rb CHANGED
@@ -5,8 +5,8 @@ require_relative "tldr/assertions"
5
5
  require_relative "tldr/backtrace_filter"
6
6
  require_relative "tldr/class_util"
7
7
  require_relative "tldr/error"
8
+ require_relative "tldr/executor"
8
9
  require_relative "tldr/parallel_controls"
9
- require_relative "tldr/parallelizer"
10
10
  require_relative "tldr/path_util"
11
11
  require_relative "tldr/planner"
12
12
  require_relative "tldr/reporters"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tldr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Searls
@@ -61,8 +61,8 @@ files:
61
61
  - lib/tldr/backtrace_filter.rb
62
62
  - lib/tldr/class_util.rb
63
63
  - lib/tldr/error.rb
64
+ - lib/tldr/executor.rb
64
65
  - lib/tldr/parallel_controls.rb
65
- - lib/tldr/parallelizer.rb
66
66
  - lib/tldr/path_util.rb
67
67
  - lib/tldr/planner.rb
68
68
  - lib/tldr/rake.rb
@@ -100,14 +100,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
100
100
  requirements:
101
101
  - - ">="
102
102
  - !ruby/object:Gem::Version
103
- version: 3.2.0
103
+ version: '3.1'
104
104
  required_rubygems_version: !ruby/object:Gem::Requirement
105
105
  requirements:
106
106
  - - ">="
107
107
  - !ruby/object:Gem::Version
108
108
  version: '0'
109
109
  requirements: []
110
- rubygems_version: 3.4.6
110
+ rubygems_version: 3.3.26
111
111
  signing_key:
112
112
  specification_version: 4
113
113
  summary: TLDR will run your tests, but only for 1.8 seconds.