Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/xemantic/xemantic-kotlin-test
The power-assert compatible assertions DSL and some other testing goodies - a Kotlin multiplatform testing library.
https://github.com/xemantic/xemantic-kotlin-test
assert assertion-framework assertion-library assertions domain-specific-language dsl kotlin kotlin-library kotlin-multiplatform multiplatform power-assert testing testing-framework testing-library testing-tools
Last synced: 1 day ago
JSON representation
The power-assert compatible assertions DSL and some other testing goodies - a Kotlin multiplatform testing library.
- Host: GitHub
- URL: https://github.com/xemantic/xemantic-kotlin-test
- Owner: xemantic
- License: apache-2.0
- Created: 2024-12-09T13:46:55.000Z (2 months ago)
- Default Branch: main
- Last Pushed: 2025-01-26T15:22:26.000Z (15 days ago)
- Last Synced: 2025-01-26T15:32:53.912Z (15 days ago)
- Topics: assert, assertion-framework, assertion-library, assertions, domain-specific-language, dsl, kotlin, kotlin-library, kotlin-multiplatform, multiplatform, power-assert, testing, testing-framework, testing-library, testing-tools
- Language: Kotlin
- Homepage:
- Size: 192 KB
- Stars: 7
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
# xemantic-kotlin-test
The power-assert compatible assertions DSL and some other testing goodies - a Kotlin multiplatform testing library.[
](https://central.sonatype.com/artifact/com.xemantic.kotlin/xemantic-kotlin-test)
[](https://github.com/xemantic/xemantic-kotlin-test/releases)
[](https://github.com/xemantic/xemantic-kotlin-test/blob/main/LICENSE)
[
](https://github.com/xemantic/xemantic-kotlin-test/actions/workflows/build-main.yml)
[](https://github.com/xemantic/xemantic-kotlin-test/actions/workflows/build-main.yml)
[](https://github.com/xemantic/xemantic-kotlin-test/commits/main/)
[](https://github.com/xemantic/xemantic-kotlin-test/commits/main/)
[
](https://github.com/xemantic/xemantic-kotlin-test/graphs/contributors)
[](https://github.com/xemantic/xemantic-kotlin-test/commits/main/)
[]()
[](https://github.com/xemantic/xemantic-kotlin-test/commits)
[](https://kotlinlang.org/docs/releases.html)
[](https://discord.gg/vQktqqN2Vn)
[![Bluesky](https://img.shields.io/badge/Bluesky-0285FF?logo=bluesky&logoColor=fff)](https://bsky.app/profile/xemantic.com)## Why?
I am mostly using [kotest](https://kotest.io/) library for writing test assertions in my projects.
When [power-assert](https://kotlinlang.org/docs/power-assert.html) became the official Kotlin compiler plugin, I also realized that most of the kotest assertions can be replaced with something which suits my needs much better.
Instead of writing:```kotlin
x shouldBeGreaterThanOrEqualTo 42
```I could write:
```kotlin
assert(x >= 42)
```And the power-assert will provide comprehensive error message breaking down the expression written in Kotlin into components, while displaying their values.
I am quite often asserting the state of hierarchical data structures, therefore I came up with such a syntax, following the natural language, and utilizing power-assert:
```kotlin
message should {
have(id == 42)
have(content.size == 2)
content[0] should {
be()
have(type == "text")
have("Hello" in text)
}
content[1] should {
be()
have(type == "image")
have(width >= 800)
have(height >= 600)
mediaType should {
have(type == "image/png")
}
}
}
```Now, if the image `mediaType.type` is not `PNG`, it will show:
```text
Message(id=42, content=[Text(text=Hello there), Image(path=image.png, width=1024, height=768, mediaType=MediaType(type=image/jpeg))])
containing:
Image(path=image.png, width=1024, height=768, mediaType=MediaType(type=image/jpeg))
containing:
MediaType(type=image/jpeg)
should:
have(type == "image/png")
| |
| false
image/jpeg
```In addition, the library supports:
* uniform access to project test files across non-browser platforms of a KMP project
* access to defined set of environment variables in browser platforms of a KMP project## Usage
### Setting up Gradle
#### Setting up Gradle for Kotlin Multiplatform project
In your `build.gradle.kts`:
```kotlin
plugins {
kotlin("multiplatform") version "2.1.0"
kotlin("plugin.power-assert") version "2.1.0" // replace with the latest kotlin version
}kotlin {
sourceSets {
commonTest {
depencencies {
implementation("com.xemantic.kotlin:xemantic-kotlin-test:1.8.10")
}
}}
}powerAssert {
functions = listOf(
"com.xemantic.kotlin.test.assert",
"com.xemantic.kotlin.test.have"
)
}
```#### Setting up Gradle for Kotlin JVM project
In your `build.gradle.kts`:
```kotlin
plugins {
kotlin("jvm") version "2.1.0"
kotlin("plugin.power-assert") version "2.1.0" // replace with the latest kotlin version
}dependencies {
testImplementation("com.xemantic.kotlin:xemantic-kotlin-test:1.8.10")
}powerAssert {
functions = listOf(
"com.xemantic.kotlin.test.assert",
"com.xemantic.kotlin.test.have"
)
}
```### Basic Assertions
```kotlin
assert(2 + 2 == 4)
```> [!NOTE]
> The [assert](https://kotlinlang.org/api/core/kotlin-stdlib/kotlin/assert.html) function in Kotlin stdlib is providing `assert` only for `jvm` and `native` out of all the Kotlin multiplatform targets.
> The multiplatform `assert` function can be imported from `com.xemantic.kotlin.test.assert`.### Asserting object properties
The library introduces [should](src/commonMain/kotlin/Assertions.kt) infix function, which allows you to chain assertions on an object:
```kotlin
someObject should {
// assertions go here
}
```### Type Assertions
You can assert the type of object using the [be](src/commonMain/kotlin/Assertions.kt) function:
```kotlin
someObject should {
be()
}
```> [!TIP]
> After calling `be` function with expected type, all the subsequent calls within `should {}` will have access to the properties of the expected type, like if `this`, representing `someObject`, was cast to the expected type.### Condition Assertions
Use the `have` function to assert conditions:
```kotlin
someObject should {
have(someProperty == expectedValue)
}
```### Nested Assertions
You can nest assertions for complex objects:
```kotlin
complexObject should {
have(property1 == expectedValue1)
nestedObject should {
have(nestedProperty == expectedValue2)
}
}
```### Test Context
You can obtain access to the test context like:
* Stable absolute path of the current gradle root dir, so that the test files can be used in tests of non-browser
platforms of the KMP project.
* Environment variables, accessible on almost all the platforms, including access to predefined set of environment
variables in tests of browser platforms (e.g. API keys) of the KMP project.See [TextContext](src/commonMain/kotlin/TestContext.kt) for details.
You have to add to `build.gradle.kts`:
```kotlin
val gradleRootDir: String = rootDir.absolutePath
val fooValue = "bar"tasks.withType().configureEach {
environment("GRADLE_ROOT_DIR", gradleRootDir)
environment("FOO", fooValue)
}tasks.withType().configureEach {
environment("GRADLE_ROOT_DIR", gradleRootDir)
environment("FOO", fooValue)
}tasks.withType().configureEach {
environment("GRADLE_ROOT_DIR", gradleRootDir)
environment("SIMCTL_CHILD_GRADLE_ROOT_DIR", gradleRootDir)
environment("FOO", fooValue)
environment("SIMCTL_CHILD_FOO", fooValue)
}
```and specify environment variables you are interested in. The `SIMCTL_CHILD_` is used in tests running inside emulators.
To pass environment variables to browser tests, you have to create `webpack.confg.d` folder and drop this file named `env-config.js`:
```js
const webpack = require("webpack");
const envPlugin = new webpack.DefinePlugin({
'process': {
'env': {
'FOO': JSON.stringify(process.env.FOO)
}
}
});
config.plugins.push(envPlugin);
```Pick environment variables which should be provided to browser tests.
Then you can write test like:
```kotlin
class FooTest {@Test
fun `should test against test data`() {
if (isBrowserPlatform) return // we don't have access to Gradle root dir
val testData = Path(gradleRootDir, "test-data.txt")
// ...
}@Test
fun `should use predefined environment variable`() {
val apiKey = getEnv("SOME_API_KEY")
// ...
}}
```## Development
Clone this project, and then run:
```shell
./gradlew build
```