Por que os testes unitários não salvam e quando os testes E2E são necessários
\n\nImagine: você escreveu um código perfeito em C#. Os testes unitários estão verdes, a cobertura é de 95%, a revisão de código foi aprovada. Você lança a versão, e os usuários escrevem: "O botão 'Finalizar pedido' não funciona se o carrinho tiver mais de 3 itens". Familiar?
\n\nOs testes unitários verificam métodos isoladamente. Os testes de integração verificam a conexão entre banco de dados e API. Mas os testes E2E de aplicações C# (End-to-End) são a única maneira de garantir que todo o sistema funcione como um todo: navegador, servidor, banco de dados, APIs externas. Os testes de ponta a ponta simulam as ações de um usuário real: cliques, entrada de dados, espera pelo carregamento de páginas.
\n\nNeste artigo, não vamos apenas falar teoria. Vamos mostrar como escrever testes E2E em C# usando Selenium e Playwright, como organizar o código com Page Object Model e como integrar os testes automatizados no CI/CD. Vamos lá.
\n\nO que são testes E2E C# na prática
\n\nUm teste E2E é um cenário que percorre todo o caminho do usuário: desde a abertura da página até a conclusão da ação desejada (compra, registro, envio de formulário). Para um desenvolvedor C#, isso geralmente significa:
\n\n- \n
- Iniciar o navegador (Chrome, Firefox, Edge) através do WebDriver \n
- Encontrar elementos na página (botões, campos de entrada, links) \n
- Realizar ações (clicar, digitar texto, selecionar de uma lista) \n
- Verificar o resultado esperado (uma mensagem apareceu, a URL mudou, os dados foram atualizados) \n
- Fechar o navegador e limpar os dados de teste \n
A principal diferença dos testes unitários: os testes E2E trabalham com a interface real do usuário. Eles são lentos, frágeis (dependem de seletores CSS), mas são inestimáveis para verificar cenários críticos de negócio.
\n\nFerramentas para testes E2E C#: Selenium vs Playwright
\n\nA escolha da ferramenta é a primeira questão que surge para a equipe. Vamos considerar as duas opções mais populares.
\n\nSelenium WebDriver
\nPadrão da indústria. Funciona através do WebDriver — um processo separado que controla o navegador. Suporta todos os navegadores, comunidade enorme, milhares de soluções prontas. Desvantagem: a configuração requer drivers (ChromeDriver, GeckoDriver), e os testes podem ser lentos devido às esperas.
\n\nPlaywright para .NET
\nMais recente, mas já muito popular, ferramenta da Microsoft. Funciona diretamente através do protocolo DevTools, sem camadas extras. Mais rápido, mais estável, aguarda automaticamente o carregamento dos elementos (sem Thread.Sleep explícitos). Suporta não apenas navegadores, mas também emuladores móveis.
\n\nNeste artigo, mostraremos exemplos em ambos os frameworks para que você possa comparar.
\n\nEscrevendo o primeiro teste E2E em C#: Selenium
\n\nVamos começar com o clássico. Instale o pacote via NuGet:
\n\ndotnet add package Selenium.WebDriver\ndotnet add package Selenium.Support\ndotnet add package Selenium.WebDriver.ChromeDriver\n\nAgora vamos escrever um teste para um site de exemplo (suponha que seja uma loja online). Queremos verificar se, após adicionar um produto ao carrinho, o ícone com a quantidade de itens aparece na página.
\n\nusing OpenQA.Selenium;\nusing OpenQA.Selenium.Chrome;\nusing OpenQA.Selenium.Support.UI;\n\npublic class CartE2ETests\n{\n [Fact]\n public void AddItemToCart_ShouldUpdateCartBadge()\n {\n using var driver = new ChromeDriver();\n \n // Arrange\n driver.Navigate().GoToUrl("https://demo-store.com");\n driver.Manage().Window.Maximize();\n \n // Act\n var addToCartButton = driver.FindElement(By.CssSelector(".product-card .add-to-cart"));\n addToCartButton.Click();\n \n // Wait for badge to appear\n var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(5));\n var cartBadge = wait.Until(drv => \n drv.FindElement(By.CssSelector(".cart-badge")));\n \n // Assert\n Assert.Equal("1", cartBadge.Text);\n \n driver.Quit();\n }\n}\n\n
Blogs
Book Recommendations
Leia também
Refatoração de código legado em Go: técnicas e estratégias avançadas
Clean Code em C++: princípios para escrever código legível
Fundamentos do NumPy: Arrays, Matrizes e Operações Matemáticas em Python
Princípios SOLID em Go: da teoria à prática em Golang
GraphQL API com C++: tutorial passo a passo para iniciantes