lyng/docs/Testing.md

3.1 KiB

Testing and Assertions

Lyng provides several built-in functions for testing and verifying code behavior. These are available in all scripts.

Basic Assertions

assert

Assert that a condition is true.

assert(condition, message=null)
  • condition: A boolean expression.
  • message (optional): A string message to include in the exception if the assertion fails.

If the condition is false, it throws an AssertionFailedException.

assert(1 + 1 == 2)
assert(true, "This should be true")

assertEquals and assertEqual

Assert that two values are equal. assertEqual is an alias for assertEquals.

assertEquals(expected, actual)
assertEqual(expected, actual)

If expected != actual, it throws an AssertionFailedException with a message showing both values.

assertEquals(4, 2 * 2)
assertEqual("hello", "hel" + "lo")

assertNotEquals

Assert that two values are not equal.

assertNotEquals(unexpected, actual)

If unexpected == actual, it throws an AssertionFailedException.

assertNotEquals(5, 2 * 2)

Exception Testing

assertThrows

Assert that a block of code throws an exception.

assertThrows(code)
assertThrows(expectedExceptionClass, code)
  • expectedExceptionClass (optional): The class of the exception that is expected to be thrown.
  • code: A lambda block or statement to execute.

If the code does not throw an exception, an AssertionFailedException is raised. If an expectedExceptionClass is provided, the thrown exception must be of that class (or its subclass), otherwise an error is raised.

assertThrows returns the caught exception object if successful.

// Just assert that something is thrown
assertThrows { 1 / 0 }

// Assert that a specific exception class is thrown
assertThrows(NoSuchElementException) { 
    [1, 2, 3].findFirst { it > 10 } 
}

// You can use the returned exception
val ex = assertThrows { throw Exception("custom error") }
assertEquals("custom error", ex.message)

Other Validation Functions

While not strictly for testing, these functions help in defensive programming:

require

require(condition, message="requirement not met")

Throws an IllegalArgumentException if the condition is false. Use this for validating function arguments.

If we want to evaluate the message lazily:

require(condition) { "requirement not met: %s"(someData) }

In this case, formatting will only occur if the condition is not met.

check

check(condition, message="check failed")

Throws an IllegalStateException if the condition is false. Use this for validating internal state.

With lazy message evaluation:

check(condition) { "check failed: %s"(someData) }

In this case, formatting will only occur if the condition is not met.

TODO

It is easy to mark some code and make it throw a special exception at cone with:

TODO()

or

TODO("some message")

It raises an NotImplementedException with the given message. You can catch it as any other exception when necessary.

Many IDE and editors have built-in support for marking code with TODOs.