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 +7 -0
- data/.standard.yml +3 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +213 -0
- data/Rakefile +14 -0
- data/exe/tldr +5 -0
- data/lib/tldr/argv_parser.rb +94 -0
- data/lib/tldr/assertions/minitest_compatibility.rb +38 -0
- data/lib/tldr/assertions.rb +365 -0
- data/lib/tldr/backtrace_filter.rb +44 -0
- data/lib/tldr/error.rb +7 -0
- data/lib/tldr/planner.rb +170 -0
- data/lib/tldr/reporters/base.rb +36 -0
- data/lib/tldr/reporters/default.rb +167 -0
- data/lib/tldr/reporters/icon_provider.rb +93 -0
- data/lib/tldr/reporters.rb +4 -0
- data/lib/tldr/runner.rb +113 -0
- data/lib/tldr/skippable.rb +7 -0
- data/lib/tldr/sorbet_compatibility.rb +9 -0
- data/lib/tldr/value/config.rb +217 -0
- data/lib/tldr/value/location.rb +15 -0
- data/lib/tldr/value/plan.rb +3 -0
- data/lib/tldr/value/test.rb +23 -0
- data/lib/tldr/value/test_result.rb +62 -0
- data/lib/tldr/value/wip_test.rb +3 -0
- data/lib/tldr/value.rb +6 -0
- data/lib/tldr/version.rb +3 -0
- data/lib/tldr.rb +41 -0
- data/script/parse +6 -0
- data/script/run +6 -0
- data/script/test +25 -0
- metadata +108 -0
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
data/CHANGELOG.md
ADDED
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,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
|