{"id":18510026,"url":"https://github.com/lfex/ltest","last_synced_at":"2025-04-05T02:09:13.388Z","repository":{"id":57518752,"uuid":"21803635","full_name":"lfex/ltest","owner":"lfex","description":"A Testing Framework for LFE (successor to lfeunit)","archived":false,"fork":false,"pushed_at":"2025-01-15T22:06:34.000Z","size":1006,"stargazers_count":37,"open_issues_count":12,"forks_count":13,"subscribers_count":7,"default_branch":"release/0.13.x","last_synced_at":"2025-03-29T01:12:03.420Z","etag":null,"topics":["erlang","eunit","hacktoberfest","integration","lfe","lisp","system","testing","unit"],"latest_commit_sha":null,"homepage":"","language":"LFE","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lfex.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2014-07-14T01:19:26.000Z","updated_at":"2025-01-15T22:06:36.000Z","dependencies_parsed_at":"2024-02-20T00:27:43.029Z","dependency_job_id":"3bfeb687-8554-415c-b1c4-87b28f3b1003","html_url":"https://github.com/lfex/ltest","commit_stats":{"total_commits":456,"total_committers":10,"mean_commits":45.6,"dds":0.3377192982456141,"last_synced_commit":"6cfb0e3c372f85a04e681aa6a92df37c8a496308"},"previous_names":[],"tags_count":44,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lfex%2Fltest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lfex%2Fltest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lfex%2Fltest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lfex%2Fltest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lfex","download_url":"https://codeload.github.com/lfex/ltest/tar.gz/refs/heads/release/0.13.x","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247276164,"owners_count":20912288,"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":["erlang","eunit","hacktoberfest","integration","lfe","lisp","system","testing","unit"],"created_at":"2024-11-06T15:20:16.407Z","updated_at":"2025-04-05T02:09:13.365Z","avatar_url":"https://github.com/lfex.png","language":"LFE","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ltest\n\n[![Build Status][gh-actions-badge]][gh-actions]\n[![LFE Versions][lfe-badge]][lfe]\n[![Erlang Versions][erlang-badge]][versions]\n[![Tags][github-tags-badge]][github-tags]\n[![Downloads][hex-downloads]][hex-package]\n\n*A Unit, Integration, and System Tests Framework for LFE*\n\n[![][ltest-logo]][ltest-logo-large]\n\n## Contents\n\n* [Introduction](#introduction-)\n* [Dependencies](#dependencies-)\n* [EUnit Compatibility](#eunit-compatibility-)\n* [Features](#features-)\n* [Using ltest](#using-ltest-)\n  * [Adding ltest to Your Project](#adding-ltest-to-your-project-)\n  * [Structuring Your Tests](#structuring-your-tests-)\n  * [Naming Rules](#naming-rules-)\n  * [Creating Unit Tests](#creating-unit-tests-)\n  * [Running Your Tests](#running-your-tests-)\n  * [The LFE Test Runner](#the-lfe-test-runner-)\n* [Dogfood](#dogfood-)\n* [License](#license-)\n\n## Introduction [\u0026#x219F;](#contents)\n\nThe macros in this library are, in large part, inspired by Clojure's excellent\nunit test framework. In addition to provding such a testing DSL for LFE, this\nlibrary also includes a visually pleasing test running with coloured output\nand obvious errors/test failures. It also provides the ability to skip tests.\n\n## Dependencies [\u0026#x219F;](#contents)\n\nVersion 0.11.0 is the first version to support and work with LFE 2.0.\n\nAs of version 0.7.0, this project assumes that you have\n[rebar3](https://github.com/rebar/rebar3) installed somwhere in your `$PATH`.\nIt no longer uses the old version of rebar. If you do not wish to use rebar3,\nyou may use the most recent rebar2-compatible release of ltest: 0.6.3.\n\n## EUnit Compatibility [\u0026#x219F;](#contents)\n\nThe tests created with ltest are compatible with EUnit and can be run from\neither Erlang or LFE, using the standard EUnit listener or the ltest\nlistener (test runner).\n\n### Features [\u0026#x219F;](#contents)\n\n* `(deftest ...)` for standard unit tests\n* `(deftestgen ...)` for writing tests with generators, including the\n  standard EUnit test fixtures (see naming caveat below)\n* `(deftestskip ...)` for skipping unit tests; note that for a test to show up\n  as skipped in the test runner, it has to be `export`ed in the module\n* `(list ...)`-wrapped tests (of arbitrary depth) for use as test sets\n* `(tuple ...)`-wrapped tests for naming/describing tests (first element\n  of tuple)\n* `(behaviour ltest-unit)` - annotating a test module to be run as a unit\n  test\n* `(behaviour ltest-integration)` - annotating a test module to be run as an\n  integration test\n* `(behaviour ltest-system)` - annotating a test module to be run as a\n  system test\n* A custom test runner that over-rides EUnit behaviour and aesthetics\n\n## Using `ltest` [\u0026#x219F;](#contents)\n\n### Adding ltest to Your Project [\u0026#x219F;](#contents)\n\nIn order to use ltest in your project, all you need to do is add a rebar dep.\nGenerally, you only need `ltest` when running tests, so it's best to add it as\na dependency in the `test` profile. You'll also need to tell EUnit where to\ntake your tests from (`eunit_compile_otps`). In your `rebar.config`:\n\n```erlang\n{profiles, [\n  {test, [\n    {deps, [\n      {ltest, \"0.13.7\"}\n    ]}\n    {src_dirs, [\"src\", \"test\"]}\n  ]}\n]}.\n```\n\nOnce you write some tests (see below for how to do that), you can then do this:\n\n```bash\n$ rebar3 as test lfe ltest\n```\n\n### Structuring Your Tests [\u0026#x219F;](#contents)\n\nltest doesn not support putting your unit tests directly in your modules. If\nyou do this, things may break or not work properly, even though Erlang's EUnit\ndoes support it.\n\nInstead, you should create a top-level directory in your project called\n`test`. In `test`, create a test cases module for every module your project\nhas, e.g., `test/myproj-base-tests.lfe` and `test/myproj-util-tests.lfe`.\nObviously, if it makes sense to break things up in a more fine-grained manner,\nfeel free to do so :-)\n\nFurthermore, ltest supports separating unit, integration, and system tests.\nThis is done using custom OTP behaviours. For each test cases module you have\ncreated in `./test`, be sure to set the behaviour in the `(defmodule ...)`\nform. For instance:\n\n```cl\n  (defmodule my-unit-tests\n    (behaviour ltest-unit)\n    (export ...))\n```\nAnd two more as well:\n\n```cl\n  (defmodule my-integration-tests\n    (behaviour ltest-integration)\n    (export ...))\n```\n\nor\n\n```cl\n  (defmodule my-system-tests\n    (behaviour ltest-system)\n    (export ...))\n```\n\nFor a working example of such a structure, see the layout of the `ltest`\nproject itself: it uses just such a setup.\n\nTo read more about the distinction between unit, integration, and system\ntests, check out the Wikipedia\n[article on testing](http://en.wikipedia.org/wiki/Software_testing#Testing_levels).\n\n### Naming Rules [\u0026#x219F;](#contents)\n\nKeep in mind that your tests will be compiled to `.beam` and then run with\nErlang's eunit module. As such, your tests need to following the same\nconventions that eunit establishes:\n\n* Test module filenames should end in `-tests`, e.g.,\n  `some-module-tests.lfe`.\n\n* Test module and filename need to be the same, minus the extension. For\n  example, `test/unit-my-module-tests.lfe` needs to be declared as\n  `(defmodule unit-my-module-tests ...) in the test case module`.\n\n* If you chose *not* to use the `deftest` macro to build each unit test\n  function, you will need to name your unit test functions with `_test`\n  appended to them. For example,\n  `(defun unit-my-function-negagive-check_test () ...)`. We recommend,\n  however, that you use `deftest` instead, and obviate the need for `_test\n  ()` boilerplate.\n\n### Creating Unit Tests [\u0026#x219F;](#contents)\n\nltest is entirely macro-based. ltest uses LFE to parse the Erlang macros in\nthe eunit header file. It also provides its own header file which defines macros\nwhose main purpose is to wrap the eunit macros in a more Lispy form.\n\nltest also provides a syntactic sugar macro for defining tests: `deftest`.\nInstead of writing something like this for your unit tests:\n\n```cl\n\n    (defun unit-my-function-test ()\n      ...)\n```\n\nYou can use `deftest` to write this:\n\n```cl\n\n    (deftest unit-my-function\n      ...)\n```\n\nNote that the `-test` is no longer needed, nor is the empty argument list.\n\nIf you would like to use EUnit's fixtures feature, you must use another macro:\n\n```cl\n    (deftestgen unit-my-function\n      ...)\n```\n\nSee the unit tests in the `test` directory for example usage.\n\n\nIf you would like tests to be skipped, you can use this macro:\n\n```cl\n    (deftestskip unit-my-function\n      ...)\n```\n\nThis will simply make the test invisible to EUnit. EUnit doesn't actually\ntrack user-skipped tests; it only tracks tests that are skipped do to issues\nas perceived by EUnit.\n\nHowever, ltest's test runner *does* track skipped tests and will report\nthese in its output.\n\nHere is a more complete example:\n\n```cl\n    (defmodule unit-mymodule-tests\n      (behaviour ltest-unit)\n      (export all))\n\n    (include-lib \"ltest/include/ltest-macros.lfe\")\n\n    (deftest is\n      (is 'true)\n      (is (not 'false))\n      (is (not (not 'true))))\n\n    (deftest is-not\n      (is-not `'false))\n\n    (deftest is-equal\n      (is-equal 2 (+ 1 1)))\n```\n\nltest is working towards full test coverage; while not there yet, the unit\ntests for ltest itself provide the best examples of usage.\n\n### Running Your Tests [\u0026#x219F;](#contents)\n\nThe recommended way to run unit tests is to use the LFE plugin got `rebar3`.\nRunning tests is now as easy as doing the following:\n\n```bash\n    $ rebar3 as test lfe ltest\n```\n\nThat will run any unit tests you have defined. To run integration or system tests\nin your project:\n\n``` bash\n    $ rebar3 as test lfe ltest -tintegration\n    $ rebar3 as test lfe ltest -tsystem\n```\n\nTo run all tests for your project:\n\n``` bash\n    $ rebar3 as test lfe ltest -tall\n```\n\n### The LFE Test Runner [\u0026#x219F;](#contents)\n\nltest now includes a test runner which overrides the EUnit handlers with its\nown. Here's what the output looks like with failing and skipped tests:\n\n\u003cimg src=\"priv/images/screen-2-1.png\"/\u003e\n\nEnd:\n\n\u003cimg src=\"priv/images/screen-2-2.png\"/\u003e\n\nAnd here's what passing tests looks like:\n\n\u003cimg src=\"priv/images/screen-1-1.png\"/\u003e\n\nEnd:\n\n\u003cimg src=\"priv/images/screen-1-2.png\"/\u003e\n\nThe rest of the `make` targets still use lfetool, and will continue to do\nso, since lfetool will be updating to use ltest's new runner. If you'd like\nto track the progress on these, here are the related tickets:\n * https://github.com/lfex/ltool/issues/4\n * https://github.com/lfe/lfetool/issues/160\n\n\n## Dogfood [\u0026#x219F;](#contents)\n\n`ltest` writes its unit tests in `ltest` :-) You can run them from the\nproject directory:\n\n```bash\n    $ make check-runner-ltest\n```\n\nWhich will give you output similar to the following:\n\n```\n================================ ltest =================================\n\n------------------------------ Unit Tests ------------------------------\n\nmodule: ltest-basic-tests\n  is ................................................................ [ok]\n  are* .............................................................. [ok]\n  is_with_one_phrase_deftest ........................................ [ok]\n  is_with_two_phrase_deftest ........................................ [ok]\n  is_with_many_phrase_deftest ....................................... [ok]\n  is_fail ........................................................... [ok]\n  is_not ............................................................ [ok]\n  is_not_fail ....................................................... [ok]\n  is_equal .......................................................... [ok]\n  is_equal_fail ..................................................... [ok]\n  is_not_equal ...................................................... [ok]\n  is_not_equal_fail ................................................. [ok]\n  is_exception ...................................................... [ok]\n  is_exception_wrong_class .......................................... [ok]\n  is_exception_wrong_term ........................................... [ok]\n  is_exception_unexpected_success ................................... [ok]\n  is_not_exception .................................................. [ok]\n  is_not_exception_exit ............................................. [ok]\n  is_not_exception_throw ............................................ [ok]\n  is_error .......................................................... [ok]\n  is_error_wrong_term ............................................... [ok]\n  is_error_unexpected_success ....................................... [ok]\n  is_throw .......................................................... [ok]\n  is_throw_wrong_term ............................................... [ok]\n  is_throw_unexpected_success ....................................... [ok]\n  is_exit ........................................................... [ok]\n  is_exit_wrong_term ................................................ [ok]\n  is_exit_unexpected_success ........................................ [ok]\n  is_match .......................................................... [ok]\n  is_match_fail ..................................................... [ok]\n  time: 94ms\n\nmodule: ltest-cancelled-tests\n  setup_test_case ................................................... [ok]\n  Another unused test ............................................... [ok]\n  time: 17ms\n\nmodule: ltest-fixture-tests\n  setup_test_case ................................................... [ok]\n  setup_test_case ................................................... [ok]\n  Named setup test .................................................. [ok]\n  setup_test_case ................................................... [ok]\n  setup_test_case ................................................... [ok]\n  Named setup test .................................................. [ok]\n  setup_test_case ................................................... [ok]\n  setup_test_case ................................................... [ok]\n  Named setup test .................................................. [ok]\n  foreach_test_case ................................................. [ok]\n  foreach_test_case ................................................. [ok]\n  setup_test_case ................................................... [ok]\n  setup_test_case ................................................... [ok]\n  Named setup test .................................................. [ok]\n  foreach_test_case ................................................. [ok]\n  foreach_test_case ................................................. [ok]\n  time: 49ms\n\nmodule: ltest-fixturecase-tests\n  setup_tc_test_case ................................................ [ok]\n  setup_tc_test_case ................................................ [ok]\n  Named test in setup-tc ............................................ [ok]\n  setup_tc_test_case ................................................ [ok]\n  setup_tc_test_case ................................................ [ok]\n  Named test in setup-tc ............................................ [ok]\n  setup_tc_test_case ................................................ [ok]\n  setup_tc_test_case ................................................ [ok]\n  Named test in setup-tc ............................................ [ok]\n  foreach_tc_test_case .............................................. [ok]\n  foreach_tc_test_case .............................................. [ok]\n  Named foreach-tc test ............................................. [ok]\n  setup_tc_test_case ................................................ [ok]\n  setup_tc_test_case ................................................ [ok]\n  Named test in setup-tc ............................................ [ok]\n  foreach_tc_test_case .............................................. [ok]\n  foreach_tc_test_case .............................................. [ok]\n  Named foreach-tc test ............................................. [ok]\n  time: 56ms\n\nmodule: ltest-generated-tests\n  is* ............................................................... [ok]\n  is_not*_in_list ................................................... [ok]\n  many_generators_in_list ........................................... [ok]\n  many_generators_in_list ........................................... [ok]\n  many_generators_in_list ........................................... [ok]\n  nested_test_set ................................................... [ok]\n  nested_test_set ................................................... [ok]\n  nested_test_set ................................................... [ok]\n  nested_test_set ................................................... [ok]\n  nested_test_set ................................................... [ok]\n  nested_test_set ................................................... [ok]\n  time: 34ms\n\nmodule: ltest-named-tests\n  named_is .......................................................... [ok]\n  named_is_not_fail ................................................. [ok]\n  named_testset_with_one ............................................ [ok]\n  named_testset_with_two ............................................ [ok]\n  named_testset_with_three .......................................... [ok]\n  named_testset_nested .............................................. [ok]\n  named_testset_deeply_nested ....................................... [ok]\n  time: 22ms\n\nmodule: ltest-skipped-tests\n  bogus_test_will_be_skipped ...................................... [skip]\n  time: 1ms\n\nmodule: ltest-testset-tests\n  testset_with_one .................................................. [ok]\n  testset_with_two .................................................. [ok]\n  testset_with_three ................................................ [ok]\n  testset_nested .................................................... [ok]\n  testset_deeply_nested ............................................. [ok]\n  time: 16ms\n\nsummary:\n  Tests: 90  Passed: 89  Skipped: 1  Failed: 0 Erred: 0\n  Total time: 289ms\n\n\n----------------------------- System Tests -----------------------------\n\nThere were no system tests found.\n\n\n-------------------------- Integration Tests ---------------------------\n\nThere were no integration tests found.\n\n\n========================================================================\n```\n\n## License [\u0026#x219F;](#contents)\n\nBSD 3-Clause License\n\n```\nCopyright © 2013-2021, Duncan McGreggor \u003coubiwann@gmail.com\u003e\n\nCopyright © 2014, Døkkarr Hirðisson \u003cdokkarr@lfe.io\u003e,\n                  Joshua Schairbaum \u003cjoshua.schairbaum@gmail.com\u003e\n\nCopyright © 2016, Eric Bailey \u003ceric@ericb.me\u003e, \n                  jsc \u003cjonas.skovsgaard.christensen@gmail.com\u003e\n```\n\n[//]: ---Named-Links---\n\n[ltest-logo]: priv/images/ltest-logo-small.png\n[ltest-logo-large]: priv/images/ltest-logo-large.png\n[lr3-logo]: priv/images/logo.png\n[org]: https://github.com/lfe-rebar3\n[github]: https://github.com/lfex/ltest\n[gitlab]: https://gitlab.com/lfex/ltest\n[gh-actions-badge]: https://github.com/lfex/ltest/workflows/ci%2Fcd/badge.svg\n[gh-actions]: https://github.com/lfex/ltest/actions\n[lfe]: https://github.com/lfe/lfe\n[lfe-badge]: https://img.shields.io/badge/lfe-2.1.0-blue.svg\n[erlang-badge]: https://img.shields.io/badge/erlang-19%20to%2025-blue.svg\n[versions]: https://github.com/lfex/ltest/blob/master/.travis.yml\n[github-tags]: https://github.com/lfex/ltest/tags\n[github-tags-badge]: https://img.shields.io/github/tag/lfex/ltest.svg\n[github-downloads]: https://img.shields.io/github/downloads/atom/atom/total.svg\n[hex-badge]: https://img.shields.io/hexpm/v/ltest.svg?maxAge=2592000\n[hex-package]: https://hex.pm/packages/ltest\n[hex-downloads]: https://img.shields.io/hexpm/dt/ltest.svg\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flfex%2Fltest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flfex%2Fltest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flfex%2Fltest/lists"}