Mettle is a unit and behavioral testing framework. It includes a robust set of assertions (and refutations, a la Ruby's MiniTest), pure mock objects, and a runner that makes testing easy. Create a test suite by creating a child of $mettle.test_suite_proto
. Add tests (any verb that begins with "test" is a test). Run tests by calling "run_tests()".
N.B. Testing frameworks and tests are hard to secure. Remove your tests (and remove Mettle) before you ship!
Behavior of the object under test is checked using assertions and refutations. Assertions claim that an expression about the state or behavior of the object under test is true. Refutations, on the other hand, claim that an expression is false.
this:assert():equal(a, b) => /* a & b must be equal */
this:refute():equal(a, b) => /* a & b must NOT be equal */
In the example above, "equal()" is a predicate. Mettle includes a useful set of predicates. If used without a predicate, assert()
and refute()
test whether an expression is true or false.
Mocks are useful for testing the interaction between objects. A mock responds in a predictable way to specific verb calls made by the object under test. When the test is complete, Mettle verifies that the expected interactions occurred.
this:mock("dummy") => /* a name is required */
this:mock("dummy", ["length" -> 5]) => /* responds to "length" and returns 5 */
In the example above, if the method length()
is not subsequently called on the mock, the test will fail!
none test_suite:run_tests([STR pattern])
Runs the tests in the test suite. If an optional pattern is specified, runs only the tests that match pattern.
test_suite:run_tests("initializing")
ANON assertion this:assert([ANY value [, STR message]])
Used within a test suite test verb. If called with a value, raises an error if value is false. Otherwise, returns an assertion object. The optional message describes the test failure.
this:assert(1) => /* success */
this:assert(0) => /* raises error */
this:assert() => assertion
ANON refutation this:refute([ANY value [, STR message]])
Used within a test suite test verb. If called with a value, raises an error if value is true. Otherwise, returns an refutation object. The optional message describes the test failure.
this:refute(0) => /* success */
this:refute(1) => /* raises error */
this:refute() => refutation
ANON mock this:mock(STR name [, MAP verbs])
Used within a test suite test verb. Defines a mock object. The name is required. The optional map of verbs defines the verbs the mock responds to, and their return values.
this:mock("test") => /* empty mock */
this:mock("dummy", ["foo" -> 1, "bar" -> 2]) => /* mock that responds to foo() and bar() */
none assertion:test(ANY value, LIST|STR message, ANY other)
Tests value. If value is false, raises an error.
When raising an error, the first argument to raise()
is the magic string "-*-failed-*-". If message is a list, the second argument is the first element of the list (the assertion failure message); otherwise it is message. The third argument is other.
none refutation:test(ANY value, LIST|STR message, ANY other)
Tests value. If value is true, raises an error.
When raising an error, the first argument to raise()
is the magic string "-*-failed-*-". If message is a list, the second argument is the first element of the list (the refutation failure message); otherwise it is message. The third argument is other.
test test:case_matters(ANY arg)
If arg is true, makes the test case sensitive. By default, tests are not case sensitive.
this:assert():case_matters(0):equal("Foo", "foo") => /* succeeds */
this:refute():case_matters(1):equal("Foo", "foo") => /* succeeds */
none test:equal(ANY val1, ANY val2)
Tests whether or not val1 and val2 are equal.
this:assert():equal(1, 1) => /* succeeds */
this:refute():equal(1, 1) => /* fails */
none test:is_true(ANY val)
Tests whether or not val is true.
this:assert():is_true(1) => /* succeeds */
this:refute():is_true(1) => /* fails */
none test:is_false(ANY val)
Tests whether or not val is false.
this:assert():is_false(0) => /* succeeds */
this:refute():is_false(0) => /* fails */
none test:matches(STR subject, STR pattern)
Tests whether or not subject matches pattern using the match()
builtin.
this:assert():matches("foobar", "oo") => /* succeeds */
this:refute():matches("foobar", "aa") => /* succeeds */
none test:is_member(ANY element, LIST list)
none test:has_value(ANY value, MAP map)
Tests whether or not element (or value) is in list (or map).
this:assert():is_member(1, {1}) => /* succeeds */
this:refute():has_value(1, [1 -> 2]) => /* succeeds */
none test:is_index(INT index, LIST list)
none test:has_key(ANY key, MAP map)
Tests whether or not index (or key) is in list (or map).
this:assert():is_index(1, {2}) => /* succeeds */
this:refute():has_key(1, [2 -> 1]) => /* succeeds */