{"id":13896473,"url":"https://github.com/siffiejoe/lua-testy","last_synced_at":"2025-12-27T15:04:16.591Z","repository":{"id":32378320,"uuid":"35954623","full_name":"siffiejoe/lua-testy","owner":"siffiejoe","description":"Easy unit testing for Lua modules","archived":false,"fork":false,"pushed_at":"2024-08-18T15:26:33.000Z","size":484,"stargazers_count":36,"open_issues_count":2,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-11-25T02:32:08.908Z","etag":null,"topics":["lua","unit-testing"],"latest_commit_sha":null,"homepage":null,"language":"Lua","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/siffiejoe.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2015-05-20T14:53:51.000Z","updated_at":"2024-10-14T09:04:29.000Z","dependencies_parsed_at":"2025-07-17T16:43:39.437Z","dependency_job_id":"87356823-c9f0-4af7-aff8-f5e889f2ecbf","html_url":"https://github.com/siffiejoe/lua-testy","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/siffiejoe/lua-testy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siffiejoe%2Flua-testy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siffiejoe%2Flua-testy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siffiejoe%2Flua-testy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siffiejoe%2Flua-testy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/siffiejoe","download_url":"https://codeload.github.com/siffiejoe/lua-testy/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/siffiejoe%2Flua-testy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28080199,"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","status":"online","status_checked_at":"2025-12-27T02:00:05.897Z","response_time":58,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["lua","unit-testing"],"created_at":"2024-08-06T18:02:56.683Z","updated_at":"2025-12-27T15:04:16.551Z","avatar_url":"https://github.com/siffiejoe.png","language":"Lua","readme":"[![Build Status](https://travis-ci.org/siffiejoe/lua-testy.svg?branch=master)](https://travis-ci.org/siffiejoe/lua-testy)\n\n#             Testy -- Easy Unit Testing for Lua Modules             #\n\n##                           Introduction                           ##\n\nGood software engineering practices include testing your module code\non a regular basis to make sure that changes to your code did not\nbreak anything. There are many full-featured unit testing frameworks\navailable for Lua, but this one aims to be as unobtrusive as possible.\n\nFeatures:\n\n*   Pure Lua (compatible with Lua 5.1 and up), no other external\n    dependencies.\n*   You can embed the test functions *inside* your module code without\n    * wasting resources when not testing (embedded test functions get\n      discarded by default unless you load them via the `testy.lua`\n      script)\n    * messing up your public interface (the tests are local and have\n      access to internal functions that you might want to test)\n*   The test code looks like regular Lua code (you use `assert` for\n    your tests).\n*   Now includes (and autoloads) the `testy.extra` module, which\n    contains functions for specifying expected return values, expected\n    yields, expected iteration values, expected errors, etc. in a\n    declarative way.\n\n\n##                          Getting Started                         ##\n\nYou write your tests using `assert` in local functions embedded in\nyour Lua module (or in separate Lua files if you prefer). The test\nfunctions are identified by having a `test_` prefix in their names.\nE.g.:\n\n```lua\n-- module1.lua\nlocal M = {}\n\nfunction M.func1()\n  return 1\nend\n\n-- this is a test function for the module function `M.func1()`\nlocal function test_func1()\n  assert( M.func1() == 1, \"func1() should always return 1\" )\n  assert( M.func1() ~= 2, \"func1() should never return 2\" )\n  assert( type( M.func1() ) == \"number\" )\nend\n\nfunction M.func2()\n  return 2\nend\n\n-- this is a test function for the module function `M.func2()`\nlocal function test_func2()\n  assert( M.func2() == 2 )\n  assert( M.func2() ~= M.func1() )\nend\n\nreturn M\n```\n\nYou run your tests using the `testy.lua` script:\n\n```\n$ testy.lua module1.lua\nfunc1 ('module1.lua')   ...\nfunc2 ('module1.lua')   ..\n5 tests (5 ok, 0 failed, 0 errors)\n```\n\nThe `assert`s won't kill your test run even if they are false. Instead\nthey will update the test statistics, print a progress indicator, and\ncontinue on. This behavior of `assert` only happens when directly\ncalled by a test function. Anywhere else the `assert` function behaves\nnormally (thus terminating the program with an error if the condition\nevaluates to false). Instead of the `assert` function you can also use\nthe new global function `testy_assert`. This function works the same\nway, but its behavior doesn't depend on the function that calls it.\nThis is useful if you want to run a test in a function callback, or if\nyou want to write your own helper assertion functions.\n\nYou can pass multiple Lua files to the `testy.lua` script, or you can\npass the `-r` command line flag, which causes `testy.lua` to also\ncollect test functions from `require`d Lua modules recursively. You\nmay also switch to [TAP][3]-formatted output for third-party test\nreport tools like e.g. `prove` using the `-t` command line flag.\n\n```\n$ prove --exec \"testy.lua -t\" module1.lua\nmodule1.lua .. ok\nAll tests successful.\nFiles=1, Tests=5,  0 wallclock secs ( 0.02 usr +  0.01 sys =  0.03 CPU)\nResult: PASS\n```\n\nIf you installed **Testy** via LuaRocks, you should also have a Lua\nversion-specific script `testy-5.x` available, in case you want to\nrun the test suite with different Lua versions.\n\nAnd that's about it, but for more information you can view an\nannotated HTML version of the `testy.lua` source code rendered with\n[Docco][1] on the [GitHub pages][2].\n\n  [1]: http://jashkenas.github.io/docco/\n  [2]: http://siffiejoe.github.io/lua-testy/\n  [3]: http://testanything.org/tap-specification.html\n\n\n##                     The `testy.extra` Module                     ##\n\nThe `testy.lua` script tries to `require()` the `testy.extra` module\nand makes all exported functions available as global variables during\ntest execution. Failure to load `testy.extra` is silently ignored.\n\nThe following functions are part of `testy.extra`:\n\n*   `is( x, y ) ==\u003e boolean, string`\n\n    `is( y )( x ) ==\u003e boolean, string`\n\n    The `is` function is roughly equivalent to the equality operator,\n    but for certain values `y` is interpreted as a *template* or\n    *prototype*: If `y` is a function (and not primitively equal to\n    `x`), it is called as a unary predicate with `x` as argument. If\n    `y` is a table (and not primitively equal to `x`), it is iterated,\n    and the fields of `y` are compared to the corresponding fields of\n    `x` using the same rules as for `is`. The `is` function also\n    correctly handles `NaN` values.\n\n    The second form of `is` can be used to create unary predicates.\n    (I.e. `is( y )` returns a unary function that when applied to an\n    `x` is equivalent to the results of an `is( x, y )` call.)\n\n*   `is_\u003ctype\u003e( x ) ==\u003e boolean, string`\n\n    Unary predicates that check the type of the argument `x`.\n    There's one function for each of the eight primitive Lua types,\n    and additionally an `is_cdata` function for LuaJIT's FFI type.\n\n*   `is_false( x ) ==\u003e boolean, string`\n\n    Unary predicate that tests for `nil` or `false` (commonly known as\n    a *falsey* value).\n\n*   `is_true( x ) ==\u003e boolean, string`\n\n    Unary predicate that tests for a *trueish* value (a value that is\n    neither `nil` nor `false`).\n\n*   `is_len( x, y ) ==\u003e boolean, string`\n\n    `is_len( y )( x ) ==\u003e boolean, string`\n\n    The `is_len` function checks whether `#x` is equal to `y`. The\n    second form of `is_len` can be used to create unary predicates.\n    (See `is` above!)\n\n*   `is_like( x, y ) ==\u003e boolean, string`\n\n    `is_like( y )( x ) ==\u003e boolean, string`\n\n    The `is_like` function uses `string.match` to check whether the\n    string `x` matches the pattern `y`. The second form of `is_like`\n    can be used to create unary predicates. (See `is` above!)\n\n*   `is_eq( x, y ) ==\u003e boolean, string`\n\n    `is_eq( y )( x ) ==\u003e boolean, string`\n\n    The `is_eq` function checks for (deep) equality between `x` and\n    `y`. It correctly handles `NaN` values, metatables, `__eq`\n    metamethods, and cyclic tables. This is a stricter version of the\n    `is` function above without the prototype/template stuff.\n\n    The second form of `is_eq` can be used to create unary predicates.\n    (See `is` above!)\n\n*   `is_raweq( x, y ) ==\u003e boolean, string`\n\n    `is_raweq( y )( x ) ==\u003e boolean, string`\n\n    The `is_raweq` function checks for raw equality between `x` and\n    `y` (almost like the `rawequal` function from Lua's standard\n    library): it doesn't check `__eq` metamethods or recurse into\n    subtables. It does however correctly handle `NaN` values.\n\n    The second form of `is_raweq` can be used to create unary\n    predicates. (See `is` above!)\n\n*   `is_gt( x, y ) ==\u003e boolean, string`\n\n    `is_gt( y )( x ) ==\u003e boolean, string`\n\n    The `is_gt` function checks whether `x \u003e y`. The second form can\n    be used to create unary predicates. (See `is` above!)\n\n*   `is_lt( x, y ) ==\u003e boolean, string`\n\n    `is_lt( y )( x ) ==\u003e boolean, string`\n\n    The `is_lt` function checks whether `x \u003c y`. The second form can\n    be used to create unary predicates. (See `is` above!)\n\n*   `is_ge( x, y ) ==\u003e boolean, string`\n\n    `is_ge( y )( x ) ==\u003e boolean, string`\n\n    The `is_ge` function checks whether `x \u003e= y`. The second form can\n    be used to create unary predicates. (See `is` above!)\n\n*   `is_le( x, y ) ==\u003e boolean, string`\n\n    `is_le( y )( x ) ==\u003e boolean, string`\n\n    The `is_le` function checks whether `x \u003c= y`. The second form can\n    be used to create unary predicates. (See `is` above!)\n\n*   `any( ... )( ... ) ==\u003e boolean, string`\n\n    `any( ... )` creates a n-ary predicate that succeeds if at least\n    one of its arguments matches the second vararg list. The arguments\n    to `any` are interpreted as by the `is` function above, except\n    that functions will be treated as n-ary not unary. The `any`\n    function evaluates from left to right and short-circuits similar\n    to the `or` operator.\n\n*   `all( ... )( ... ) ==\u003e boolean, string`\n\n    `all( ... )` creates a n-ary predicate that succeeds if all of its\n    arguments match the second vararg list. The arguments to `all` are\n    interpreted as by the `is` function above, except that functions\n    will be treated as n-ary not unary. The `all` function evaluates\n    from left to right and short-circuits similar to the `and`\n    operator.\n\n*   `none( ... )( ... ) ==\u003e boolean, string`\n\n    `none( ... )` creates a n-ary predicate that succeeds only if all\n    of its arguments fail to match the second vararg list. The\n    arguments to `none` are interpreted as by the `is` function above,\n    except that functions will be treated as n-ary not unary. The\n    `none` function evaluates from left to right and short-circuits\n    similar to the `and` operator (with the individual operands\n    negated).\n\n*   `resp( ... )( ... ) ==\u003e boolean, string`\n\n    `resp( ... )` creates an n-ary predicate that tries to match each\n    argument to the corresponding value in the first vararg list,\n    *resp*ectively. The values in the first argument list are\n    interpreted as by the `is` function above.\n\n*   `raises( p, f, ... ) ==\u003e boolean, string`\n\n    `raises` `pcall`s the function `f` with the given arguments and\n    matches the error object to `p`. `p` is interpreted as by the `is`\n    function above. If `f` does not raise an error, the `raises`\n    function returns `false`.\n\n*   `returns( p, f, ... ) ==\u003e boolean, string`\n\n    `returns` `pcall`s the function `f` with the given arguments and\n    applies the predicate `p` to the return values. `p` is interpreted\n    as by the `is` function above, except that functions are treated\n    as n-ary not unary. If `f` raises an error, the `returns` function\n    returns `false` (plus message).\n\n*   `yields( f, a1, p1, ... ) ==\u003e boolean, string`\n\n    `yields` creates a new coroutine from `f` and resumes it multiple\n    times using the arguments in the tables `a1`, `a2`, ..., and\n    compares the resulting values using the predicates `p1`, `p2`,\n    ..., respectively. The arguments must be contained in tables as\n    returned by `table.pack` (the `n` field is optional if the table\n    is a proper sequence). The predicates `px` usually are n-ary\n    predicates, but they can be anything that `is` can handle (in\n    which case they are *unary* tests, though). `yields` only succeeds\n    if `f` yields often enough, no errors are raised, and all\n    predicates match the corresponding yielded/returned values.\n\n*   `iterates( ps, f, s, var ) ==\u003e boolean, string`\n\n    `iterates` compares the values created by the iterator triple `f`,\n    `s`, `var`, to the values contained in the table `ps`. `ps` is a\n    table as returned by `table.pack` (the `n` field is optional if\n    the table is a proper sequence) and usually contains n-ary\n    predicates, but it may contain anything that `is` can handle (in\n    which case they are *unary* tests, though). `iterates` succeeds\n    only if the iterator iterates often enough, no errors are raised\n    by `f`, and the tuples created during iteration match the\n    predicates in `ps`.\n\n\n##                              Contact                             ##\n\nPhilipp Janda, siffiejoe(a)gmx.net\n\nComments and feedback are always welcome.\n\n\n##                              License                             ##\n\n**Testy** is *copyrighted free software* distributed under the MIT\nlicense (the same license as Lua 5.1). The full license text follows:\n\n    Testy (c) 2015,2016 Philipp Janda\n\n    Permission is hereby granted, free of charge, to any person obtaining\n    a copy of this software and associated documentation files (the\n    \"Software\"), to deal in the Software without restriction, including\n    without limitation the rights to use, copy, modify, merge, publish,\n    distribute, sublicense, and/or sell copies of the Software, and to\n    permit persons to whom the Software is furnished to do so, subject to\n    the following conditions:\n\n    The above copyright notice and this permission notice shall be\n    included in all copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\n    IN NO EVENT SHALL THE AUTHOR OR COPYRIGHT HOLDER BE LIABLE FOR ANY\n    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\n    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\n    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n","funding_links":[],"categories":["Lua"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsiffiejoe%2Flua-testy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsiffiejoe%2Flua-testy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsiffiejoe%2Flua-testy/lists"}