Module:Assert: Difference between revisions
(Created page with "require('strict') local Assert = {} --- Formats a message with optional arguments. --- @param message string The message to format. --- @param ... any The format arguments. --- @return string local function formatMessage(message, ...) local args = { ... } if #args > 0 then return message:format(...) else return message end end --- Asserts that `value`'s type matches one of the types in `expected`. --- @generic T --- @param value T The v...") |
No edit summary |
||
Line 27: | Line 27: | ||
types = expected | types = expected | ||
elseif type(expected) == 'table' then | elseif type(expected) == 'table' then | ||
types = '' | |||
for i, v in ipairs(expected) do | for i, v in ipairs(expected) do | ||
if i ~= 0 then | if i ~= 0 then |
Latest revision as of 02:23, 17 May 2024
The Assert module contains several convenience functions for common assertion use cases.
Using the module
To use the module, it must first be imported at the top of your module.
local Assert = require('Module:Assert')
Once the module is imported, simply call any of its functions to use it.
Custom Message Assertions
Every assertion has an additional *Msg variant which allows the caller to provide its own error message and optionally string format arguments. These functions drop the arguments that are used for formatting the default message and instead take a single message argument. If additional arguments are passed in, the message argument will be treated as a format string and passed to the string.format along with the additional arguments.
The "isType" assertion
The isType assertion checks that a value is of an expected type. If the value is not one of the expected types, then the assertion fails and an error is raised.
The value argument is returned to the caller upon successful completion.
Parameters
Parameter | Type | Description |
---|---|---|
value | any | The value to test the assertion against. |
expected | string or string[] | The expected type or list of types which value must be one of. |
name | string? | The name of the parameter to use in the error message, or nil for a generic error message. |
Example Usage
-- Succeeds: "Alice" is a string
Assert.isType('Alice', 'string', 'name')
-- Succeeds: 25 is a number or a string
Assert.isType(25, { 'string', 'number' }, 'age')
-- Fails: true is a boolean, but is expected to be a string
Assert.isType(true, 'string', 'height')
-- Fails with error message: 'This is a custom error, the value is actually a string'
Assert.isTypeMsg('abc', 'number', 'This is a custom error, the value was actually a %s', type('abc'))
The "exists" assertion
The isType assertion checks that a value is not nil. If the value is nil, then the assertion fails and an error is raised. This assertion also returns the value argument upon successful completion.
The value argument is returned to the caller upon successful completion.
Parameters
Parameter | Type | Description |
---|---|---|
value | any | The value to test the existence of. |
name | string? | The name of the parameter to use in the error message, or nil for a generic error message. |
Example Usage
--- Maps a quantity suffix to its exponent.
local UNIT_EXPONENTS = {
'k' = 3,
'm' = 6,
'b' = 9,
't' = 12
}
-- Succeeds: The value exists and is assigned to exponent.
local exponent = Assert.exists(UNIT_EXPONENTS['k'], 'exponent')
-- Fails: The value does not exist.
local exponent = Assert.exists(UNIT_EXPONENTS['p'], 'exponent')
-- Fails with custom error message: "Uh oh, something which should exist doesn't!"
local exponent = Assert.existsMsg(UNIT_EXPONENTS['p'], "Uh oh, something which should exist doesn't!")
The "isTrue/isFalse" assertions
The isTrue assertion checks that an expression evaluates to true. If the expression evaluates to false, then the assertion fails and an error is raised. The isFalse assertion functions the same way, but negates the logic.
These functions do not return the condition to the caller.
Parameters
Parameter | Type | Description |
---|---|---|
value | any | The expression to test the truthiness of. |
Example Usage
-- Succeeds: 'Bob' has a length greater than 0.
Assert.isTrue(string.len('Bob') > 0)
-- Fails with message: '3 is not an even number.'
local number = 3
Assert.isTrueMsg(number % 2 == 0, '%d is not an even number.', number)
The "equal" and "notEqual" assertions
The equal assertion checks that two values are equal. If the values are unequal, then the assertion fails and an error is raised. The notEqual assertion functions the same way, but negates the logic.
These functions return both a and b to the caller.
Parameters
Parameter | Type | Description |
---|---|---|
a | any | The first value being compared. |
b | any | The second value being compared. |
Example Usage
-- Succeeds: a = 'hi', b = 'hi'
local a, b = Assert.equal('hi', 'hi')
-- Fails: 'Hello' and 'World' are not equal
Assert.equal('Hello', 'World')
-- Fails with custom error: 'These things just aren't the same'
local first, second = Assert.equalMsg(true, false, "These things just aren't the same")
require('strict')
local Assert = {}
--- Formats a message with optional arguments.
--- @param message string The message to format.
--- @param ... any The format arguments.
--- @return string
local function formatMessage(message, ...)
local args = { ... }
if #args > 0 then
return message:format(...)
else
return message
end
end
--- Asserts that `value`'s type matches one of the types in `expected`.
--- @generic T
--- @param value T The value to run the assertion against.
--- @param expected type|type[] The list of expected types.
--- @param name string? The name of the parameter.
--- @return T value
function Assert.isType(value, expected, name)
local types
if type(expected) == 'string' then
types = expected
elseif type(expected) == 'table' then
types = ''
for i, v in ipairs(expected) do
if i ~= 0 then
types = types .. ', '
end
types = types .. v
end
end
return Assert.isTypeMsg(value, expected,
'"%s" has type "%s" but is expected to be one of the following types: %s',
name or value,
types,
type(value))
end
--- Asserts that `value`'s type matches one of the types in `expected` with a custom error message.
--- @generic T
--- @param value T The value to run the assertion against.
--- @param expected type|type[] The list of expected types.
--- @param message string The custom error message or format string.
--- @param ... any The error message format arguments.
--- @return T value
function Assert.isTypeMsg(value, expected, message, ...)
message = formatMessage(message, ...)
if type(expected) == 'string' then
assert(type(value) == expected, message)
elseif type(expected) == 'table' then
for _, v in ipairs(expected) do
if type(value) == v then
return value
end
end
-- Value type matches none of the expected types.
error(message)
else
-- Guaranteed to generate an error. We're only using this to make use of the prebuilt error string.
Assert.isType(expected, { 'string', 'table' }, 'expected')
end
return value
end
--- Asserts that `value` is not nil.
--- @generic T
--- @param value T The value to run the assertion against.
--- @param name T the name of the parameter.
--- @return T value
function Assert.exists(value, name)
if name then
return Assert.existsMsg(value, 'Expected "%s" to not be nil.', name)
else
return Assert.existsMsg(value, 'Expected value to not be nil.')
end
end
--- Asserts that `value` is not nil with a custom error message.
--- @generic T
--- @param value T The value to run the assertion against.
--- @param message string The custom error message or format string.
--- @param ... any The error message format arguments.
--- @return T value
function Assert.existsMsg(value, message, ...)
message = formatMessage(message, ...)
assert(value ~= nil, message)
return value
end
--- Asserts that `value` is true.
---@param value boolean The value to run the assertion on.
---@param name string The name of the parameter.
function Assert.isTrue(value, name)
if name then
Assert.isTrueMsg(value, 'Expected "%s" to be true.', name)
else
Assert.isTrueMsg(value, 'Expected value to be true.')
end
end
--- Asserts that `value` is true with a custom error message.
--- @param value boolean The value to run the assertion on.
--- @param message string The custom error message or format string.
--- @param ... any
function Assert.isTrueMsg(value, message, ...)
message = formatMessage(message, ...)
assert(value, message)
end
--- Asserts that `value` is false.
--- @param value boolean The value to run the assertion on.
--- @param name string? The name of the value
function Assert.isFalse(value, name)
if name then
Assert.isFalseMsg(value, 'Expected "%s" to be false.', name)
else
Assert.isFalseMsg(value, 'Expected value to be false.')
end
end
--- Asserts that `value` is false with a custom error message.
--- @param value boolean The value to run the assertion on.
--- @param message string The custom error message or format string.
--- @param ... any
function Assert.isFalseMsg(value, message, ...)
message = formatMessage(message, ...)
assert(not value, message)
end
--- Asserts that `a` and `b` are equal.
--- @generic U
--- @generic V
--- @param a U The first value to run the assertion against.
--- @param b V The second value to run the assertion against.
--- @return U a
--- @return V b
function Assert.equal(a, b)
return Assert.equalsMsg(a, b,
'Expected values to be equal "%s" (%s) ~= "%s" (%s)',
a, type(a),
b, type(b))
end
--- Asserts that `a` and `b` are equal with a custom error message.
--- @generic U
--- @generic V
--- @param a U The first value to run the assertion against.
--- @param b V The second value to run the assertion against.
--- @param message string The custom error message or format string.
--- @param ... any The error message format arguments.
--- @return U a
--- @return V b
function Assert.equalMsg(a, b, message, ...)
message = formatMessage(message, ...)
assert(a == b, message)
return a, b
end
--- Asserts that `a` and `b` are not equal.
--- @generic U
--- @generic V
--- @param a U The first value to run the assertion against.
--- @param b V The second value to run the assertion against.
--- @return U a
--- @return V b
function Assert.notEqual(a, b)
return Assert.notEqualMsg(a, b,
'Expected values to not be equal "%s" (%s) ~= "%s" (%s)',
a, type(a),
b, type(b))
end
--- Asserts that `a` and `b` are not equal with a custom error message.
--- @generic U
--- @generic V
--- @param a U The first value to run the assertion against.
--- @param b V The second value to run the assertion against.
--- @param message string The custom error message for format string.
--- @param ... any The error message format arguments.
--- @return U a
--- @return V b
function Assert.notEqualMsg(a, b, message, ...)
assert(a ~= b, message)
return a, b
end
return Assert