lyng/docs/Testing.md

122 lines
3.1 KiB
Markdown

# 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`.
```lyng
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.
```lyng
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`.
```lyng
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.
```lyng
// 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.