tldr 0.5.0 → 0.6.0

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: 32f7b9dbcf9e09433eef762eaafe19804643aa543ac2c0a9599303ea2e960f25
4
- data.tar.gz: 789c07fb2db1fad39b234976999b575a1bea27c4796a4d062a373df11d3716e5
3
+ metadata.gz: 4be82f4551acdf8d4312b512a1c12d2a857cb1d1420b4eebc6d7a74632eecd19
4
+ data.tar.gz: 8f10cecb4d4701fb24f84c36ec78f6b91fe4b381bcf6c86f02f2743f93b61a1f
5
5
  SHA512:
6
- metadata.gz: 7975ec24ae3f080ed564666c5319928964c970794a740a21253551be1be9b945374394b2f860cdd8737151f8e21fdb0d592c126895dd02b91dd21c899824226a
7
- data.tar.gz: b11f3c52624b63a7aa44eadd4f17aa662d134648d61eb55eb7124e7956d0b28f20a04545552f9af8710330ffa98c94e85cec87dc80715a532522ccdeb15a8b42
6
+ metadata.gz: 8262b1e6ee4fd4154d9c46d883d1d49b76026a3752b5d26a4ea520fa8b0c0b786019cb3c770b319bd22130c1f194883d02cefbb38b9f171a4571b91ab1793d5f
7
+ data.tar.gz: 125b89ee409f0080a61ceb00232464c455213223883ce10502742a90a825c0a208ed625e5608ecd585a26a900bc49dd8d6a1b49202a88684386c455d9eb313a0
data/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ ## [0.6.0]
2
+
3
+ * When `dont_run_these_in_parallel!` and `run_these_together!` are called from a
4
+ super class, gather subclasses' methods as well when the method is `nil`
5
+ * Stop shelling out to `tldr` from our Rake task. Rescue `SystemExit` instead
6
+ * Rename `Config#helper` to `Config#helper_paths`, which YAML config keys
7
+ * Print Ruby warnings by default (disable with --no-warnings)
8
+
1
9
  ## [0.5.0]
2
10
 
3
11
  * Define your own Rake tasks with `TLDR::Task` and pass in a custom configuration
data/README.md CHANGED
@@ -23,8 +23,8 @@ suite.
23
23
 
24
24
  Some stuff you might like:
25
25
 
26
- * A CLI that can run tests by line number(s) (e.g. `foo.rb:5 bar.rb:3:10`) and
27
- by names or patterns (e.g. `--name test_fail,test_error --name "/_\d/"`)
26
+ * A CLI that can specify tests by line number(s) (e.g. `foo.rb:5 bar.rb:3:10`)
27
+ and by names or patterns (e.g. `--name test_fail,test_error --name "/_\d/"`)
28
28
  * Everything is **parallel by default**, and seems pretty darn fast; TLDR
29
29
  also provides [several escape hatches to sequester tests that aren't thread-safe](#parallel-by-default-is-nice-in-theory-but-half-my-tests-are-failing-wat)
30
30
  * Surprisingly delightful color diff output when two things fail to equal one
@@ -112,8 +112,8 @@ Usage: tldr [options] some_tests/**/*.rb some/path.rb:13 ...
112
112
  -n, --name PATTERN One or more names or /patterns/ of tests to run (like: foo_test, /test_foo.*/, Foo#foo_test)
113
113
  --exclude-name PATTERN One or more names or /patterns/ NOT to run
114
114
  --exclude-path PATH One or more paths NOT to run (like: foo.rb, "test/bar/**", baz.rb:3)
115
- --helper HELPER Path to a test helper to load before any tests (Default: "test/helper.rb")
116
- --no-helper Don't try loading a test helper before the tests
115
+ --helper PATH One or more paths to a helper that is required before any tests (Default: "test/helper.rb")
116
+ --no-helper Don't require any test helpers
117
117
  --prepend PATH Prepend one or more paths to run before the rest (Default: most recently modified test)
118
118
  --no-prepend Don't prepend any tests before the rest of the suite
119
119
  -l, --load-path PATH Add one or more paths to the $LOAD_PATH (Default: ["test"])
@@ -122,6 +122,7 @@ Usage: tldr [options] some_tests/**/*.rb some/path.rb:13 ...
122
122
  --no-dotfile Disable loading .tldr.yml dotfile
123
123
  --no-emoji Disable emoji in the output
124
124
  -v, --verbose Print stack traces for errors
125
+ --[no-]warnings Print Ruby warnings (Default: true)
125
126
  --comment COMMENT No-op comment, used internally for multi-line execution instructions
126
127
  ```
127
128
 
@@ -193,7 +194,7 @@ require "tldr/rake"
193
194
 
194
195
  TLDR::Task.new(name: :safe_tests, config: TLDR::Config.new(
195
196
  paths: FileList["safe/**/*_test.rb"],
196
- helper: "safe/helper.rb",
197
+ helper_paths: ["safe/helper.rb"],
197
198
  load_paths: ["lib", "safe"]
198
199
  ))
199
200
  ```
@@ -35,11 +35,12 @@ class TLDR
35
35
  options[:exclude_paths] += path
36
36
  end
37
37
 
38
- opts.on "#{CONFLAGS[:helper]} HELPER", String, "Path to a test helper to load before any tests (Default: \"test/helper.rb\")" do |helper|
39
- options[:helper] = helper
38
+ opts.on "#{CONFLAGS[:helper_paths]} PATH", Array, "One or more paths to a helper that is required before any tests (Default: \"test/helper.rb\")" do |path|
39
+ options[:helper_paths] ||= []
40
+ options[:helper_paths] += path
40
41
  end
41
42
 
42
- opts.on CONFLAGS[:no_helper], "Don't try loading a test helper before the tests" do
43
+ opts.on CONFLAGS[:no_helper], "Don't require any test helpers" do
43
44
  options[:no_helper] = true
44
45
  end
45
46
 
@@ -77,6 +78,10 @@ class TLDR
77
78
  options[:verbose] = verbose
78
79
  end
79
80
 
81
+ opts.on CONFLAGS[:warnings], "Print Ruby warnings (Default: true)" do |warnings|
82
+ options[:warnings] = warnings
83
+ end
84
+
80
85
  opts.on "--comment COMMENT", String, "No-op comment, used internally for multi-line execution instructions" do
81
86
  # See "--comment" in lib/tldr/reporters/default.rb for an example of how this is used internally
82
87
  end
@@ -0,0 +1,15 @@
1
+ class TLDR
2
+ module ClassUtil
3
+ def self.gather_descendants root_klass
4
+ root_klass.subclasses + root_klass.subclasses.flat_map { |subklass|
5
+ gather_descendants subklass
6
+ }
7
+ end
8
+
9
+ def self.gather_tests klass
10
+ klass.instance_methods.grep(/^test_/).sort.map { |method|
11
+ Test.new klass, method
12
+ }
13
+ end
14
+ end
15
+ end
@@ -1,6 +1,8 @@
1
1
  class TLDR
2
2
  module PathUtil
3
- def self.expand_search_locations path_strings
3
+ def self.expand_paths path_strings, globs: true
4
+ path_strings = expand_globs path_strings if globs
5
+
4
6
  path_strings.flat_map { |path_string|
5
7
  File.directory?(path_string) ? Dir["#{path_string}/**/*.rb"] : path_string
6
8
  }.flat_map { |path_string|
data/lib/tldr/planner.rb CHANGED
@@ -3,7 +3,8 @@ require "pathname"
3
3
  class TLDR
4
4
  class Planner
5
5
  def plan config
6
- search_locations = PathUtil.expand_search_locations config.paths
6
+ $VERBOSE = config.warnings
7
+ search_locations = PathUtil.expand_paths config.paths, globs: false
7
8
 
8
9
  prepend_load_paths config
9
10
  require_test_helper config
@@ -33,16 +34,14 @@ class TLDR
33
34
  private
34
35
 
35
36
  def gather_tests
36
- gather_descendants(TLDR).flat_map { |subklass|
37
- subklass.instance_methods.grep(/^test_/).sort.map { |method|
38
- Test.new subklass, method
39
- }
37
+ ClassUtil.gather_descendants(TLDR).flat_map { |subklass|
38
+ ClassUtil.gather_tests(subklass)
40
39
  }
41
40
  end
42
41
 
43
42
  def prepend tests, config
44
43
  return tests if config.no_prepend
45
- prepended_locations = PathUtil.expand_search_locations PathUtil.expand_globs config.prepend_paths
44
+ prepended_locations = PathUtil.expand_paths config.prepend_paths
46
45
  prepended, rest = tests.partition { |test|
47
46
  PathUtil.locations_include_test? prepended_locations, test
48
47
  }
@@ -54,7 +53,7 @@ class TLDR
54
53
  end
55
54
 
56
55
  def exclude_by_path tests, exclude_paths
57
- excluded_locations = PathUtil.expand_search_locations PathUtil.expand_globs exclude_paths
56
+ excluded_locations = PathUtil.expand_paths exclude_paths
58
57
  return tests if excluded_locations.empty?
59
58
 
60
59
  tests.reject { |test|
@@ -102,8 +101,12 @@ class TLDR
102
101
  end
103
102
 
104
103
  def require_test_helper config
105
- return if config.no_helper || config.helper.nil? || !File.exist?(config.helper)
106
- require File.expand_path(config.helper, Dir.pwd)
104
+ return if config.no_helper || config.helper_paths.empty?
105
+ PathUtil.expand_paths(config.helper_paths).map(&:file).uniq.each do |helper_file|
106
+ next unless File.exist?(helper_file)
107
+
108
+ require helper_file
109
+ end
107
110
  end
108
111
 
109
112
  def require_tests search_locations
@@ -112,12 +115,6 @@ class TLDR
112
115
  end
113
116
  end
114
117
 
115
- def gather_descendants root_klass
116
- root_klass.subclasses + root_klass.subclasses.flat_map { |subklass|
117
- gather_descendants subklass
118
- }
119
- end
120
-
121
118
  def expand_names_with_patterns names
122
119
  names.map { |name|
123
120
  if name.is_a?(String) && name =~ /^\/(.*)\/$/
data/lib/tldr/rake.rb CHANGED
@@ -16,13 +16,17 @@ class TLDR
16
16
  def define name, task_config
17
17
  desc "Run #{name} tests (use TLDR_OPTS or .tldr.yml to configure)"
18
18
  task name do
19
- cli_args = build_cli_args(task_config)
20
- fail unless system "#{"bundle exec " if defined?(Bundler)}tldr #{cli_args}"
19
+ argv = Shellwords.shellwords(merge_env_opts(task_config).to_full_args)
20
+ begin
21
+ TLDR::Run.cli(argv)
22
+ rescue SystemExit => e
23
+ fail "TLDR task #{name} failed with status #{e.status}" unless e.status == 0
24
+ end
21
25
  end
22
26
  end
23
27
 
24
- def build_cli_args task_config
25
- config = if ENV["TLDR_OPTS"]
28
+ def merge_env_opts task_config
29
+ if ENV["TLDR_OPTS"]
26
30
  env_argv = Shellwords.shellwords(ENV["TLDR_OPTS"])
27
31
  opts_config = ArgvParser.new.parse(env_argv, {
28
32
  config_intended_for_merge_only: true
@@ -31,8 +35,6 @@ class TLDR
31
35
  else
32
36
  task_config
33
37
  end
34
-
35
- config.to_full_args
36
38
  end
37
39
  end
38
40
  end
@@ -9,7 +9,8 @@ class TLDR
9
9
  def before_suite tests
10
10
  @suite_start_time = Process.clock_gettime Process::CLOCK_MONOTONIC, :microsecond
11
11
  @out.print <<~MSG
12
- Command: #{tldr_command} #{@config.to_full_args}#{"\n#{@icons.seed} #{CONFLAGS[:seed]} #{@config.seed}" unless @config.seed_set_intentionally}
12
+ Command: #{tldr_command} #{@config.to_full_args}
13
+ #{@icons.seed} #{CONFLAGS[:seed]} #{@config.seed}
13
14
 
14
15
  #{@icons.run} Running:
15
16
 
@@ -42,7 +42,7 @@ class TLDR
42
42
  # Sadly duplicative with Planner.rb, necessitating the extraction of PathUtil
43
43
  # Suboptimal, but we do indeed need to do this work in two places ¯\_(ツ)_/¯
44
44
  def partition_prepend thread_unsafe_tests, prepend_paths
45
- locations = PathUtil.expand_search_locations PathUtil.expand_globs prepend_paths
45
+ locations = PathUtil.expand_paths prepend_paths
46
46
 
47
47
  thread_unsafe_tests.partition { |test|
48
48
  PathUtil.locations_include_test? locations, test
@@ -4,7 +4,7 @@ class TLDR
4
4
  no_helper: "--no-helper",
5
5
  verbose: "--verbose",
6
6
  reporter: "--reporter",
7
- helper: "--helper",
7
+ helper_paths: "--helper",
8
8
  load_paths: "--load-path",
9
9
  parallel: "--[no-]parallel",
10
10
  names: "--name",
@@ -16,19 +16,22 @@ class TLDR
16
16
  exclude_names: "--exclude-name",
17
17
  base_path: "--base-path",
18
18
  no_dotfile: "--no-dotfile",
19
+ warnings: "--[no-]warnings",
19
20
  paths: nil
20
21
  }.freeze
21
22
 
22
- PATH_FLAGS = [:paths, :helper, :load_paths, :prepend_paths, :exclude_paths].freeze
23
+ PATH_FLAGS = [:paths, :helper_paths, :load_paths, :prepend_paths, :exclude_paths].freeze
23
24
  MOST_RECENTLY_MODIFIED_TAG = "MOST_RECENTLY_MODIFIED".freeze
24
-
25
- Config = Struct.new :paths, :seed, :no_helper, :verbose, :reporter,
26
- :helper, :load_paths, :parallel, :names, :fail_fast, :no_emoji,
25
+ CONFIG_ATTRIBUTES = [
26
+ :paths, :seed, :no_helper, :verbose, :reporter,
27
+ :helper_paths, :load_paths, :parallel, :names, :fail_fast, :no_emoji,
27
28
  :prepend_paths, :no_prepend, :exclude_paths, :exclude_names, :base_path,
28
- :no_dotfile,
29
+ :no_dotfile, :warnings,
29
30
  # Internal properties
30
- :config_intended_for_merge_only, :seed_set_intentionally, :cli_defaults,
31
- keyword_init: true do
31
+ :config_intended_for_merge_only, :seed_set_intentionally, :cli_defaults
32
+ ].freeze
33
+
34
+ Config = Struct.new(*CONFIG_ATTRIBUTES, keyword_init: true) do
32
35
  def initialize(**args)
33
36
  unless args[:config_intended_for_merge_only]
34
37
  change_working_directory_because_i_am_bad_and_i_should_feel_bad!(args[:base_path])
@@ -60,20 +63,21 @@ class TLDR
60
63
  no_prepend: false,
61
64
  exclude_paths: [],
62
65
  exclude_names: [],
63
- base_path: nil
66
+ base_path: nil,
67
+ warnings: true
64
68
  }
65
69
 
66
70
  if cli_defaults
67
71
  common.merge(
68
72
  paths: Dir["test/**/*_test.rb", "test/**/test_*.rb"],
69
- helper: "test/helper.rb",
73
+ helper_paths: ["test/helper.rb"],
70
74
  load_paths: ["test"],
71
75
  prepend_paths: [MOST_RECENTLY_MODIFIED_TAG]
72
76
  )
73
77
  else
74
78
  common.merge(
75
79
  paths: [],
76
- helper: nil,
80
+ helper_paths: [],
77
81
  load_paths: [],
78
82
  prepend_paths: []
79
83
  )
@@ -92,17 +96,17 @@ class TLDR
92
96
  defaults = Config.build_defaults(cli_defaults: merged_args[:cli_defaults])
93
97
 
94
98
  # Arrays
95
- [:paths, :load_paths, :names, :prepend_paths, :exclude_paths, :exclude_names].each do |key|
99
+ [:paths, :helper_paths, :load_paths, :names, :prepend_paths, :exclude_paths, :exclude_names].each do |key|
96
100
  merged_args[key] = defaults[key] if merged_args[key].nil? || merged_args[key].empty?
97
101
  end
98
102
 
99
103
  # Booleans
100
- [:no_helper, :verbose, :fail_fast, :no_emoji, :no_prepend].each do |key|
104
+ [:no_helper, :verbose, :fail_fast, :no_emoji, :no_prepend, :warnings].each do |key|
101
105
  merged_args[key] = defaults[key] if merged_args[key].nil?
102
106
  end
103
107
 
104
108
  # Values
105
- [:seed, :reporter, :helper].each do |key|
109
+ [:seed, :reporter].each do |key|
106
110
  merged_args[key] ||= defaults[key]
107
111
  end
108
112
 
@@ -166,7 +170,7 @@ class TLDR
166
170
  # Don't print prepended tests if they're disabled
167
171
  next
168
172
  end
169
- elsif key == :helper && no_helper
173
+ elsif key == :helper_paths && no_helper
170
174
  # Don't print the helper if it's disabled
171
175
  next
172
176
  elsif key == :parallel
@@ -176,6 +180,8 @@ class TLDR
176
180
  "--parallel"
177
181
  end
178
182
  next val
183
+ elsif key == :warnings && defaults[:warnings] != self[:warnings]
184
+ next warnings ? "--warnings" : "--no-warnings"
179
185
  end
180
186
 
181
187
  if defaults[key] == self[key]
@@ -231,6 +237,9 @@ class TLDR
231
237
  if dotfile_args.key?(:reporter)
232
238
  dotfile_args[:reporter] = Kernel.const_get(dotfile_args[:reporter])
233
239
  end
240
+ if (invalid_args = dotfile_args.except(*CONFIG_ATTRIBUTES)).any?
241
+ raise Error, "Invalid keys in .tldr.yml file: #{invalid_args.keys.join(", ")}"
242
+ end
234
243
 
235
244
  dotfile_args.merge(args)
236
245
  end
@@ -6,8 +6,8 @@ class TLDR
6
6
  @tests ||= configuration.flat_map { |(klass, method)|
7
7
  klass = Kernel.const_get(klass) if klass.is_a? String
8
8
  if method.nil?
9
- klass.instance_methods.grep(/^test_/).sort.map { |method|
10
- Test.new klass, method
9
+ ([klass] + ClassUtil.gather_descendants(klass)).flat_map { |klass|
10
+ ClassUtil.gather_tests(klass)
11
11
  }
12
12
  else
13
13
  Test.new klass, method
data/lib/tldr/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  class TLDR
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
data/lib/tldr.rb CHANGED
@@ -3,6 +3,7 @@ require "concurrent-ruby"
3
3
  require_relative "tldr/argv_parser"
4
4
  require_relative "tldr/assertions"
5
5
  require_relative "tldr/backtrace_filter"
6
+ require_relative "tldr/class_util"
6
7
  require_relative "tldr/error"
7
8
  require_relative "tldr/parallel_controls"
8
9
  require_relative "tldr/parallelizer"
@@ -40,6 +41,8 @@ class TLDR
40
41
  def self.at_exit! config = Config.new
41
42
  # Ignore at_exit when running tldr CLI, since that will run any tests
42
43
  return if $PROGRAM_NAME.end_with? "tldr"
44
+ # Also ignore if we're running from within our rake task
45
+ return if caller.any? { |line| line.include? "lib/tldr/rake.rb" }
43
46
  # Ignore at_exit when we've already registered an at_exit hook
44
47
  return if @@at_exit_registered
45
48
 
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.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Searls
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2023-09-28 00:00:00.000000000 Z
12
+ date: 2023-09-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: super_diff
@@ -59,6 +59,7 @@ files:
59
59
  - lib/tldr/assertions.rb
60
60
  - lib/tldr/assertions/minitest_compatibility.rb
61
61
  - lib/tldr/backtrace_filter.rb
62
+ - lib/tldr/class_util.rb
62
63
  - lib/tldr/error.rb
63
64
  - lib/tldr/parallel_controls.rb
64
65
  - lib/tldr/parallelizer.rb