{"id":13526326,"url":"https://github.com/bjornbytes/lust","last_synced_at":"2026-03-14T01:02:17.086Z","repository":{"id":25274898,"uuid":"28700502","full_name":"bjornbytes/lust","owner":"bjornbytes","description":"Lightweight Lua test framework","archived":false,"fork":false,"pushed_at":"2024-10-03T22:41:06.000Z","size":35,"stargazers_count":118,"open_issues_count":0,"forks_count":12,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-05T14:04:05.329Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"lukes/ISO-3166-Countries-with-Regional-Codes","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bjornbytes.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":"2015-01-02T01:38:54.000Z","updated_at":"2025-03-12T20:26:06.000Z","dependencies_parsed_at":"2024-11-20T07:34:56.204Z","dependency_job_id":"3f89b6a5-4050-4d40-9781-a92ba14ad700","html_url":"https://github.com/bjornbytes/lust","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/bjornbytes/lust","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bjornbytes%2Flust","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bjornbytes%2Flust/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bjornbytes%2Flust/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bjornbytes%2Flust/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bjornbytes","download_url":"https://codeload.github.com/bjornbytes/lust/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bjornbytes%2Flust/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270014238,"owners_count":24512608,"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-08-12T02:00:09.011Z","response_time":80,"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":[],"created_at":"2024-08-01T06:01:28.054Z","updated_at":"2025-12-17T10:34:32.261Z","avatar_url":"https://github.com/bjornbytes.png","language":"Lua","funding_links":[],"categories":["资源","Resources","Testing"],"sub_categories":["Testing"],"readme":"Lust\n===\n\nLust is a small library that tests Lua code.  It's useful because it is a single file and isn't very\nopinionated, which can make it easier to quickly add testing to a Lua project.\n\nIt supports nested describe/it blocks, before/after handlers, expect-style assertions, function\nspies, and colors.\n\nUsage\n---\n\nCopy the `lust.lua` file to a project directory and require it, which returns a table that includes all of the functionality.\n\n```Lua\nlocal lust = require 'lust'\nlocal describe, it, expect = lust.describe, lust.it, lust.expect\n\ndescribe('my project', function()\n  lust.before(function()\n    -- This gets run before every test.\n  end)\n\n  describe('module1', function() -- Can be nested\n    it('feature1', function()\n      expect(1).to.be.a('number') -- Pass\n      expect('astring').to.equal('astring') -- Pass\n    end)\n\n    it('feature2', function()\n      expect(nil).to.exist() -- Fail\n    end)\n  end)\nend)\n```\n\nDocumentation\n---\n\n##### `lust.describe(name, func)`\n\nUsed to declare a group of tests.  `name` is a string used to describe the group, and `func` is a function containing all tests and `describe` blocks in the group.  Groups created using `describe` can be nested.\n\n##### `lust.it(name, func)`\n\nUsed to declare a test, which consists of a set of assertions.  `name` is a string used to describe the test, and `func` is a function containing the assertions.\n\n### Assertions\n\nLust uses \"expect style\" assertions.  An assertion begins with `lust.expect(value)` and other modifiers can be chained after that:\n\n##### `lust.expect(x).to.exist()`\n\nFails only if `x` is `nil`.\n\n##### `lust.expect(x).to.equal(y, [eps])`\n\nPerforms a strict equality test, failing if `x` and `y` have different types or values.  Tables are tested by recursively ensuring that both tables contain the same set of keys and values.  Metatables are not taken into consideration.  The optional `eps` parameter is used as a threshold for numbers to test for approximate floating point equality.\n\n##### `lust.expect(x).to.be(y)`\n\nPerforms an equality test using the `==` operator.  Fails if `x ~= y`.\n\n##### `lust.expect(x).to.be.truthy()`\n\nFails if `x` is `nil` or `false`.\n\n##### `lust.expect(x).to.be.a(y)`\n\nIf `y` is a string, fails if `type(x)` is not equal to `y`.  If `y` is a table, walks up `x`'s metatable chain and fails if `y` is not encountered.\n\n##### `lust.expect(x).to.have(y)`\n\nIf `x` is a table, ensures that at least one of its keys contains the value `y` using the `==` operator.  If `x` is not a table, this assertion fails.\n\n##### `lust.expect(f).to.fail()`\n\nEnsures that the function `f` throws an error when it is run.\n\n##### `lust.expect(f).to.fail.with(pattern)`\n\nEnsures that the function `f` throws an error matching `pattern` when it is run.\n\n##### `lust.expect(x).to.match(p)`\n\nFails if the string representation of `x` does not match the pattern `p`.\n\n##### `lust.expect(x).to_not.*`\n\nNegates the assertion.\n\n### Spies\n\n##### `lust.spy(table, key, run)` and `lust.spy(function, run)`\n\nSpies on a function and tracks the number of times it was called and the arguments it was called with.  There are 3 ways to specify arguments to this function:\n\n- Specify `nil`.\n- Specify a function.\n- Specify a table and a name of a function in that table.\n\nThe return value is a table that will contain one element for each call to the function. Each element of this table is a table containing the arguments passed to that particular invocation of the function.  The table can also be called as a function, in which case it will call the function it is spying on.  The third argument, `run`, is a function that will be called immediately upon creation of the spy.  Example:\n\n```lua\nlocal object = {\n  method = function() end\n}\n\n-- Basic usage:\nlocal spy = lust.spy(object, 'method')\nobject.method(3, 4) -- spy is now {{3, 4}}\nobject.method('foo') -- spy is now {{3, 4}, {'foo'}}\nlust.expect(#spy).to.equal(2)\nlust.expect(spy[1][2]).to.equal(4)\n\n-- Using a run function:\nlocal run = function()\n  object.method(1, 2, 3)\n  object.method(4, 5, 6)\nend\n\nlust.expect(lust.spy(object, 'method', run)).to.equal({{1, 2, 3}, {4, 5, 6}})\n\n-- Using a function input:\nlocal add = function(a, b)\n  return a + b\nend\n\nlocal spy = lust.spy(add)\n\nspy(1, 2) -- =\u003e {{1, 2}}\nspy('rain', 'bows') -- =\u003e {{1, 2}, {'rain', 'bows'}}\n\nlust.expect(#spy).to.equal(2)\nlust.expect(spy[2]).to.equal({'rain', 'bows'})\n```\n\n### Befores and Afters\n\nYou can define functions that are called before and after every call to `lust.it` using `lust.before` and `lust.after`.  They are scoped to the `describe` block that contains them as well as any inner `describe` blocks.\n\n##### `lust.before(fn)`\n\nSet a function that is called before every test inside this `describe` block.  `fn` will be passed a single string containing the name of the test about to be run.\n\n##### `lust.after(fn)`\n\nSet a function that is called after every test inside this `describe` block.  `fn` will be passed a single string containing the name of the test that was finished.\n\n### Custom Assertions\n\nExample of adding a custom `empty` assertion:\n\n```lua\nlocal lust = require 'lust'\n\nlust.paths.empty = {\n  test = function(value)\n    return #value == 0,\n      'expected ' .. tostring(value) .. ' to be empty',\n      'expected ' .. tostring(value) .. ' to not be empty'\n  end\n}\n\ntable.insert(lust.paths.be, 'empty')\n\nlust.expect({}).to.be.empty()\nlust.expect('').to.be.empty()\n```\n\nFirst we define the assertion in the `lust.paths` table.  Each path is a table containing a `test`\nfunction which performs the assertion.  It returns three values: the result of the test (true for\npass, false for fail), followed by two messages: the first for a normal expectation failure, the\nsecond for when the expectation is negated.\n\nWe then insert our 'empty' assertion into the `be` path -- the numeric keys of a path represent the\npossible expectations that can be chained.\n\n### Non-console Environments\n\nIf Lua is embedded in an application and does not run in a console environment that understands ANSI color escapes, the library can be required as follows:\n\n```lua\nlocal lust = require('lust').nocolor()\n```\n\nLicense\n---\n\nMIT, see LICENSE for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbjornbytes%2Flust","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbjornbytes%2Flust","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbjornbytes%2Flust/lists"}