Skip to content

Assertion

An Assertion wraps a single value and exposes one method per expectation.

At a glance

Method Passes when
equalsTo The value equals the expected value.
notEqualsTo The value differs from the expected value.
isTrue The value is exactly true.
isFalse The value is exactly false.
isNil The value is nil.
isNotNil The value is not nil.
isNaN The value is NaN.
isInf The value is positive or negative infinity.
isFinite The value is a finite number.
isType typeof(value) equals the given type name.
throws The value is a function, and calling it raises.
notThrows The value is a function, and calling it returns normally.
contains A string contains the substring, or a table contains the value.
notContains The inverse of contains.

Assertion.new

Assertion.new(expression: any): Assertion

Stores expression in _expression and returns the new assertion. This is what Wisp.assume calls.

Parameter Type Description
expression any The subject of the expectation. Never evaluated for truthiness.

_expression is the only field, and it is internal by convention. Each call returns a fresh object, so assertions hold no state between calls.

How failures work

Assertion methods do not return a boolean. Each one either returns nothing — the assertion held — or calls error(message, 2). Wisp catches that error in Suite:run and attributes it to the action that raised it.

Because the level is 2, the reported location is the assertion line rather than a line inside Wisp.

The remaining assertions in the action do not run: the first failure ends that action.

Messages below are written as templates — {value} is the tostring of the subject, and {expected} the tostring of the argument.

Equality

equalsTo

Assertion:equalsTo(expected: any): ()

Passes when self._expression == expected.

Parameter Type Description
expected any The value to compare against, with ==.

Fails with Assertion failed: expected {expected}, got {value}.

Equality is ==, not deep equality

Tables and functions are compared by identity, so two structurally identical tables fail. Assert on individual fields instead. NaN is also never equal to itself, so this can never match it — use isNaN.

notEqualsTo

Assertion:notEqualsTo(expected: any): ()

Passes when self._expression ~= expected.

Parameter Type Description
expected any The value to compare against, with ==.

Fails with Assertion failed: expected not {expected}, got {value}.

Booleans

isTrue

Assertion:isTrue(): ()

Passes when the value is exactly true. Truthy non-booleans fail, because the comparison is against the boolean itself.

Fails with Assertion failed: expected true, got {value}.

isFalse

Assertion:isFalse(): ()

Passes when the value is exactly false.

Fails with Assertion failed: expected false, got {value}.

Nil

isNil

Assertion:isNil(): ()

Passes when the value is nil.

Fails with Assertion failed: expected nil, got {value}.

isNotNil

Assertion:isNotNil(): ()

The inverse of isNil. Every other falsy value passes, since only nil is nil.

Fails with Assertion failed: expected non-nil, got nil — the message is fixed, since the only possible value is nil.

Numbers

All three delegate to the math library.

isNaN

Assertion:isNaN(): ()

Passes when math.isnan(value) is true.

Fails with Assertion failed: expected nan, got {value}.

This is the only way to assert on NaN

Because NaN ~= NaN, both equalsTo and contains can never match it.

isInf

Assertion:isInf(): ()

Passes when math.isinf(value) is true. Both signs match.

Fails with Assertion failed: expected inf, got {value}.

isFinite

Assertion:isFinite(): ()

Passes when math.isfinite(value) is true. Ordinary numbers, including 0 and negatives, pass; both infinities and NaN fail.

Fails with Assertion failed: expected a finite number, got {value}.

These three need a number

A non-number subject raises a type error from the engine rather than an assertion message, because math.isnan and friends are called directly. The action still fails, but the message comes from the engine. Use isType first if you want a clearer failure.

Types

isType

Assertion:isType(expectedType: string): ()

Compares typeof(value) against a type name string.

Parameter Type Description
expectedType string A typeof name, such as "number" or "table".

Fails with Assertion failed: expected type {expectedType}, got type {actualType}.

Because the comparison is a plain string match, a misspelled type name is reported against the actual type rather than raising.

Errors

throws

Assertion:throws(): ()

Passes when the subject is a function and calling it raises. Uses pcall, so a nested assertion failure inside the function also counts as a throw.

Condition Message
The value is not a function throws() requires a function, got {typeof(value)}
The function returned normally Assertion failed: expected function to throw, but it did not

The message is not checked

throws() only asserts that an error occurred, not what it said. To assert on the message, call the function yourself and assert on the string with contains.

notThrows

Assertion:notThrows(): ()

The inverse of throws. Passes when the subject is a function and calling it returns normally.

Condition Message
The value is not a function notThrows() requires a function, got {typeof(value)}
The function raised Assertion failed: expected function not to throw, but it did

Containment

contains

Assertion:contains(value: any): ()
Subject type Passes when Failure message
string The string contains value as a literal substring. Assertion failed: expected string to contain {value}, but it did not
table Some value in the table is == to value. Assertion failed: expected table to contain {value}, but it did not
anything else Never — raises immediately. contains() not supported for type {typeof(value)}
Parameter Type Description
value any The substring or value to look for.

For strings the needle is never treated as a Lua pattern, so . and % are literal. The search is a plain substring scan, not anchored, so a partial match passes.

For tables, the scan covers both the array and hash parts.

Values only, and == only

On a table, contains inspects values, never keys, and compares with ==. It will not find a key, will not match nested tables by content, and cannot find NaN. For key or shape checks, use rawget or isType.

notContains

Assertion:notContains(value: any): ()

The exact inverse of contains, including the unsupported-type behaviour.

Subject type Passes when Failure message
string The string does not contain value as a literal substring. Assertion failed: expected string to not contain {value}, but it did
table No value in the table is == to value. Assertion failed: expected table to not contain {value}, but it did
anything else Never — raises immediately. notContains() not supported for type {typeof(value)}
Parameter Type Description
value any The substring or value that must be absent.

Failure message caveats

Messages are built with tostring, so two different values can produce identical text — a number and its string form are indistinguishable in the output. When a message looks confusing, assert the type first with isType to pin it down.

Next

  • Runner — how a raised assertion becomes a line in the report.
  • Types — the Assertion type definition.