kex docs Standard Library 0.4.0-alpha kex.run ↗

Assertprelude

function describe

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.

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.

describe : String -> Block<Void> -> Void
Parameters
label String
what this group is about
block Block
the tests, and any nested groups

Returns: Void

Examples
describe "String" do
  describe "count" do
    it "returns the character count" do
      assert("hello".count == 5)
    end
  end
end

function it

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.

it : String -> Block<Void> -> Void
Parameters
label String
what this case establishes, phrased as a claim
block Block
the case body

Returns: Void

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

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.

before : Block<Void> -> Void
before : Atom -> Block<Void> -> Void
Parameters
block Block
the setup to run

Returns: Void

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

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.

after : Block<Void> -> Void
after : Atom -> Block<Void> -> Void
Parameters
block Block
the cleanup to run

Returns: Void

Examples
after do
  FS.File.delete("tmp/out.txt")
end

function assert

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.

assert : Bool -> Bool
assert : Bool -> String -> Bool
Parameters
value Bool
the condition that must hold

Returns: Bool — 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"))

function equal

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.

equal(actual, expected)
Parameters
actual A
the value produced
expected A
the value it should equal

Returns: Booltrue when they are equal

Examples
Assert.equal("hi".upperCase, "HI")
Assert.equal([1, 2, 3].sum, 6)
Assert.equal(config.get(:port), Just(8080))

function notEqual

Fails when actual equals expected.

notEqual(actual, expected)
Parameters
actual A
the value produced
expected A
the value it should differ from

Returns: Booltrue when they differ

Examples
Assert.notEqual(newId, oldId)

function truthy

Fails unless value is truthy: anything except false, None and ().

truthy(value)
Parameters
value A
the value to test

Returns: Booltrue when the value is truthy

Examples
Assert.truthy("hello".contains?("ell"))

function falsy

Fails unless value is falsy: false, None or ().

falsy(value)
Parameters
value A
the value to test

Returns: Booltrue when the value is falsy

Examples
Assert.falsy([].any? { |x| x > 0 })

function some

Fails unless value is a Just.

some(value)
Parameters
value A?
the optional to test

Returns: Booltrue when a value is present

Examples
Assert.some([1, 2].first)
Assert.some(config.get(:host))

function none

Fails unless value is None.

none(value)
Parameters
value A?
the optional to test

Returns: Booltrue when there is no value

Examples
Assert.none([].first)
Assert.none("abc".to(Integer))

function ok

Fails unless value is an Ok.

ok(value)
Parameters
value Result<A, E>
the result to test

Returns: Booltrue when the result succeeded

Examples
Assert.ok(Integer.parse("42"))

function error

Fails unless value is an Error.

error(value)
Parameters
value Result<A, E>
the result to test

Returns: Booltrue when the result failed

Examples
Assert.error(Integer.parse("4x"))