tldr 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2b1d2d2176a02f16901ea2c2c739fd576c46fd363e5ea79790718f58efadedba
4
+ data.tar.gz: 727de7ca74f16a4676636780e19abc1f7c9cd0d906b4577de1aa462039f6e8f5
5
+ SHA512:
6
+ metadata.gz: ca384136a4c9c1863f4f22916090f8c4f6f1836f3935495d0c0018d7fee48237c1ce9797ecc7e35739a14890893aa32a85b2159ceecc501959729f8bc2071543
7
+ data.tar.gz: 8580d4cf390cc8f15515e45f7354007bd3419bbbed0749ec9d0b574d52f96de4d8a8ec3966480d96a6c2e853a520964cb8e671b371407070d78d414f4c74c2a3
data/.standard.yml ADDED
@@ -0,0 +1,3 @@
1
+ # For available configuration options, see:
2
+ # https://github.com/testdouble/standard
3
+ ruby_version: 3.2
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0]
4
+
5
+ - Initial release
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2023 Aaron Patterson, Justin Searls
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,213 @@
1
+ # TLDR - for people who don't have time for slow tests
2
+
3
+ **tl;dr, this is a very nice test runner for Ruby that fails after 1.8 seconds**
4
+
5
+ We initially meant this as a joke [while
6
+ pairin'](https://www.youtube.com/live/bmi-SWeH4MA?si=p5g1j1FQZrbYEOCg&t=63), but
7
+ in addition to being funny, it was also a pretty good idea. So we fleshed out
8
+ `tldr` to be a full-featured, mostly
9
+ [Minitest-compatible](#minitest-compatibility), and downright pleasant test
10
+ framework for Ruby.
11
+
12
+ Some stuff you might like:
13
+
14
+ * A CLI that can run tests by line number(s) (e.g. `foo.rb:5 bar.rb:3:10`) and
15
+ by names or patterns (e.g. `--name test_fail,test_error --name "/_\d/"`)
16
+ * Everything is **parallel by default**, and seems pretty fast (you can disable with `--no-parallel`)
17
+ * Surprisingly delightful color diff output when two things fail to equal one another, care of [@mcmire's super_diff gem](https://github.com/mcmire/super_diff)
18
+ * By default, the CLI will prepend your most-recently-edited test file to the
19
+ front of your suite so its tests will run first. The tests you're working on are
20
+ the most likely you care about running, so TLDR runs them first (see the
21
+ `--prepend` option)
22
+ * And, of course, our signature feature: your test suite will never grow into
23
+ a glacially slow, soul-sucking albatross around your neck, because **after 1.8
24
+ seconds, it stops running your tests**, with a report on what it _was_ able to
25
+ run and where your slowest tests are
26
+
27
+ Some stuff you might _not_ like:
28
+
29
+ * The thought of switching Ruby test frameworks in 2023
30
+ * That bit about your test suite exploding after 1.8 seconds
31
+
32
+ ## Install
33
+
34
+ Either `gem install tldr` or add it to your Gemfile:
35
+
36
+ ```
37
+ gem "tldr"
38
+ ```
39
+
40
+ ## Usage
41
+
42
+ Here's what a test looks like:
43
+
44
+ ```ruby
45
+ class MathTest < TLDR
46
+ def test_adding
47
+ assert_equal 1 + 1, 2
48
+ end
49
+ end
50
+ ```
51
+
52
+ A TLDR subclass defines its tests with instance methods that begin with
53
+ `_test`. They can define `setup` and/or `teardown` methods which will run before
54
+ and after each test, respectively.
55
+
56
+ If you place your tests in `test/**/*_test.rb` (and/or `test/**/test_*.rb`)
57
+ files, the `tldr` executable will find them automatically. And if you define a
58
+ `test/helper.rb` file, it will be loaded prior to your tests.
59
+
60
+ Running the CLI is pretty straightforward:
61
+
62
+ ```
63
+ $ tldr
64
+ ```
65
+
66
+ You can, of course, also just run a specific test file or glob:
67
+
68
+ ```
69
+ $ tldr test/this/one/in/particular.rb
70
+ ```
71
+
72
+ Or specify the line numbers of tests to run by appending them after a `:`
73
+
74
+ ```
75
+ $ tldr test/fixture/line_number.rb:3:10
76
+ ```
77
+
78
+ And filter which tests run by name or pattern with one or more `--name` or `-n`
79
+ flags:
80
+
81
+ ```
82
+ $ tldr --name FooTest#test_foo -n test_bar,test_baz -n /_qux/
83
+ ```
84
+
85
+ (The above will translate to this array of name fiilters internally:
86
+ `["FooTest#test_foo", "test_bar", "test_baz", "/_qux/"]`.)
87
+
88
+ ### Running tests without the CLI
89
+
90
+ If you'd rather use TLDR by running Ruby files instead of the `tldr` CLI
91
+ (similar to `require "minitest/autorun"`), here's how to do it!
92
+
93
+ Given a file `test/some_test.rb`:
94
+
95
+ ```ruby
96
+ require "tldr"
97
+ TLDR::Run.at_exit! TLDR::Config.new(no_emoji: true)
98
+
99
+ class SomeTest < TLDR
100
+ def test_truth
101
+ assert true
102
+ end
103
+ end
104
+ ```
105
+
106
+ You could run the test with:
107
+
108
+ ```
109
+ $ ruby test/some_test.rb
110
+ ```
111
+
112
+ To maximize control and to avoid running code accidentally (and _unlike_ the
113
+ `tldr` CLI), running `at_exit!` will not set default values to the `paths`,
114
+ `helper`, `load_paths`, and `prepend_tests` config properties. You'll have to
115
+ pass any values you want to set on a [Config object](/lib/tldr/value/config.rb)
116
+ and pass it to `at_exit!`.
117
+
118
+ To avoid running multiple suites accidentally, if `TLDR::Run.at_exit!` is
119
+ encountered multiple times, only the first hook will be registered. If the
120
+ `tldr` CLI is running and encounters a call to `at_exit!`, it will be ignored.
121
+
122
+ #### Setting up the load path
123
+
124
+ When running TLDR from a Ruby script, one thing the framework can't help you with
125
+ is setting up load paths for you.
126
+
127
+ If you want to require code in `test/` or `lib/` without using
128
+ `require_relative`, you'll need to add those directories to the load path. You
129
+ can do this programmatically by prepending the path to `$LOAD_PATH`, like
130
+ this:
131
+
132
+ ```ruby
133
+ $LOAD_PATH.unshift "test"
134
+
135
+ require "tldr"
136
+ TLDR::Run.at_exit! TLDR::Config.new(no_emoji: true)
137
+
138
+ require "helper"
139
+ ```
140
+
141
+ Or by using Ruby's `-I` flag to include it:
142
+
143
+ ```
144
+ $ ruby -Itest test/some_test.rb
145
+ ```
146
+
147
+ ### Options
148
+
149
+ Here is the full list of CLI options:
150
+
151
+ ```
152
+ $ tldr --help
153
+ Usage: tldr [options] some_tests/**/*.rb some/path.rb:13 ...
154
+ --fail-fast Stop running tests as soon as one fails
155
+ -s, --seed SEED Seed for randomization
156
+ --[no-]parallel Parallelize tests (Default: true)
157
+ -n, --name PATTERN One or more names or /patterns/ of tests to run (like: foo_test, /test_foo.*/, Foo#foo_test)
158
+ --exclude-name PATTERN One or more names or /patterns/ NOT to run
159
+ --exclude-path PATH One or more paths NOT to run (like: foo.rb, "test/bar/**", baz.rb:3)
160
+ --helper HELPER Path to a test helper to load before any tests (Default: "test/helper.rb")
161
+ --no-helper Don't try loading a test helper before the tests
162
+ --prepend PATH Prepend one or more paths to run before the rest (Default: most recently modified test)
163
+ --no-prepend Don't prepend any tests before the rest of the suite
164
+ -l, --load-path PATH Add one or more paths to the $LOAD_PATH (Default: ["test"])
165
+ -r, --reporter REPORTER Set a custom reporter class (Default: "TLDR::Reporters::Default")
166
+ --base-path PATH Change the working directory for all relative paths (Default: current working directory)
167
+ --no-dotfile Disable loading .tldr.yml dotfile
168
+ --no-emoji Disable emoji in the output
169
+ -v, --verbose Print stack traces for errors
170
+ --comment COMMENT No-op comment, used internally for multi-line execution instructions
171
+ ```
172
+
173
+ After being parsed, all the CLI options are converted into a
174
+ [TLDR::Config](/lib/tldr/value/config.rb) object.
175
+
176
+ ### Setting defaults in .tldr.yml
177
+
178
+ The `tldr` CLI will look for a `.tldr.yml` file in your project root (your
179
+ working directory or whatever `--base-path` you set), which can contain values
180
+ for any properties on [TLDR::Config](/lib/tldr/value/config.rb) (with the
181
+ exception of `--base-path` itself).
182
+
183
+ Any values found in the dotfile will override TLDR's built-in values, but can
184
+ still be specified by the `tldr` CLI or a `TLDR::Config` object passed to
185
+ [TLDR::Run.at_exit!](#running-tests-without-the-cli).
186
+
187
+ Here's an [example project](/example/c) that specifies a `.tldr.yml` file as
188
+ well as some [internal tests](/tests/dotfile_test.rb) demonstrating its behavior.
189
+
190
+ ### Minitest compatibility
191
+
192
+ Tests you write with tldr are designed to be mostly-compatible with
193
+ [Minitest](https://github.com/minitest/minitest) tests. Some notes:
194
+
195
+ * `setup` and `teardown` hook methods should work as you expect
196
+ * All of Minitest's assertions (e.g. `assert`, `assert_equals`) are provided,
197
+ with these caveats:
198
+ * To retain the `expected, actual` argument ordering, `tldr` defines
199
+ `assert_include?(element, container)` instead of
200
+ `assert_includes(container, element)`
201
+ * If you want to maximize compatibility and mix in `assert_includes` and the
202
+ deprecated `assert_send`, just `include
203
+ TLDR::Assertions::MinitestCompatibility` into the `TLDR` base class or
204
+ individual test classes
205
+
206
+ ### How will I run all my tests in CI without the time bomb going off?
207
+
208
+ TLDR will run all your tests in CI without the time bomb going off.
209
+
210
+ ## Acknowledgements
211
+
212
+ Thanks to [George Sheppard](https://github.com/fuzzmonkey) for freeing up the
213
+ [tldr gem name](https://rubygems.org/gems/tldr)!
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rake/testtask"
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << "tests"
8
+ t.libs << "lib"
9
+ t.test_files = FileList["tests/**/*_test.rb"]
10
+ end
11
+
12
+ require "standard/rake"
13
+
14
+ task default: %i[test standard:fix]
data/exe/tldr ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "tldr"
4
+
5
+ TLDR::Run.cli(ARGV)
@@ -0,0 +1,94 @@
1
+ require "optparse"
2
+
3
+ class TLDR
4
+ class ArgvParser
5
+ PATTERN_FRIENDLY_SPLITTER = /,(?=(?:[^\/]*\/[^\/]*\/)*[^\/]*$)/
6
+
7
+ def parse(args)
8
+ options = {
9
+ cli_mode: true
10
+ }
11
+
12
+ OptionParser.new do |opts|
13
+ opts.banner = "Usage: tldr [options] some_tests/**/*.rb some/path.rb:13 ..."
14
+
15
+ opts.on CONFLAGS[:fail_fast], "Stop running tests as soon as one fails" do |fail_fast|
16
+ options[:fail_fast] = fail_fast
17
+ end
18
+
19
+ opts.on "-s", "#{CONFLAGS[:seed]} SEED", Integer, "Seed for randomization" do |seed|
20
+ options[:seed] = seed
21
+ end
22
+
23
+ opts.on CONFLAGS[:parallel], "Parallelize tests (Default: true)" do |parallel|
24
+ options[:parallel] = parallel
25
+ end
26
+
27
+ opts.on "-n", "#{CONFLAGS[:names]} PATTERN", "One or more names or /patterns/ of tests to run (like: foo_test, /test_foo.*/, Foo#foo_test)" do |name|
28
+ options[:names] ||= []
29
+ options[:names] += name.split PATTERN_FRIENDLY_SPLITTER
30
+ end
31
+
32
+ opts.on "#{CONFLAGS[:exclude_names]} PATTERN", "One or more names or /patterns/ NOT to run" do |exclude_name|
33
+ options[:exclude_names] ||= []
34
+ options[:exclude_names] += exclude_name.split PATTERN_FRIENDLY_SPLITTER
35
+ end
36
+
37
+ opts.on "#{CONFLAGS[:exclude_paths]} PATH", Array, "One or more paths NOT to run (like: foo.rb, \"test/bar/**\", baz.rb:3)" do |path|
38
+ options[:exclude_paths] ||= []
39
+ options[:exclude_paths] += path
40
+ end
41
+
42
+ opts.on "#{CONFLAGS[:helper]} HELPER", String, "Path to a test helper to load before any tests (Default: \"test/helper.rb\")" do |helper|
43
+ options[:helper] = helper
44
+ end
45
+
46
+ opts.on CONFLAGS[:no_helper], "Don't try loading a test helper before the tests" do
47
+ options[:no_helper] = true
48
+ end
49
+
50
+ opts.on "#{CONFLAGS[:prepend_tests]} PATH", Array, "Prepend one or more paths to run before the rest (Default: most recently modified test)" do |prepend|
51
+ options[:prepend_tests] ||= []
52
+ options[:prepend_tests] += prepend
53
+ end
54
+
55
+ opts.on CONFLAGS[:no_prepend], "Don't prepend any tests before the rest of the suite" do
56
+ options[:no_prepend] = true
57
+ end
58
+
59
+ opts.on "-l", "#{CONFLAGS[:load_paths]} PATH", Array, "Add one or more paths to the $LOAD_PATH (Default: [\"test\"])" do |load_path|
60
+ options[:load_paths] ||= []
61
+ options[:load_paths] += load_path
62
+ end
63
+
64
+ opts.on "-r", "#{CONFLAGS[:reporter]} REPORTER", String, "Set a custom reporter class (Default: \"TLDR::Reporters::Default\")" do |reporter|
65
+ options[:reporter] = Kernel.const_get(reporter)
66
+ end
67
+
68
+ opts.on "#{CONFLAGS[:base_path]} PATH", String, "Change the working directory for all relative paths (Default: current working directory)" do |path|
69
+ options[:base_path] = path
70
+ end
71
+
72
+ opts.on CONFLAGS[:no_dotfile], "Disable loading .tldr.yml dotfile" do
73
+ options[:no_dotfile] = true
74
+ end
75
+
76
+ opts.on CONFLAGS[:no_emoji], "Disable emoji in the output" do
77
+ options[:no_emoji] = true
78
+ end
79
+
80
+ opts.on "-v", CONFLAGS[:verbose], "Print stack traces for errors" do |verbose|
81
+ options[:verbose] = verbose
82
+ end
83
+
84
+ opts.on "--comment COMMENT", String, "No-op comment, used internally for multi-line execution instructions" do
85
+ # See "--comment" in lib/tldr/reporters/default.rb for an example of how this is used internally
86
+ end
87
+ end.parse!(args)
88
+
89
+ options[:paths] = args if args.any?
90
+
91
+ Config.new(**options)
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,38 @@
1
+ # These methods are provided only for drop-in compatibility with Minitest:
2
+ #
3
+ # require "tldr/assertions/minitest"
4
+ #
5
+ # Will load these methods for use in your tests
6
+ #
7
+ # While all the methods in this file were written for TLDR, they were designed
8
+ # to maximize compatibility with minitest's assertions API and messages here:
9
+ #
10
+ # https://github.com/minitest/minitest/blob/master/lib/minitest/assertions.rb
11
+ #
12
+ # As a result, many implementations are extremely similar to those found in
13
+ # minitest. Any such implementations are Copyright © Ryan Davis, seattle.rb and
14
+ # distributed under the MIT License
15
+
16
+ class TLDR
17
+ module Assertions
18
+ module MinitestCompatibility
19
+ def assert_includes actual, expected, message = nil
20
+ assert_include? expected, actual, message
21
+ end
22
+
23
+ def refute_includes actual, expected, message = nil
24
+ refute_include? expected, actual, message
25
+ end
26
+
27
+ def assert_send receiver_method_args, message = nil
28
+ warn "DEPRECATED: assert_send. From #{TLDR.filter_backtrace(caller).first}"
29
+ receiver, method, *args = receiver_method_args
30
+ message = Assertions.msg(message) {
31
+ "Expected #{Assertions.h(receiver)}.#{method}(*#{Assertions.h(args)}) to return true"
32
+ }
33
+
34
+ assert receiver.__send__(method, *args), message
35
+ end
36
+ end
37
+ end
38
+ end