tldr 0.6.0 → 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
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.