{"id":13411537,"url":"https://github.com/tendersearls/tldr","last_synced_at":"2025-03-14T17:30:57.348Z","repository":{"id":195236917,"uuid":"692503199","full_name":"tendersearls/tldr","owner":"tendersearls","description":"A Ruby test framework for people who don't have time for slow tests 💣💥","archived":false,"fork":false,"pushed_at":"2024-01-11T18:21:45.000Z","size":770,"stargazers_count":252,"open_issues_count":2,"forks_count":4,"subscribers_count":6,"default_branch":"main","last_synced_at":"2024-10-02T00:18:18.059Z","etag":null,"topics":["assertions","tdd","test-runner","testing"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tendersearls.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-16T17:17:36.000Z","updated_at":"2024-10-01T15:53:59.000Z","dependencies_parsed_at":"2023-12-25T21:26:37.916Z","dependency_job_id":"e25d2648-9911-42ea-9844-1e1becc44e60","html_url":"https://github.com/tendersearls/tldr","commit_stats":null,"previous_names":["tenderlove/tldr"],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tendersearls%2Ftldr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tendersearls%2Ftldr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tendersearls%2Ftldr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tendersearls%2Ftldr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tendersearls","download_url":"https://codeload.github.com/tendersearls/tldr/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243618635,"owners_count":20320269,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["assertions","tdd","test-runner","testing"],"created_at":"2024-07-30T20:01:14.344Z","updated_at":"2025-03-14T17:30:56.563Z","avatar_url":"https://github.com/tendersearls.png","language":"Ruby","funding_links":[],"categories":["testing","Ruby"],"sub_categories":[],"readme":"# TLDR - for people who don't have time for slow tests\n\nOkay, you might need to sit down for this:\n\n**tl;dr, TLDR is a Ruby test framework that stops running your tests after 1.8 seconds.**\n\nWe initially meant this as a joke [while\npairin'](https://www.youtube.com/live/bmi-SWeH4MA?si=p5g1j1FQZrbYEOCg\u0026t=63), but\nin addition to being funny, it was also a pretty good idea. So we fleshed out\n`tldr` to be a full-featured, mostly\n[Minitest-compatible](#minitest-compatibility), and dare-we-say pleasant test\nframework for Ruby.\n\nThe \"big idea\" here is TLDR is designed for users to run the `tldr` command\nrepeatedly as they work—as opposed to only running the tests for whatever is\nbeing worked on. Even if the suite runs over the 1.8 second time limit. Because\nTLDR shuffles and runs in parallel and is guaranteed to take less than two\nseconds,\n**you'll actually wind up running _all_ of your tests quite often as you work**,\ncatching any problems much earlier than if you had waited until the end of the\nday to push your work and let a continuous integration server run the full\nsuite.\n\nSome stuff you might like:\n\n* A CLI that can specify tests by line number(s) (e.g. `foo.rb:5 bar.rb:3:10`)\nand by names or patterns (e.g. `--name test_fail,test_error --name \"/_\\d/\"`)\n* Everything is **parallel by default**, and seems pretty darn fast; TLDR\nalso 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)\n* Surprisingly delightful color diff output when two things fail to equal one\nanother, care of [@mcmire's super_diff gem](https://github.com/mcmire/super_diff)\n* By default, the CLI will prepend your most-recently-edited test file to the\nfront of your suite so its tests will run first. The test you worked on most recently\nis the one you most likely want to ensure runs, so TLDR runs it first (see the\n`--prepend` option for how to control this behavior)\n* And, of course, our signature feature: your test suite will never grow into\na glacially slow, soul-sucking albatross around your neck, because **after 1.8\nseconds, it stops running your tests**, with a report on what it _was_ able to\nrun and where your slowest tests are\n\nSome stuff you might _not_ like:\n\n* The thought of switching Ruby test frameworks in 2023\n* That bit about your test suite exploding after 1.8 seconds\n\n## Install\n\nEither `gem install tldr` or add it to your Gemfile:\n\n```\ngem \"tldr\"\n```\n\n## Usage\n\nHere's what a test looks like:\n\n```ruby\nclass MathTest \u003c TLDR\n  def test_adding\n    assert_equal 1 + 1, 2\n  end\nend\n```\n\nA TLDR subclass defines its tests with instance methods that begin with\n`test_`. They can define `setup` and/or `teardown` methods which will run before\nand after each test, respectively.\n\nIf you place your tests in `test/**/*_test.rb` (and/or `test/**/test_*.rb`)\nfiles, the `tldr` executable will find them automatically.  And if you define a\n`test/helper.rb` file, it will be loaded prior to your tests.\n\nRunning the CLI is pretty straightforward:\n\n```\n$ tldr\n```\n\nYou can, of course, also just run a specific test file or glob:\n\n```\n$ tldr test/this/one/in/particular.rb\n```\n\nOr specify the line numbers of tests to run by appending them after a `:`\n\n```\n$ tldr test/fixture/line_number.rb:3:10\n```\n\nAnd filter which tests run by name or pattern with one or more `--name` or `-n`\nflags:\n\n```\n$ tldr --name FooTest#test_foo -n test_bar,test_baz -n /_qux/\n```\n\n(The above will translate to this array of name filters internally:\n `[\"FooTest#test_foo\", \"test_bar\", \"test_baz\", \"/_qux/\"]`.)\n\n### Options\n\nHere is the full list of CLI options:\n\n```\n$ tldr --help\nUsage: tldr [options] some_tests/**/*.rb some/path.rb:13 ...\n        --fail-fast                  Stop running tests as soon as one fails\n    -s, --seed SEED                  Seed for randomization\n        --[no-]parallel              Parallelize tests (Default: true)\n    -n, --name PATTERN               One or more names or /patterns/ of tests to run (like: foo_test, /test_foo.*/, Foo#foo_test)\n        --exclude-name PATTERN       One or more names or /patterns/ NOT to run\n        --exclude-path PATH          One or more paths NOT to run (like: foo.rb, \"test/bar/**\", baz.rb:3)\n        --helper PATH                One or more paths to a helper that is required before any tests (Default: \"test/helper.rb\")\n        --no-helper                  Don't require any test helpers\n        --prepend PATH               Prepend one or more paths to run before the rest (Default: most recently modified test)\n        --no-prepend                 Don't prepend any tests before the rest of the suite\n    -l, --load-path PATH             Add one or more paths to the $LOAD_PATH (Default: [\"lib\", \"test\"])\n    -r, --reporter REPORTER          Set a custom reporter class (Default: \"TLDR::Reporters::Default\")\n        --base-path PATH             Change the working directory for all relative paths (Default: current working directory)\n        --no-dotfile                 Disable loading .tldr.yml dotfile\n        --no-emoji                   Disable emoji in the output\n    -v, --verbose                    Print stack traces for errors\n        --print-interrupted-test-backtraces\n                                     Print stack traces for interrupted tests\n        --[no-]warnings              Print Ruby warnings (Default: true)\n        --watch                      Run your tests continuously on file save (requires 'fswatch' to be installed)\n        --yes-i-know                 Suppress TLDR report when suite runs over 1.8s\n        --i-am-being-watched         [INTERNAL] Signals to tldr it is being invoked under --watch mode\n        --comment COMMENT            [INTERNAL] No-op; used for multi-line execution instructions\n```\n\nAfter being parsed, all the CLI options are converted into a\n[TLDR::Config](/lib/tldr/value/config.rb) object.\n\n### Setting defaults in .tldr.yml\n\nThe `tldr` CLI will look for a `.tldr.yml` file in your project root (your\nworking directory or whatever `--base-path` you set), which can contain values\nfor any properties on [TLDR::Config](/lib/tldr/value/config.rb) (with the\nexception of `--base-path` itself).\n\nAny values found in the dotfile will override TLDR's built-in values, but can\nstill be specified by the `tldr` CLI or a `TLDR::Config` object passed to\n[TLDR::Run.at_exit!](#running-tests-without-the-cli).\n\nHere's an [example project](/example/c) that specifies a `.tldr.yml` file as\nwell as some [internal tests](/tests/dotfile_test.rb) demonstrating its behavior.\n\n### Minitest compatibility\n\nTests you write with tldr are designed to be mostly-compatible with\n[Minitest](https://github.com/minitest/minitest) tests. Some notes:\n\n* `setup` and `teardown` hook methods should work as you expect. (We even threw\nin [an `around` hook](https://github.com/splattael/minitest-around) as a bonus!)\n* All of Minitest's assertions (e.g. `assert`, `assert_equals`) are provided,\nwith these caveats:\n  * To retain the `expected, actual` argument ordering, `tldr` defines\n  `assert_include?(element, container)` instead of\n  `assert_includes(container, element)`\n  * If you want to maximize compatibility and mix in `assert_includes` and the\n  deprecated `assert_send`, just `include\n  TLDR::Assertions::MinitestCompatibility` into the `TLDR` base class or\n  individual test classesJust set it\n\n### Running tests continuously with --watch\n\nThe `tldr` CLI includes a `--watch` option which will watch for changes in any\nof the configured load paths (`[\"test\", \"lib\"]` by default) and then execute\nyour tests each time a file is changed. To keep the output up-to-date and easy\nto scan, it will also clear your console before each run.\n\nNote that this feature requires you have\n[fswatch](https://github.com/emcrisostomo/fswatch) installed and on your `PATH`\n\nHere's what that might look like:\n\n![tldr-watch](https://github.com/tendersearls/tldr/assets/79303/364f0e52-5596-49ce-a470-5eaeddd11f03)\n\n### Running TLDR with Rake\n\nTLDR ships with a [very](lib/tldr/rake.rb) minimal rake task that simply shells\nout to the `tldr` CLI. If you want to run TLDR with Rake, you can configure\nthe test run by setting flags on an env var named `TLDR_OPTS` or else in\nthe [.tldr.yml](#setting-defaults-in-tldryml).\n\nHere's an example Rakefile:\n\n```ruby\nrequire \"standard/rake\"\nrequire \"tldr/rake\"\n\ntask default: [:tldr, \"standard:fix\"]\n```\n\nYou could then run the task with:\n\n```\n$ TLDR_OPTS=\"--no-parallel\" bundle exec rake tldr\n```\n\nOne reason you'd want to invoke TLDR with Rake is because you have multiple\ntest suites that you want to be able to conveniently run separately ([this\ntalk](https://blog.testdouble.com/talks/2014-05-25-breaking-up-with-your-test-suite/)\ndiscussed a few reasons why this can be useful).\n\nTo create a custom TLDR Rake test, just instantiate `TLDR::Task` like this:\n\n```ruby\nrequire \"tldr/rake\"\n\nTLDR::Task.new(name: :safe_tests, config: TLDR::Config.new(\n  paths: FileList[\"safe/**/*_test.rb\"],\n  helper_paths: [\"safe/helper.rb\"],\n  load_paths: [\"lib\", \"safe\"]\n))\n```\n\nThe above will create a second Rake task named `safe_tests` running a different\nset of tests than the default `tldr` task. Here's [an\nexample](/example/b/Rakefile).\n\n### Running tests without the CLI\n\nIf you'd rather use TLDR by running Ruby files instead of the `tldr` CLI\n(similar to `require \"minitest/autorun\"`), here's how to do it!\n\nGiven a file `test/some_test.rb`:\n\n```ruby\nrequire \"tldr\"\nTLDR::Run.at_exit! TLDR::Config.new(no_emoji: true)\n\nclass SomeTest \u003c TLDR\n  def test_truth\n    assert true\n  end\nend\n```\n\nYou could run the test with:\n\n```\n$ ruby test/some_test.rb\n```\n\nTo maximize control and to avoid running code accidentally (and _unlike_ the\n`tldr` CLI), running `at_exit!` will not set default values to the `paths`,\n`helper`, `load_paths`, and `prepend_paths` config properties. You'll have to\npass any values you want to set on a [Config object](/lib/tldr/value/config.rb)\nand pass it to `at_exit!`.\n\nTo avoid running multiple suites accidentally, if `TLDR::Run.at_exit!` is\nencountered multiple times, only the first hook will be registered. If the\n`tldr` CLI is running and encounters a call to `at_exit!`, it will be ignored.\n\n#### Setting up the load path\n\nBy default, the `tldr` CLI adds `test` and `lib` directories to the load path\nfor you, but when running TLDR from a Ruby script, it doesn't set those up for\nyou.\n\nIf you want to require code in `test/` or `lib/` without using\n`require_relative`, you'll need to add those directories to the load path. You\ncan do this programmatically by prepending the path to `$LOAD_PATH`, like\nthis:\n\n```ruby\n$LOAD_PATH.unshift \"test\"\n\nrequire \"tldr\"\nTLDR::Run.at_exit! TLDR::Config.new(no_emoji: true)\n\nrequire \"helper\"\n```\n\nOr by using Ruby's `-I` flag to include it:\n\n```\n$ ruby -Itest test/some_test.rb\n```\n\n## Questions you might be asking\n\nTLDR is very similar to Minitest in API, but different in enough ways that you\nprobably have some questions.\n\n### Parallel-by-default is nice in theory but half my tests are failing. Wat?\n\n**Read this before you add `--no-parallel` because some tests are failing when\nyou run `tldr`.**\n\nThe vast majority of test suites in the wild are not parallelized and the vast\nmajority of _those_ will only parallelize by forking processes as opposed to\nusing a thread pool. We wanted to encourage more people to save time (after all,\nyou only get 1.8 seconds here) by making your test suite run as fast as it can,\nso your tests run in parallel threads by default.\n\nIf you're writing new code and tests with TLDR and dutifully running `tldr`\nconstantly for fast feedback, odds are that this will help you catch thread\nsafety issues early—this is a good thing, because it gives you a chance to\naddress them before they're too hard to fix! But maybe you're porting an\nexisting test suite to TLDR and running in parallel for the first time, or maybe\nyou need to test something that simply _can't_ be exercised in a thread-safe\nway. For those cases, TLDR's goal is to give you some tools to prevent you from\ngiving up and adding `--no-parallel` to your entire test suite and **slowing\neverything down for the sake of a few tests**.\n\nSo, when you see a test that is failing when run in parallel with the rest of your\nsuite, here is what we recommend doing, in priority order:\n\n1. Figure out a way to redesign the test (or the code under test) to be\nthread-safe.  Modern versions of Ruby provide a number of tools to make this\neasier than it used to be, and it may be as simple as making an instance\nvariable thread-local\n2. If the problem is that a subset of your tests depend on the same resource,\ntry using [TLDR.run_these_together!](lib/tldr/parallel_controls.rb) class to\ngroup the tests together. This will ensure that those tests run in the same\nthread in sequence (here's a [simple\nexample](/tests/fixture/run_these_together.rb))\n3. For tests that affect process-wide resources like setting the system clock or\nchanging the process's working directory (i.e. `Dir.chdir`), you can sequester\nthem to run sequentially _after_ all parallel tests in your suite have run with\n[TLDR.dont_run_these_in_parallel!](lib/tldr/parallel_controls.rb), which takes\nthe same arguments as `run_these_together!`\n([example](/tests/fixture/dont_run_these_in_parallel.rb))\n4. Give up and make the whole suite `--no-parallel`. If you find that you need\nto resort to this, you might save some keystrokes by adding `parallel: false` in\na [.tldr.yml](#setting-defaults-in-tldryml) file\n\nWe have a couple other ideas of ways to incorporate non-thread-safe tests into\nyour suite without slowing down the rest of your tests, so stay tuned!\n\n### How will I run all my tests in CI without the time bomb going off?\n\nTLDR will run all your tests in CI without the time bomb going off. If\n`tldr` is run in a non-interactive shell and a `CI` environment variable is set\n(as it is on virtually every CI service), then the bomb will be defused.\n\n### What if I already have another `tldr` executable on my path?\n\nThere's a [command-line utility named tldr](https://tldr.sh) that might conflict\nwith this gem's binary in your PATH. If that's the case you could change your\npath, invoke `bundle exec tldr`, run [with Rake](#running-tldr-with-rake), or\nuse the `tldt` (\"too long; didn't test\") executable alias that ships with this\ngem.\n\n### Is there a plugin system?\n\nThere is not.\n\nCurrently, the only pluggable aspect of TLDR are reporters, which can be set\nwith the `--reporter` command line option. It can be set to any fully-qualified\nclass name that extends from\n[TLDR::Reporters::Base](/lib/tldr/reporters/base.rb).\n\n### I know my tests are over 1.8s, how do I suppress the huge output?\n\nPlenty of test suites are over 1.8s and having TLDR repeatedly print out the\nhuge summary at the end of each test run can be distracting and make it harder\nto spot test failures. If you know your test suite is too slow, you can simply\nadd the `--yes-i-know` flag\n\n### What about mocking?\n\nTLDR is laser-focused on running tests, so it doesn't provide a built-in mocking\nfacility. Might we interest you in a refreshing\n[mocktail](https://github.com/testdouble/mocktail), instead?\n\n## Contributing to TLDR\n\nIf you want to submit PRs on this repo, please know that the code style is\n[Kirkland-style Ruby](https://mastodon.social/@searls/111137666157318482), where\nmethod definitions have parentheses omitted but parentheses are generally\nexpected for method invocations.\n\n## Acknowledgements\n\nThanks to [George Sheppard](https://github.com/fuzzmonkey) for freeing up the\n[tldr gem name](https://rubygems.org/gems/tldr)!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftendersearls%2Ftldr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftendersearls%2Ftldr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftendersearls%2Ftldr/lists"}