Se você já escreveu testes em Kotlin, sabe que uma das maiores dores de cabeça é decifrar mensagens de erro genéricas. Aquele AssertionError: expected true but was false que não diz absolutamente nada sobre o que deu errado. Para resolver isso, muita gente recorre a bibliotecas como AssertJ ou Kotest Assertions — mas e se o próprio compilador pudesse gerar mensagens detalhadas automaticamente?
É exatamente isso que o Power-Assert faz. Trata-se de um plugin oficial do compilador Kotlin, mantido pela JetBrains, que transforma assertions simples em mensagens ricas mostrando o valor de cada subexpressão. Neste artigo, vamos configurar o Power-Assert do zero, explorar exemplos práticos e entender quando ele substitui (ou complementa) bibliotecas de assertion tradicionais.
Se você já domina o básico de testes em Kotlin, confira nosso guia completo de testes com JUnit 5 e MockK para contexto adicional.
O que é o Power-Assert?
O Power-Assert é um plugin do compilador Kotlin (não uma biblioteca runtime) que intercepta chamadas a funções como assert(), require(), check() e assertTrue() durante a compilação. Quando uma assertion falha, em vez de exibir uma mensagem genérica, ele gera um diagrama mostrando o valor de cada variável e expressão intermediária.
O conceito nasceu com o Groovy Power Assert e foi adaptado para Kotlin por Brian Norman no projeto kotlin-power-assert. A partir do Kotlin 2.0, a JetBrains integrou o plugin oficialmente ao compilador K2, tornando-o um cidadão de primeira classe do ecossistema.
Diferente de bibliotecas como AssertJ que exigem uma API fluente (assertThat(valor).isEqualTo(esperado)), o Power-Assert funciona com o assert nativo do Kotlin. Você escreve código idiomático e o compilador faz o trabalho pesado.
Configurando o Power-Assert no Gradle
A configuração é feita no build.gradle.kts. Primeiro, adicione o plugin:
// build.gradle.kts
plugins {
kotlin("jvm") version "2.3.20"
kotlin("plugin.power-assert") version "2.3.20"
}
Em seguida, configure quais funções o plugin deve transformar:
import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi
@OptIn(ExperimentalKotlinGradlePluginApi::class)
powerAssert {
functions = listOf(
"kotlin.assert",
"kotlin.require",
"kotlin.check",
"kotlin.test.assertTrue",
"kotlin.test.assertEquals",
"kotlin.test.assertNull"
)
}
Não esqueça de adicionar a dependência de testes:
dependencies {
testImplementation(kotlin("test"))
}
Se você usa Gradle com Kotlin DSL, esse setup já é familiar. O plugin funciona com Kotlin 2.0+ e é compatível com projetos Kotlin Multiplatform — basta configurar os includedSourceSets adequados.
Como funciona na prática
Vamos começar com um exemplo simples. Considere este teste:
import kotlin.test.Test
class UsuarioTest {
@Test
fun `nome do usuario deve ter pelo menos 3 caracteres`() {
val nome = "Al"
assert(nome.length >= 3) { "Nome muito curto" }
}
}
Sem o Power-Assert, a falha exibe apenas:
Nome muito curto
Com o Power-Assert habilitado, a saída vira:
Nome muito curto
assert(nome.length >= 3) { "Nome muito curto" }
| | |
Al 2 false
Cada subexpressão é decomposta e alinhada verticalmente. Você vê imediatamente que nome vale "Al", que length é 2 e que a comparação >= 3 resultou em false. Sem precisar adicionar logs ou usar debugger.
Exemplo com expressões complexas
O Power-Assert brilha quando a assertion envolve múltiplas condições:
data class Funcionario(val nome: String, val idade: Int, val salario: Double)
@Test
fun `dados do funcionario devem ser validos`() {
val func = Funcionario("Carlos", 150, 8500.0)
assert(func.idade in 18..65 && func.salario > 5000.0 && func.nome.isNotBlank())
}
A saída do Power-Assert:
Assertion failed
assert(func.idade in 18..65 && func.salario > 5000.0 && func.nome.isNotBlank())
| | | |
| 150 false false
Funcionario(nome=Carlos, idade=150, salario=8500.0)
Repare que o plugin identifica exatamente qual parte da expressão falhou (idade in 18..65 retornou false) e mostra o valor 150. Isso é infinitamente mais útil do que um AssertionError genérico.
Usando com assertTrue e assertEquals
O plugin não se limita ao assert. Quando você configura kotlin.test.assertTrue e kotlin.test.assertEquals na lista de funções, eles também ganham mensagens detalhadas:
import kotlin.test.Test
import kotlin.test.assertTrue
import kotlin.test.assertEquals
class CalculadoraTest {
fun somar(a: Int, b: Int) = a + b
@Test
fun `soma deve retornar valor correto`() {
val resultado = somar(2, 3)
assertEquals(6, resultado)
}
@Test
fun `resultado deve ser positivo e par`() {
val valor = somar(3, 4)
assertTrue(valor > 0 && valor % 2 == 0)
}
}
No segundo teste, a saída mostra:
Assertion failed
assertTrue(valor > 0 && valor % 2 == 0)
| | | | |
7 true 7 1 false
Fica claro que 7 % 2 resulta em 1, que não é igual a 0. Se você usa JUnit 5 com MockK no dia a dia, o Power-Assert complementa bem o workflow sem exigir mudanças na sua API de testes.
Soft assertions com Power-Assert
Uma técnica avançada é combinar o Power-Assert com soft assertions — onde múltiplas falhas são coletadas e reportadas juntas no final do teste, em vez de parar na primeira:
interface AssertScope {
fun assert(assertion: Boolean, message: (() -> String)? = null)
}
class AssertScopeImpl : AssertScope {
val errors = mutableListOf<String>()
override fun assert(assertion: Boolean, message: (() -> String)?) {
if (!assertion) {
errors.add(message?.invoke() ?: "Assertion failed")
}
}
}
fun <R> assertSoftly(block: AssertScope.() -> R): R {
val scope = AssertScopeImpl()
val result = scope.block()
if (scope.errors.isNotEmpty()) {
throw AssertionError(scope.errors.joinToString("\n"))
}
return result
}
Para que o Power-Assert transforme a função assert dentro do AssertScope, adicione-a na configuração:
powerAssert {
functions = listOf(
"kotlin.assert",
"com.exemplo.AssertScope.assert" // sua função customizada
)
}
Isso funciona porque o Power-Assert aceita qualquer função cujo último parâmetro seja String ou () -> String. Você pode criar suas próprias funções de assertion e o plugin gera os diagramas automaticamente.
Quando usar e quando não usar
O Power-Assert é excelente para:
- Testes unitários com assertions simples usando
assert,assertTrue,assertEquals - Validações em tempo de execução com
require()echeck()— veja nosso artigo sobre null safety para contexto - Projetos que valorizam simplicidade e não querem adicionar bibliotecas de assertion pesadas
- Projetos multiplataforma via KMP onde você quer assertions consistentes em todas as plataformas
Porém, ele não substitui completamente bibliotecas como Kotest Assertions quando você precisa de:
- Matchers especializados (coleções, strings, exceções)
- Assertions assíncronas para coroutines e Flow
- DSLs de assertion complexas com encadeamento fluente
A melhor abordagem é combinar: use Power-Assert para assertions diretas e uma biblioteca complementar para casos mais sofisticados. Se você está montando uma suíte de testes do zero, confira nosso tutorial de testes unitários para a base.
Limitações atuais
Algumas coisas para ficar atento:
- O plugin é experimental — a API pode mudar entre versões do Kotlin, embora esteja estável desde o Kotlin 2.0
- Requer K2 — funciona apenas com o compilador K2 (Kotlin 2.0+). Se seu projeto ainda usa o compilador legado, será preciso migrar primeiro
- Expressões inline geram melhor output — se você armazena o resultado de uma subexpressão em uma variável antes do
assert, o diagrama perde contexto - Não funciona com
assertThatdo AssertJ ou APIs fluentes — o Power-Assert precisa de uma expressão booleana direta
Power-Assert no contexto do ecossistema Kotlin
O Power-Assert se encaixa na filosofia do Kotlin de oferecer ferramentas poderosas integradas ao compilador. Assim como as sealed classes eliminaram a necessidade de bibliotecas de pattern matching, e as data classes substituíram geradores de boilerplate, o Power-Assert reduz a dependência de bibliotecas externas para testes.
Se você trabalha com Spring Boot e Kotlin, a integração é transparente — basta adicionar o plugin ao Gradle e seus testes existentes com assert ganham mensagens melhores sem nenhuma mudança de código.
Para quem está montando um projeto novo, confira também nosso post sobre Kotlin Scripting — outra feature subestimada do ecossistema que complementa bem a experiência de desenvolvimento. Se você trabalha com outras linguagens, vale comparar: Rust já oferece mensagens de assert detalhadas nativamente, e Go usa uma abordagem diferente com testify — cada ecossistema resolve testes de um jeito.
Perguntas frequentes
O Power-Assert funciona com Kotlin Multiplatform?
Sim. O plugin suporta KMP nativamente. Basta configurar os includedSourceSets para incluir os source sets desejados (commonTest, jvmTest, iosTest, etc.).
Preciso remover minhas bibliotecas de assertion existentes?
Nao. O Power-Assert complementa bibliotecas como Kotest e AssertJ. Você pode usar ambos no mesmo projeto sem conflitos.
O Power-Assert afeta a performance dos testes?
O impacto é insignificante. A transformação acontece em tempo de compilacao, nao em runtime. O unico overhead adicional e a construcao das mensagens de erro quando uma assertion falha — o que so ocorre em cenarios de falha.
Funciona com Gradle Version Catalog?
Sim. Basta declarar o plugin no version catalog e referencia-lo no build.gradle.kts usando o alias definido no catalogo.