Testando e evoluindo DSLs sem interromper os usuários
Projete APIs de DSL estáveis e teste-as com blocos de asserções legíveis.
Testando e evoluindo DSLs sem interromper os usuários é uma aula grátis de Kotlin Academy no CoddyKit. Esta é a aula 4 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Kotlin Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Kotlin Academy inclui 4 aulas no total.
Por que os testes de DSL são diferentes
Uma DSL é uma API pública. Alterações nela podem quebrar todos os pontos de chamada no código do usuário. Testar uma DSL significa verificar tanto a saída que ela produz quanto a estrutura que impõe — inclusive confirmar que construções inválidas continuam sendo erros de compilação.
Testando a saída da DSL
O teste mais simples: crie um objeto usando a DSL e faça asserções sobre o resultado renderizado ou sobre o estado interno do construtor.
@Test
fun `div contains a paragraph`() {
val result = html {
body {
div { p("Hi") }
}
}
assertTrue(result.render().contains("<p>"))
}Testando o estado do construtor
Em vez de testar a cadeia de caracteres renderizada, teste diretamente o grafo de objetos do construtor. Isso é mais resistente a alterações de formatação:
@Test
fun `server config has correct port`() {
val cfg = server {
host = "example.com"
port = 9090
}
assertEquals(9090, cfg.port)
assertEquals("example.com", cfg.host)
}Testando estruturas aninhadas
Percorra a árvore de objetos para verificar as relações de aninhamento:
@Test
fun `body contains one div`() {
val page = html { body { div { } } }
assertEquals(1, page.children
.filterIsInstance<Body>().first()
.children.filterIsInstance<Div>().size
)
}Testes de erros de compilação
Não é possível testar erros de compilação diretamente em testes unitários, mas você pode adicionar comentários como // This should NOT compile com o código que falha comentado. Alguns projetos usam a biblioteca Kotlin Compile Testing para verificar que determinado código NÃO compila.
Evoluindo uma DSL com segurança: alterações aditivas
Adicionar novos parâmetros opcionais com valores padrão ou novas funções de construção é compatível com versões anteriores. Os pontos de chamada existentes compilam sem alterações.
// Before
fun server(block: ServerConfig.() -> Unit): ServerConfig
// After — additive: new optional feature
fun server(enableMetrics: Boolean = false, block: ServerConfig.() -> Unit): ServerConfigAlteração incompatível: remoção ou renomeação
Remover ou renomear uma função da DSL quebra os pontos de chamada. Se for necessário renomeá-la, forneça um nome alternativo obsoleto e remova-o em uma versão principal futura:
@Deprecated("Use database{} instead", ReplaceWith("database(block)"))
fun db(block: DbConfig.() -> Unit) = database(block)Versionando sua DSL
Para DSLs de bibliotecas, siga o versionamento semântico. Alterações incompatíveis na DSL (funções removidas ou tipos de receptor alterados) justificam o aumento da versão principal. Documente-as em um registro de alterações.
Usando @RequiresOptIn para recursos experimentais de DSL
Marque extensões instáveis da DSL com @RequiresOptIn. Os usuários precisam habilitá-las explicitamente, evitando a dependência acidental de recursos que podem mudar:
@RequiresOptIn(message = "This DSL feature is experimental and may change")
annotation class ExperimentalDsl
@ExperimentalDsl
fun ServerConfig.enableDebug() { /*...*/ }Delegação de propriedades em DSLs
As DSLs podem usar delegação de propriedades para impor campos obrigatórios e fornecer mensagens de erro claras quando falta um valor obrigatório:
class Required<T> {
private var value: T? = null
operator fun getValue(t: Any?, p: KProperty<*>): T = value ?: error("${p.name} is required")
operator fun setValue(t: Any?, p: KProperty<*>, v: T) { value = v }
}Testes de contrato entre versões
Mantenha um conjunto de trechos de uso de referência da DSL como testes. Se uma refatoração os quebrar, o conjunto de testes detectará o problema antes dos usuários. Eles também servem como documentação viva.
Verificação rápida
Qual é o tipo mais seguro de alteração em uma DSL para manter a compatibilidade com versões anteriores?
Recapitulação: testando e evoluindo DSLs
Principais conclusões:
- Teste a saída da DSL e o estado dos objetos construtores em testes unitários
- Alterações aditivas (novas funções/parâmetros opcionais) são seguras
- Use
@Deprecated(ReplaceWith=...)para renomear sem quebrar os usuários - Use
@RequiresOptInpara recursos experimentais de DSL - Mantenha testes de uso de referência para detectar regressões entre versões
Perguntas Frequentes
A aula “Testando e evoluindo DSLs sem interromper os usuários” é grátis?
Sim — o texto completo de “Testando e evoluindo DSLs sem interromper os usuários” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Kotlin Academy, atualize para CoddyKit PRO. O curso de Kotlin Academy inclui 4 aulas no total.
O que vou aprender em “Testando e evoluindo DSLs sem interromper os usuários”?
Projete APIs de DSL estáveis e teste-as com blocos de asserções legíveis. Você pratica Kotlin Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Kotlin Academy?
Nenhuma experiência prévia é necessária. Kotlin Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 4 de 4.
Quanto tempo leva a aula “Testando e evoluindo DSLs sem interromper os usuários”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Kotlin Academy?
Sim. Cada aula de Kotlin Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- Lambda com receptor: a base da DSL
- @DslMarker: impedindo o vazamento de receptores
- Criando uma DSL de HTML/configuração segura quanto a tipos
- Testando e evoluindo DSLs sem interromper os usuários