quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.53k stars 2.61k forks source link

[FR] Ability to tag/annotate tests to explicitly enable DevServices on a per-test basis #24241

Open GavinRay97 opened 2 years ago

GavinRay97 commented 2 years ago

Description

Zulip discussion link: https://quarkusio.zulipchat.com/#narrow/stream/187030-users/topic/Enable.20DevServices.20only.20for.20specific.20tests.3F

I have an unusual application, it provides support for a very large number of datasources. So in my deps, I have:

implementation("io.quarkus:quarkus-jdbc-db2")
implementation("io.quarkus:quarkus-jdbc-h2")
implementation("io.quarkus:quarkus-jdbc-mariadb")
implementation("io.quarkus:quarkus-jdbc-mssql")
implementation("io.quarkus:quarkus-jdbc-mysql")
implementation("io.quarkus:quarkus-jdbc-oracle")
implementation("io.quarkus:quarkus-jdbc-postgresql")
implementation("io.quarkus:quarkus-mongodb-client")

Obviously, it wouldn't be good to start half a dozen Docker container services for every dev/test run. So for now, I'm using manual Testcontainers in my tests:

@QuarkusTest
@Testcontainers
abstract class MongoContainerTest {
    companion object {
        @Container
        val mongo: MongoDBContainer = MongoDBContainer("mongo:5.0.6")
        val mongoDatabaseName = "test"

        lateinit var mongoClient: MongoClient
        lateinit var mongoDatabase: MongoDatabase

        @BeforeAll
        @JvmStatic
        fun initialize() {
            mongo.start()
            mongoClient = MongoClient(mongo.containerIpAddress, mongo.getMappedPort(27017))
            mongoDatabase = mongoClient.getDatabase(mongoDatabaseName)
        }
    }
}
@QuarkusTest
@Testcontainers
class MongoTest : MongoContainerTest() {}

It would be nice to be able to annotate or tag my tests somehow to still be able to benefit from DevServices, maybe something like:

@QuarkusTest
@QuarkusTag("postgres")
class PostgresTest {}
quarkus.datasource.mypostgres.devservices.enabled.whenannotatedwith = "postgres"

Implementation ideas

No response

quarkus-bot[bot] commented 2 years ago

/cc @stuartwdouglas

GavinRay97 commented 2 years ago

Easier said than done, but maybe something like:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.Type)
public @interface DevService {
    public String service();
    public Map<String, Object> config() default Map.of();
}

abstract class DevServicesBase {
    List<DevService> getDevServicesEnabledForClass(Class<?> clazz) {
        List<DevService> devServices = new ArrayList<>();

        if (clazz.isAnnotationPresent(DevService.class)) {
            DevService devService = clazz.getAnnotation(DevService.class);
            devServices.add(devService);
        }

        // Handle inherited classes/interfaces, etc

        return devServices;
    }
}

@QuarkusTest
@DevService(
    service = "datasource",
    config = {
        @DevService.Config(key = "datasource-name", value = "postgres1"),
        @DevService.Config(key = "image-name", value = "postgres:14"),
        @DevService.Config(key = "port", value = "5432"),
    }
)
class PostgresTest {}