{"id":25056378,"url":"https://github.com/clojusc/ltest","last_synced_at":"2026-04-02T02:53:24.359Z","repository":{"id":62431629,"uuid":"94098324","full_name":"clojusc/ltest","owner":"clojusc","description":"A custom test runner for clojure.test with detailed, coloured output and summaries","archived":false,"fork":false,"pushed_at":"2020-06-01T20:53:05.000Z","size":1100,"stargazers_count":7,"open_issues_count":8,"forks_count":4,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-09T09:18:11.446Z","etag":null,"topics":["ansi-colors","clojure","terminal","test-runner","testing","tests"],"latest_commit_sha":null,"homepage":null,"language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/clojusc.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-06-12T13:18:32.000Z","updated_at":"2023-12-19T17:40:30.000Z","dependencies_parsed_at":"2022-11-01T21:00:48.606Z","dependency_job_id":null,"html_url":"https://github.com/clojusc/ltest","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clojusc%2Fltest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clojusc%2Fltest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clojusc%2Fltest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/clojusc%2Fltest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/clojusc","download_url":"https://codeload.github.com/clojusc/ltest/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248872045,"owners_count":21175340,"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":["ansi-colors","clojure","terminal","test-runner","testing","tests"],"created_at":"2025-02-06T13:23:33.201Z","updated_at":"2026-04-02T02:53:24.297Z","avatar_url":"https://github.com/clojusc.png","language":"Clojure","readme":"# ltest\n\n[![Build Status][travis-badge]][travis]\n[![Dependencies Status][deps-badge]][deps]\n[![Clojars Project][clojars-badge]][clojars]\n[![Tag][tag-badge]][tag]\n[![JDK version][jdk-v]](.travis.yml)\n[![Clojure version][clojure-v]](project.clj)\n\n[![][logo]][logo-large]\n\n*A custom test runner for clojure.test with detailed, coloured output and summaries*\n\n\n#### Contents\n\n* [About](#about-)\n* [Feature List](#feature-list-)\n* [Usage](#usage-)\n  * [lein Plugin](#lein-plugin-)\n  * [Function Calls](#function-calls-)\n    * [Running Multiple Tests](#running-multiple-tests-)\n    * [Running One Test](#running-one-test-)\n    * [Running a Suite](#running-a-suite-)\n    * [Running Multiple Suites](#running-multiple-suites-)\n  * [Creating a Test Runner](#creating-a-test-runner-)\n    * [Tagging Test Namespaces](#tagging-test-namespaces-)\n    * [A runner Namespace](#a-runner-namespace-)\n    * [Adding a lein Alias](#adding-a-lein-alias-)\n    * [Running without ltest](#running-without-ltest-)\n* [License](#license-)\n\n\n## About [\u0026#x219F;](#contents)\n\nThis project started as a complaint (a numbered list of them) on a Slack\nchannel about the default test runner for `clojure.test`. Most of these\nrelating to the fact that there's not quite enough information presented to\nmaximally assist in debugging ... that one often has to piece things together.\nThanks to [@chris-durbin][chris-durbin], who urged an implementation follow-up\nto make things better, ltest for Clojure is now a thing.\n\nThe Clojure ltest test runner was inspired by the\n[LFE ltest runner][lfe-test-runner], whence it got its name.\n\nThe ltest library is currently being used in the NASA Earthdata\n[CMR project][cmr] as a supplementary development/testing tool, and in the\n[CMR Client][cmr-client] library.\n\n\n## Feature List [\u0026#x219F;](#contents)\n\nThe basic needs ltest aims to resolve (admittedly important for only a subset of\ndevelopers) are the following:\n\n* a detailed and explicit reporting-while-testing on what's getting tested\n  * \u0026#x2705; namespace\n  * \u0026#x2705; function\n  * \u0026#x2705; assertion\n  * text of `(testing ...)` call (see\n    [ticket #11](https://github.com/clojusc/ltest/issues/11))\n* \u0026#x2705; explicit test status for each assertion (`OK`, `FAIL`, `ERROR`)\n* a separation of reporting-while-testing and failure/error details\n  * \u0026#x2705; the running status of tests should be kept visually clean\n  * \u0026#x2705; failures and errors should be grouped separately\n  * \u0026#x2705; failure and error reporting should be done at the end, after the\n    summary, in their own sections\n  * suites should hold off until all suites have finished before reporting\n    (see [ticket #12](https://github.com/clojusc/ltest/issues/12))\n* \u0026#x2705; failure and error reporting should include the full namespace +\n  function of where the issue occurred for easier viewing/copying+pasting\n* \u0026#x2705; different status output, sections, etc., should use ANSI terminal\n  colors to assist with quick and easy identification of issues, data, etc.\n* \u0026#x2705; tests should be ordered alphabetically\n* \u0026#x2705; users/developers should have the ability to form arbitrary high-level\n  divisions of tests\n  * \u0026#x2705; useful for running unit tests and integration tests together\n  * \u0026#x2705; called \"suites\" in ltest\n  * an opinionated default grouping for suites should be offered\n    * \u0026#x2705; by default, group by the top two elements of a namespace (e.g.,\n      `a.b.c.d` and `a.b.e.f` would both be grouped in `a.b`)\n    * developers should have the ability to override this easily (see\n      [ticket #25](https://github.com/clojusc/ltest/issues/25))\n\n\n## Usage [\u0026#x219F;](#contents)\n\nThe functionality provided by this library may be used in several ways:\n\n* As a tool (set of functions) from a development REPL\n* As a utility library for creating a test runner for your project\n* As the basis for a `lein` plugin (not yet created; see ticket\n  [#10](https://github.com/clojusc/ltest/issues/10))\n\nThe first two are discussed below. In both cases, the ltest library is\nutilized solely through its primary namespace, e.g.:\n\n```clj\n(require '[ltest.core :as ltest])\n```\n\n### `lein` Plugin [\u0026#x219F;](#contents)\n\nThe simplest way to use ltest is with the `lein` plugin. The latest version is\nhere:\n\n[![Clojars Project for the lein plugin][clojars-lein-badge]][clojars-lein]\n\nAdd this to your project as a `lein` plugin, e.g.:\n\n```\n...\n:plugins [[lein-ltest \"x.y.z\"]]\n...\n```\n\nAnd then run your tests with the following:\n\n```bash\n$ lein ltest\n```\n\n\n### Function Calls [\u0026#x219F;](#contents)\n\n\n#### Running Multiple Tests [\u0026#x219F;](#contents)\n\nCollections of tests may be run with the `(ltest/run-tests)` function. The\nfollowing example passing just one test namespace, but any number may be\npassed as additional arguments:\n\n```clj\n(ltest/run-tests ['ltest.group1.samples.sample1])\n```\n\nHere's is a screenshot of this call's result in the ltest dev environment\n(click for a larger view):\n\n[![][screen1-thumb]][screen1]\n\nNote that this includes, in order:\n* summary results\n* failure listings\n* error listings\n\n\n#### Running One Test [\u0026#x219F;](#contents)\n\nA similar approach with analagous reporting is available for running single\ntests, but instead of a namespace, a namespace-qualified test function (as\nvar) is passed:\n\n```clj\n(ltest/run-test #'ltest.group1.samples.sample2/multiple-pass-test)\n```\n\nScreenshot:\n\n[![][screen2-thumb]][screen2]\n\n\n#### Running a Suite [\u0026#x219F;](#contents)\n\nIn ltest, test suites are aribitrary named groupings of tests. As with\n`run-tests`, any number of namespaces my be provided in the `:nss` vector:\n\n```clj\n(ltest/run-suite {:name \"Simple Suite\"\n                  :nss ['ltest.group1.samples.sample2]})\n```\n\nScreenshot:\n\n[![][screen3-thumb]][screen3]\n\n\n#### Running Multiple Suites [\u0026#x219F;](#contents)\n\nYou can also define multiple suites and run them together (useful for unit and\nintegration tests):\n\n```clj\n(def suite-1\n  {:name \"Arbitrary Division 1\"\n   :nss ['nogroup\n         'ltest.group1.samples.sample0\n         'ltest.group1.samples.sample1]})\n\n(def suite-2\n  {:name \"Arbitrary Division 2\"\n   :nss [:ltest.group1.samples.sample2\n         \"ltest.group1.samples.sample3\"\n         'ltest.group2.samples.sample4\n         'ltest.group2.samples.sample5\n         'ltest.group2.samples.sample6\n         'ltest.group2.samples.sample7]})\n\n(def suites\n  [suite-1 suite-2])\n\n(ltest/run-suites suites)\n```\n\nScreenshot:\n\n[![][screen4-thumb]][screen4]\n\n\n### Creating a Test Runner [\u0026#x219F;](#contents)\n\nThe [CMR client library][cmr-client] has opted to use ltest to build a quick\ntest runner that can be executed from the command line, via a `lein` alias.\nThis is really just a workaround until ltest has an official `lein` plugin.\n\nThe steps for creating a test runner are given in the following sub-sections.\n\n\n#### Tagging Test Namespaces [\u0026#x219F;](#contents)\n\nFor all namespaces you want to qualify as containing unit tests, simply update\nthe namespace for the given file, e.g.,\n\nfrom this:\n\n```clj\n(ns ur.proj.tests.util\n  ...)\n```\n\nto this:\n\n```clj\n(ns :unit ur.proj.tests.util\n  ...)\n```\n\nLikewse for integration and system tests:\n\n```clj\n(ns :integration ur.proj.tests.server\n  ...)\n```\n\n```clj\n(ns :system ur.proj.tests.services\n  ...)\n```\n\n\n#### A `runner` Namespace [\u0026#x219F;](#contents)\n\nIn this particular runner, the \"suite\" functionality of ltest is not taken\nadvantage of; instead, our example runner below relies upon metadata tags in\nthe test namespaces we've made. Note that the `ltest/run-*-tests` functions are\nconveniences provided by ltest; if you should want to tag your tests in any\nother arbitrary manner, creating convenience functions for your tags (e.g., to\nbe used by the test runner) is very easy (see the `ltest.core` source for\nhints).\n\nHere is a sample runner namespace, intended to be called from the command line:\n\n```clj\n(ns ur.proj.testing.runner\n  (:require\n   [cmr.client.tests]\n   [ltest.core :as ltest])\n  (:gen-class))\n\n(def tests-regex #\"ur\\.proj\\.tests\\..*\")\n\n(defn run-tests\n  []\n  (ltest/run-all-tests tests-regex))\n\n(defn print-header\n  []\n  (println)\n  (println (apply str (repeat 80 \"=\")))\n  (println \"Your Project Test Runner\")\n  (println (apply str (repeat 80 \"=\")))\n  (println))\n\n(defn -main\n  \"This can be run from `lein` in the following ways:\n  * `lein run-tests`\n  * `lein run-tests unit`\n  * `lein run-tests integration`\n  * `lein run-tests system`\"\n  [\u0026 args]\n  (print-header)\n  (case (keyword (first args))\n    :unit (ltest/run-unit-tests tests-regex)\n    :integration (ltest/run-integration-tests tests-regex)\n    :system (ltest/run-system-tests tests-regex)\n    (run-tests)))\n```\n\n\n#### Adding a `lein` Alias [\u0026#x219F;](#contents)\n\nLet's add an alias to easily execute our test runner from the command\nline. In your `project.clj` file, add a new section (if you don't already\nhave it) siblimg to the `:profiles` or `:dependencies` sections.\n\n```clj\n  ...\n  :aliases {\n    ...\n    \"run-tests\"\n      ^{:doc \"Use the ltest runner for verbose, colourful test output\"}\n      [\"with-profile\" \"+test\" \"run\" \"-m\" \"ur.proj.testing.runner\"]\n    ...}\n  ...\n```\n\nNow you can use that to run the following, optionally limiting tests to what\nthey have been tagged in their namespace:\n\n* `lein run-tests` (will run all types of tests)\n* `lein run-tests unit`\n* `lein run-tests integration`\n* `lein run-tests system`\n\n\n#### Running without ltest [\u0026#x219F;](#contents)\n\nIn the example above, we used the arbitrary namespace metadata of `:unit`,\n`:integration`, and `:system` for our different types of tests. Now that you\nhave made these annotations in the test namespaces, you can use them directly\nwith `lein`, too (without using ltest, should you so choose). Simply add this\nto your `project.clj` file's `:test` profile:\n\n```clj\n  ...\n  :profiles {\n    ...\n    :test {\n      ...\n      :test-selectors {\n        :default :unit\n        :unit :unit\n        :integration :integration\n        :system :system}\n      }}}\n  ...\n```\n\nNow you can run the following to just test the parts of the project you want:\n\n* `lein test` (will just run unit tests)\n* `lein test :unit`\n* `lein test :integration`\n* `lein test :system`\n\n\n## License [\u0026#x219F;](#contents)\n\nCopyright © 2017, Clojure-Aided Enrichment Center\n\nDistributed under the Apache License, Version 2.0.\n\n\n\u003c!-- Named page links below: /--\u003e\n\n[logo]: resources/images/test-dummies-small.jpg\n[logo-large]: resources/images/test-dummies.jpg\n\n[travis]: https://travis-ci.org/clojusc/ltest\n[travis-badge]: https://travis-ci.org/clojusc/ltest.png?branch=master\n[deps]: http://jarkeeper.com/clojusc/ltest\n[deps-badge]: http://jarkeeper.com/clojusc/ltest/status.svg\n[tag-badge]: https://img.shields.io/github/tag/clojusc/ltest.svg\n[tag]: https://github.com/clojusc/ltest/tags\n[clojure-v]: https://img.shields.io/badge/clojure-1.8.0-blue.svg\n[jdk-v]: https://img.shields.io/badge/jdk-1.7+-blue.svg\n[clojars]: https://clojars.org/clojusc/ltest\n[clojars-badge]: https://img.shields.io/clojars/v/clojusc/ltest.svg\n[clojars-lein]: https://clojars.org/lein-ltest\n[clojars-lein-badge]: https://img.shields.io/clojars/v/lein-ltest.svg\n\n[screen1-thumb]: resources/images/ns-test-thumb.png\n[screen1]: resources/images/ns-test.png\n[screen2-thumb]: resources/images/single-test-thumb.png\n[screen2]: resources/images/single-test.png\n[screen3-thumb]: resources/images/suite-test-thumb.png\n[screen3]: resources/images/suite-test.png\n[screen4-thumb]: resources/images/suites-tests-thumb.png\n[screen4]: resources/images/suites-tests.png\n\n[lfe-test-runner]: https://github.com/lfex/ltest#the-lfe-test-runner-\n[chris-durbin]: https://github.com/chris-durbin\n[cmr]: https://github.com/nasa/Common-Metadata-Repository/\n[cmr-client]: https://github.com/oubiwann/cmr-client/\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclojusc%2Fltest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fclojusc%2Fltest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fclojusc%2Fltest/lists"}