Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/bjornbytes/lust
Lightweight Lua test framework
https://github.com/bjornbytes/lust
Last synced: 1 day ago
JSON representation
Lightweight Lua test framework
- Host: GitHub
- URL: https://github.com/bjornbytes/lust
- Owner: bjornbytes
- License: mit
- Created: 2015-01-02T01:38:54.000Z (almost 10 years ago)
- Default Branch: master
- Last Pushed: 2023-08-22T20:44:58.000Z (about 1 year ago)
- Last Synced: 2024-08-02T06:20:03.962Z (3 months ago)
- Language: Lua
- Size: 26.4 KB
- Stars: 105
- Watchers: 7
- Forks: 11
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
- awesome-love2d - lust - Minimal test framework. (Testing)
README
Lust
===Lust is a small library that tests Lua code. It's useful because it is a single file and isn't very
opinionated, which can make it easier to quickly add testing to a Lua project.It supports nested describe/it blocks, before/after handlers, expect-style assertions, function
spies, and colors.Usage
---Copy the `lust.lua` file to a project directory and require it, which returns a table that includes all of the functionality.
```Lua
local lust = require 'lust'
local describe, it, expect = lust.describe, lust.it, lust.expectdescribe('my project', function()
lust.before(function()
-- This gets run before every test.
end)describe('module1', function() -- Can be nested
it('feature1', function()
expect(1).to.be.a('number') -- Pass
expect('astring').to.equal('astring') -- Pass
end)it('feature2', function()
expect(nil).to.exist() -- Fail
end)
end)
end)
```Documentation
---##### `lust.describe(name, func)`
Used 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.
##### `lust.it(name, func)`
Used 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.
### Assertions
Lust uses "expect style" assertions. An assertion begins with `lust.expect(value)` and other modifiers can be chained after that:
##### `lust.expect(x).to.exist()`
Fails only if `x` is `nil`.
##### `lust.expect(x).to.equal(y, [eps])`
Performs 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.
##### `lust.expect(x).to.be(y)`
Performs an equality test using the `==` operator. Fails if `x ~= y`.
##### `lust.expect(x).to.be.truthy()`
Fails if `x` is `nil` or `false`.
##### `lust.expect(x).to.be.a(y)`
If `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.
##### `lust.expect(x).to.have(y)`
If `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.
##### `lust.expect(f).to.fail()`
Ensures that the function `f` throws an error when it is run.
##### `lust.expect(f).to.fail.with(pattern)`
Ensures that the function `f` throws an error matching `pattern` when it is run.
##### `lust.expect(x).to.match(p)`
Fails if the string representation of `x` does not match the pattern `p`.
##### `lust.expect(x).to_not.*`
Negates the assertion.
### Spies
##### `lust.spy(table, key, run)` and `lust.spy(function, run)`
Spies 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:
- Specify `nil`.
- Specify a function.
- Specify a table and a name of a function in that table.The 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:
```lua
local object = {
method = function() end
}-- Basic usage:
local spy = lust.spy(object, 'method')
object.method(3, 4) -- spy is now {{3, 4}}
object.method('foo') -- spy is now {{3, 4}, {'foo'}}
lust.expect(#spy).to.equal(2)
lust.expect(spy[1][2]).to.equal(4)-- Using a run function:
local run = function()
object.method(1, 2, 3)
object.method(4, 5, 6)
endlust.expect(lust.spy(object, 'method', run)).to.equal({{1, 2, 3}, {4, 5, 6}})
-- Using a function input:
local add = function(a, b)
return a + b
endlocal spy = lust.spy(add)
spy(1, 2) -- => {{1, 2}}
spy('rain', 'bows') -- => {{1, 2}, {'rain', 'bows'}}lust.expect(#spy).to.equal(2)
lust.expect(spy[2]).to.equal({'rain', 'bows'})
```### Befores and Afters
You 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.
##### `lust.before(fn)`
Set 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.
##### `lust.after(fn)`
Set 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.
### Custom Assertions
Example of adding a custom `empty` assertion:
```lua
local lust = require 'lust'lust.paths.empty = {
test = function(value)
return #value == 0,
'expected ' .. tostring(value) .. ' to be empty',
'expected ' .. tostring(value) .. ' to not be empty'
end
}table.insert(lust.paths.be, 'empty')
lust.expect({}).to.be.empty()
lust.expect('').to.be.empty()
```First we define the assertion in the `lust.paths` table. Each path is a table containing a `test`
function which performs the assertion. It returns three values: the result of the test (true for
pass, false for fail), followed by two messages: the first for a normal expectation failure, the
second for when the expectation is negated.We then insert our 'empty' assertion into the `be` path -- the numeric keys of a path represent the
possible expectations that can be chained.### Non-console Environments
If 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:
```lua
local lust = require('lust').nocolor()
```License
---MIT, see LICENSE for details.