Gerenciando o Ciclo de Vida do Playwright no Kotest
Depois de concluirmos esta aula, nós:
- Saberemos criar uma extensão customizada do Kotest que configura o Playwright antes da execução dos nossos cenários e libera os recursos reservados após a execução das especificações.
- Compreenderemos como podemos configurar nossos testes End-to-End utilizando nossa extensão customizada.
Esta aula assume que:
- Você sabe executar seus testes End-to-End utilizando o Gradle 9 (
endToEndTest).- Você está familiarizado com o Microsoft Playwright para JVM/Kotlin.
- Você sabe configurar seus testes End-to-End utilizando JUnit 6.
- Você está familiarizado com o Kotest Framework.
Criando uma Extensão Customizada no Kotest
Antes de podermos escrever testes End-to-End com o Playwright no Kotest, temos que encontrar uma maneira limpa e reutilizável de:
- Criar e configurar uma instância de
PlaywrighteBrowserantes que os cenários da especificação sejam executados (beforeSpec). - Criar um
BrowserContexte umaPagelimpos antes de cada cenário raiz (beforeContainer/beforeEach), permitindo que nossos Page Objects recebam aPagepronta para uso. - Fechar o
BrowserContextapós cada cenário (limpando cookies,localStoragee sessão de usuário autenticado) e encerrar oBrowsere o processo doPlaywrightao final da especificação (afterSpec) para liberar todos os recursos nativos. - Minimizar os impactos negativos de performance na nossa suíte de testes reutilizando o processo do navegador entre os cenários de uma mesma especificação.
O Kotest possui um modelo de extensões extremamente versátil e tipado. Se quisermos adicionar comportamento customizado ao ciclo de vida do Kotest, podemos implementar interfaces como SpecExtension, TestListener (ou BeforeSpecListener, AfterSpecListener, BeforeTestListener, AfterTestListener) ou criar uma extensão gerenciadora de recursos.
O Kotest suporta duas formas de registrar extensões:
- Extensão global: Registrada em
AbstractProjectConfige carregada automaticamente para todas as especificações da suíte. - Extensão local explícita (ou guiada por anotação/registro na Spec): Registrada apenas nas classes de especificação End-to-End que realmente precisam de um navegador.
Durante esta aula, criaremos uma extensão local configurável (PlaywrightExtension) e uma anotação opcional @PlaywrightTest por três motivos:
- Podemos configurar nossa extensão (por exemplo, escolhendo entre Chromium, Firefox ou WebKit e modo
headless) diretamente ao registrá-la. - O registro explícito documenta claramente o comportamento adicionado ao ciclo de vida da especificação, evitando “mágica invisível” de extensões globais.
- Carregamos o motor do Playwright apenas nas especificações End-to-End, mantendo os testes unitários e de integração instantâneos.
A seguir, descobriremos como podemos criar as anotações e tipos de configuração necessários.
Criando as Anotações e Opções de Configuração
Podemos criar a estrutura de configuração da nossa extensão seguindo estes passos:
Primeiro, criamos um enum BrowserTypeOption que define quais motores de navegador do Playwright podem ser escolhidos pela especificação (sendo CHROMIUM o padrão):
|
|
Segundo, se quisermos suportar configuração declarativa via anotação na classe de especificação (além do registro programático via extensions(...)), podemos criar a anotação @PlaywrightTest:
|
|
Nota sobre
@ApplyExtensionno Kotest 6:O Kotest fornece a meta-anotação
@ApplyExtension, que funciona de forma análoga ao@ExtensionAnnotationdo Spock ou@ExtendWithdo JUnit 6: qualquerSpecanotada com@PlaywrightTestativa automaticamente a extensão associada!
Vamos avançar e descobrir como implementar o inicializador e o limpador do ciclo de vida do Playwright no Kotest.
Implementando os Listeners de Ciclo de Vida do Playwright
Precisamos gerenciar dois níveis de ciclo de vida na nossa extensão do Kotest:
- Nível da Especificação (
beforeSpeceafterSpec): Inicia o processoPlaywrighte lança a instância doBrowseruma única vez por classe de especificação, porque iniciar um binário de navegador do zero é uma operação relativamente custosa. Ao final de todos os cenários da classe (afterSpec), fecha oBrowsere encerra oPlaywright. - Nível do Cenário Raiz (
beforeContainer/afterContaineroubeforeTest/afterTest): Cria umBrowserContextisolado (como uma janela anônima novinha em folha) e umaPageantes de cada teste raiz, e fecha esseBrowserContextao terminar o cenário. Isso garante que um usuário logado em um cenário já esteja deslogado no próximo!
Criando e Encerrando o Playwright, Browser e Page
Vamos implementar a classe PlaywrightExtension implementando BeforeSpecListener, AfterSpecListener, BeforeTestListener e AfterTestListener do Kotest:
|
|
Vamos analisar passo a passo o que a nossa PlaywrightExtension faz:
- No
beforeSpec(spec: Spec), ela invocaPlaywright.create()e lança o navegador configurado (CHROMIUM,FIREFOXouWEBKIT) no modoheadlessdesejado. - No
beforeTest(testCase: TestCase), quando otestCaseé um cenário raiz (testCase.descriptor.isRootTest()), ela abre umBrowserContextisolado e uma novaPage. Dessa forma, todos os blocos internosWheneThendaqueleGivencompartilham a mesma aba do navegador! - No
afterTest(testCase: TestCase, result: TestResult), ao concluir o cenário raiz, ela fecha aPagee oBrowserContext, descartando instantaneamente todos os cookies de autenticação e estado da sessão. - No
afterSpec(spec: Spec), ela fecha oBrowsere encerra o processo doPlaywright, garantindo zero vazamento de processos Chromium no sistema operacional.
Usando Nossa Extensão Customizada do Kotest
Podemos usar nossa PlaywrightExtension nas especificações End-to-End seguindo três passos simples:
- Criar uma nova classe de especificação e anotá-la com
@EndToEndTestpara que seus cenários sejam executados quando rodarmos a taskendToEndTest. - Instanciar e registrar a
PlaywrightExtensionusandoinstall(...)ouextensions(...)dentro da especificação. - Acessar
playwright.pagedentro dos nossos cenários ou Page Objects.
O código-fonte da nossa classe de especificação fica assim:
|
|
Agora sabemos criar uma extensão customizada do Kotest que configura e gerencia o ciclo de vida do Playwright e utilizá-la ao escrever testes End-to-End. Na próxima aula, integraremos essa extensão com o servidor embarcado do Spring Boot 4 e o Testcontainers! Vamos resumir o que aprendemos nesta aula.
Resumo
Esta aula nos ensinou cinco coisas:
- Podemos adicionar comportamento customizado ao ciclo de vida do Kotest implementando
BeforeSpecListener,AfterSpecListener,BeforeTestListenereAfterTestListener. - Extensões locais registradas na especificação documentam explicitamente os recursos que participam do ciclo de vida do teste.
- Devemos inicializar o
Playwrighte oBrowseruma única vez por classe de especificação (beforeSpec) para maximizar a velocidade da suíte. - Devemos criar um novo
BrowserContextePagepara cada cenário raiz (isRootTest()) e fechá-los ao final do cenário para garantir isolamento total de sessão e cookies. - Devemos encerrar o
Browsere oPlaywrightnoafterSpecpara liberar todos os processos nativos ao término da especificação.