diff --git a/suite/src/commonMain/kotlin/SuiteDsl.kt b/suite/src/commonMain/kotlin/SuiteDsl.kt index f85e03f..c584a73 100644 --- a/suite/src/commonMain/kotlin/SuiteDsl.kt +++ b/suite/src/commonMain/kotlin/SuiteDsl.kt @@ -16,6 +16,7 @@ package opensavvy.prepared.suite +import opensavvy.prepared.suite.annotations.TestEntrypoint import opensavvy.prepared.suite.config.Context import opensavvy.prepared.suite.config.TestConfig import opensavvy.prepared.suite.config.plus @@ -83,6 +84,7 @@ interface SuiteDsl : PreparedDsl { * To learn more about the available configuration options, see the subtypes of [TestConfig.Element]. */ @PreparedDslMarker + @TestEntrypoint fun suite( name: String, config: TestConfig = TestConfig.Empty, @@ -119,6 +121,7 @@ interface SuiteDsl : PreparedDsl { * To learn more about the available configuration options, see the subtypes of [TestConfig.Element]. */ @PreparedDslMarker + @TestEntrypoint fun test( name: String, config: TestConfig = TestConfig.Empty, @@ -131,6 +134,7 @@ interface SuiteDsl : PreparedDsl { DeprecationLevel.WARNING ) @PreparedDslMarker + @TestEntrypoint fun test( name: String, context: CoroutineContext = EmptyCoroutineContext, diff --git a/suite/src/commonMain/kotlin/annotations/TestEntrypoint.kt b/suite/src/commonMain/kotlin/annotations/TestEntrypoint.kt new file mode 100644 index 0000000..36fe825 --- /dev/null +++ b/suite/src/commonMain/kotlin/annotations/TestEntrypoint.kt @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025, OpenSavvy and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package opensavvy.prepared.suite.annotations + +/** + * Annotates functions that are test entrypoints. + * + * These functions accept a first `String` parameter that is the name of + * the test or test suite. + * + * These functions usually accept a last parameter that is the body of the test. + * It is assumed that a thrown exception means a test failure, + * and no thrown exceptions means a test success. + */ +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.SOURCE) +annotation class TestEntrypoint -- 2.51.2 From 5417fde99a1f811dff114b543e0a483cd93e0044 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Sat, 9 Aug 2025 12:50:13 +0200 Subject: [PATCH 2/5] feat(suite): Added the @ExperimentalPreparedApi annotation This annotation allows us to release features that are not completely stable. --- suite/src/commonMain/kotlin/SuiteDsl.kt | 4 +++ .../annotations/ExperimentalPreparedApi.kt | 26 +++++++++++++++++++ .../kotlin/annotations/TestEntrypoint.kt | 3 ++- 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 suite/src/commonMain/kotlin/annotations/ExperimentalPreparedApi.kt diff --git a/suite/src/commonMain/kotlin/SuiteDsl.kt b/suite/src/commonMain/kotlin/SuiteDsl.kt index c584a73..2ff2b12 100644 --- a/suite/src/commonMain/kotlin/SuiteDsl.kt +++ b/suite/src/commonMain/kotlin/SuiteDsl.kt @@ -16,6 +16,7 @@ package opensavvy.prepared.suite +import opensavvy.prepared.suite.annotations.ExperimentalPreparedApi import opensavvy.prepared.suite.annotations.TestEntrypoint import opensavvy.prepared.suite.config.Context import opensavvy.prepared.suite.config.TestConfig @@ -83,6 +84,7 @@ interface SuiteDsl : PreparedDsl { * * To learn more about the available configuration options, see the subtypes of [TestConfig.Element]. */ + @OptIn(ExperimentalPreparedApi::class) @PreparedDslMarker @TestEntrypoint fun suite( @@ -120,6 +122,7 @@ interface SuiteDsl : PreparedDsl { * * To learn more about the available configuration options, see the subtypes of [TestConfig.Element]. */ + @OptIn(ExperimentalPreparedApi::class) @PreparedDslMarker @TestEntrypoint fun test( @@ -128,6 +131,7 @@ interface SuiteDsl : PreparedDsl { block: suspend TestDsl.() -> Unit, ) + @OptIn(ExperimentalPreparedApi::class) @Deprecated( "Prefer injecting the coroutine context using the `Context` test configuration.", ReplaceWith("test(name, config + Context(context), block)", "opensavvy.prepared.suite.config.*"), diff --git a/suite/src/commonMain/kotlin/annotations/ExperimentalPreparedApi.kt b/suite/src/commonMain/kotlin/annotations/ExperimentalPreparedApi.kt new file mode 100644 index 0000000..172b672 --- /dev/null +++ b/suite/src/commonMain/kotlin/annotations/ExperimentalPreparedApi.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025, OpenSavvy and contributors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package opensavvy.prepared.suite.annotations + +@RequiresOptIn("This is part of an experimental API of the Prepared framework. It could change or be removed without warnings.") +annotation class ExperimentalPreparedApi( + /** + * URL to get more information about the experimental status of this specific API. + */ + @Suppress("unused") + val trackingUrl: String, +) diff --git a/suite/src/commonMain/kotlin/annotations/TestEntrypoint.kt b/suite/src/commonMain/kotlin/annotations/TestEntrypoint.kt index 36fe825..69a732b 100644 --- a/suite/src/commonMain/kotlin/annotations/TestEntrypoint.kt +++ b/suite/src/commonMain/kotlin/annotations/TestEntrypoint.kt @@ -27,5 +27,6 @@ package opensavvy.prepared.suite.annotations * and no thrown exceptions means a test success. */ @Target(AnnotationTarget.FUNCTION) -@Retention(AnnotationRetention.SOURCE) +@Retention(AnnotationRetention.BINARY) +@ExperimentalPreparedApi("https://gitlab.com/opensavvy/groundwork/prepared/-/issues/86") annotation class TestEntrypoint -- 2.51.2 From e4bb5f82db952d8e349ff367a62ccbbb3bc67926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 1 Oct 2025 14:21:15 +0200 Subject: [PATCH 3/5] docs(website): Highlight more features in the home page --- docs/website/docs/index.md | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/docs/website/docs/index.md b/docs/website/docs/index.md index 8cab0c3..29166d9 100644 --- a/docs/website/docs/index.md +++ b/docs/website/docs/index.md @@ -29,13 +29,27 @@ suite("My test suite") { } ``` -Additionally, Prepared exposes many advanced features: +Prepared's eponymous feature, [prepared values](features/prepared-values.md), allow declaring coroutine-aware fixtures that are initialized once for each test they are mentioned in: -- [Isolated test fixtures](features/prepared-values.md), +```kotlin +val database by prepared { + Database.connect() +} + +test("Verify the connection") { + check(database().isConnected) +} +``` + +Additionally, Prepared exposes many other features: + +- [Shared test fixtures](features/shared-values.md), - [Time control](features/time.md), - [Background task management](features/async.md)¸ - [Randomness control](features/random.md), - [Temporary filesystems](features/files.md), +- [Easy test parametrization](features/parameterize.md), +- Compatibility for [Ktor](features/compat-ktor.md), [Arrow](features/compat-arrow.md), [Gradle](features/compat-gradle.md)… - …and [more](features/index.md). ## Prepared isn't a test runner -- 2.51.2 From bbe1c05dfc0b91ae67b90a6c7a2284d6d7693dc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 1 Oct 2025 14:31:23 +0200 Subject: [PATCH 4/5] docs(website): Clean up the Atrium description --- docs/website/docs/tutorials/index.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/website/docs/tutorials/index.md b/docs/website/docs/tutorials/index.md index 49a2b8f..26c1337 100644 --- a/docs/website/docs/tutorials/index.md +++ b/docs/website/docs/tutorials/index.md @@ -95,7 +95,7 @@ Prepared doesn't include a built-in test runner. ## Assertion libraries -Assertion libraries provide utilities for verifying the state of data structures. Prepared is compatible with all assertion libraries that throw exceptions (all the ones we know). +Assertion libraries provide utilities for verifying the state of data structures. Prepared is compatible with all assertion libraries that throw exceptions. Here are a few popular choices: @@ -184,10 +184,9 @@ Here are a few popular choices: === "Atrium" - [Atrium](https://atriumlib.org/) is a Kotlin library inspired by AssertJ with two api styles, fluent and infix. - The following shows the infix api (take a look at the [examples in the docs](https://github.com/robstoll/atrium?tab=readme-ov-file#examples) for fluent). + [Atrium](https://atriumlib.org/) is a Kotlin library inspired by AssertJ with two API styles: fluent and infix. - **Usage** + **Infix usage** ```kotlin // Equality check @@ -206,6 +205,8 @@ Here are a few popular choices: } ``` + You can learn more about Atrium assertions [here](https://github.com/robstoll/atrium?tab=readme-ov-file#examples). + **Configuration** Add a dependency on `ch.tutteli.atrium:atrium-fluent` or `ch.tutteli.atrium:atrium-infix`. -- 2.51.2 From 5c8b653b1c9c99d4aa5c1c9aa380420245836bef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20=E2=80=9CCLOVIS=E2=80=9D=20Canet?= Date: Wed, 1 Oct 2025 14:38:38 +0200 Subject: [PATCH 5/5] docs(website): Document how to configure the TestBalloon IntelliJ plugin --- docs/website/docs/index.md | 8 +++++--- runners/runner-testballoon/README.md | 8 ++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/docs/website/docs/index.md b/docs/website/docs/index.md index 29166d9..48be74c 100644 --- a/docs/website/docs/index.md +++ b/docs/website/docs/index.md @@ -54,7 +54,7 @@ Additionally, Prepared exposes many other features: ## Prepared isn't a test runner -The goal of Prepared is to simplify how we declare tests, how we go from a thought to code. Test runners are libraries that execute test batteries and report results to your build system. Prepared isn't a test runner, but [it is compatible with a few existing ones](tutorials/index#test-runners). +The goal of Prepared is to simplify how we declare tests: how we go from a thought to code. Test runners are libraries that execute test batteries and report results to your build system. Prepared isn't a test runner, but [it is compatible with a few existing ones](tutorials/index#test-runners). ## Prepared isn't an assertion library @@ -62,6 +62,8 @@ Assertion libraries provide utilities to compare values. Popular choices are [Ko Instead of any specific assertion libraries, we recommend using [Power Assert](https://kotlinlang.org/docs/power-assert.html), which is able to generate good error messages from regular Kotlin code, without needing an assertion library at all. -## Prepared isn't an IntelliJ plugin (yet?) +## Prepared isn't an IntelliJ plugin -Prepared is a simple Kotlin library. It doesn't have a Gradle plugin, nor does it have an IntelliJ plugin. Test are reported by the runner, so your IDE can display the test report. However, IntelliJ doesn't know which lines are tests or not, so it cannot display the small green triangle to select which tests to execute. +Prepared is a simple Kotlin library. It doesn't have a Gradle plugin, nor does it have an IntelliJ plugin. + +If you use the [TestBalloon runner](tutorials/index.md#test-runners), Prepared tests are supported by the TestBalloon IntelliJ plugin. [Learn how to configure it](https://prepared.opensavvy.dev/api-docs/runners/runner-testballoon/index.html). diff --git a/runners/runner-testballoon/README.md b/runners/runner-testballoon/README.md index f34afb8..58d5fd7 100644 --- a/runners/runner-testballoon/README.md +++ b/runners/runner-testballoon/README.md @@ -55,3 +55,11 @@ val MyMixedTestSuite by testSuite { } } ``` + +## IntelliJ plugin + +The [TestBalloon IntelliJ plugin](https://plugins.jetbrains.com/plugin/27749-testballoon) can be configured to recognize Prepared tests and suites. + +Once you installed the plugin, open “[File | Settings | Tools | TestBalloon](jetbrains://idea/settings?name=Tools--TestBalloon)“, open “Discovery settings”. In the field “Test discoverable annotations“, add `opensavvy.prepared.suite.annotations.TestEntrypoint` to the end, using a space character to separate it with existing values. Save your settings. You may need to reload your build. + +You should see the typical green triangles in the margin of Prepared tests and suites, allowing to run or debug a single test.