Assert
The built-in testing DSL: describe, it, before, after, and assertion helpers.
Everything here is always in scope — no import, and no separate test runner. Write a test file and run it with kex:
describe "arithmetic" do
it "adds numbers" do
assert(1 + 1 == 2)
end
it "multiplies numbers" do
Assert.equal(3 * 4, 12)
end
end
$ kex my_test.kex
arithmetic
✓ adds numbers
✓ multiplies numbers
Output uses ✓ / ✗ markers and nests by describe depth. A failing assert marks its test failed and moves on; the rest of the suite still runs.
A file named <name>.spec.kex automatically loads the declarations of <name>.kex beside it, so a spec needs no import and no main wrapper.
function describe
describe(label: String, block: Block<Void>) -> Void
Groups related test cases under a label, and runs them.
The block is called immediately. describe blocks nest, and the output is indented to match. This is a foul function — it prints.
Parameters
label- what this group is about
block- the tests, and any nested groups
Examples
describe "String" do
describe "count" do
it "returns the character count" do
assert("hello".count == 5)
end
end
end
function it
it(label: String, block: Block<Void>) -> Void
Defines a single test case, and runs it.
The block runs, and anything thrown inside it — typically a failed assert — marks the test failed without aborting the rest of the suite. This is a foul function — it prints.
Parameters
label- what this case establishes, phrased as a claim
block- the case body
Examples
it "returns true for even numbers" do
assert(2.even?)
assert(!3.even?)
end
One behaviour per case reads better than one big case
it "trims leading whitespace" do
Assert.equal(" hi".trim, "hi")
end
it "trims trailing whitespace" do
Assert.equal("hi ".trim, "hi")
end
function before
before(block: Block<Void>) -> Void
before(block: Atom) -> Block<Void> -> Void
Registers setup to run before the current group's tests.
before { ... } and before(:each) { ... } run before every test in the group; before(:all) { ... } runs once before the group's first test, following RSpec's scope convention.
Parameters
block- the setup to run
Examples
describe "the parser" do
before do
Mock.FS.file("input.txt", "one\ntwo\n")
end
it "reads two lines" do
Assert.equal(FS.File.readLines("input.txt").or([]).count, 2)
end
end
function after
after(block: Block<Void>) -> Void
after(block: Atom) -> Block<Void> -> Void
Registers cleanup to run after the current group's tests.
Defaults to :each. Cleanup is unconditional — it runs whether the test passed or failed — and inner per-test hooks run before outer hooks.
Parameters
block- the cleanup to run
Examples
after do
FS.File.delete("tmp/out.txt")
end
function assert
assert(value: Bool) -> Bool
assert(value: Bool) -> String -> Bool
Fails the enclosing it when value is falsy.
The primitive every other assertion is built on. Prefer the Assert helpers where one fits — they report what was expected and what arrived, which a bare assert cannot.
Parameters
value- the condition that must hold
Returns the value, when it held
Examples
assert(42 == 42)
assert("hello".count == 5)
module Assert
Focused assertions, each reporting what was expected and what arrived.
These are ordinary Kex stdlib functions layered on the primitive assert, so adding another helper does not require compiler or runtime work.
Assert.equal("hi".upperCase, "HI")
Assert.some(users.first)
Assert.ok(Integer.parse("42"))
equal
equal(actual: A, expected: A) -> Bool
Fails unless actual equals expected, reporting both.
The assertion to reach for by default: a failure tells you what arrived, which assert(a == b) does not.
Parameters
actual- the value produced
expected- the value it should equal
Returns true when they are equal
Examples
Assert.equal("hi".upperCase, "HI")
Assert.equal([1, 2, 3].sum, 6)
Assert.equal(config.get(:port), Just(8080))
notEqual
notEqual(actual: A, expected: A) -> Bool
Fails when actual equals expected.
Parameters
actual- the value produced
expected- the value it should differ from
Returns true when they differ
Examples
Assert.notEqual(newId, oldId)
truthy
truthy(value: A) -> Bool
Fails unless value is truthy — anything except false, None and ().
Parameters
value- the value to test
Returns true when the value is truthy
Examples
Assert.truthy("hello".contains?("ell"))
falsy
falsy(value: A) -> Bool
Fails unless value is falsy — false, None or ().
Parameters
value- the value to test
Returns true when the value is falsy
Examples
Assert.falsy([].any? { |x| x > 0 })
some
some(value: A?) -> Bool
Fails unless value is a Just.
Parameters
value- the optional to test
Returns true when a value is present
Examples
Assert.some([1, 2].first)
Assert.some(config.get(:host))
none
none(value: A?) -> Bool
Fails unless value is None.
Parameters
value- the optional to test
Returns true when there is no value
Examples
Assert.none([].first)
Assert.none("abc".to(Integer))