Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Legibilidade em testes: do caos à clareza

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
Avatar for Henrique Lopes Henrique Lopes
October 12, 2023
120

Legibilidade em testes: do caos à clareza

Avatar for Henrique Lopes

Henrique Lopes

October 12, 2023

Transcript

  1. • 😬 Como escrever testes legíveis • ✅ Como escrever

    testes manuteníveis Sobre a apresentação
  2. • 😬 Como escrever testes legíveis • ✅ Como escrever

    testes manuteníveis • ❌ Como usar ferramentas de testes Sobre a apresentação
  3. • 😬 Como escrever testes legíveis • ✅ Como escrever

    testes manuteníveis • ❌ Como usar ferramentas de testes • ❌ Quais testes criar para meu código Sobre a apresentação
  4. • Con fi ança no código • Regressão • Prática

    de mercado Por que criar testes automatizados?
  5. • Meu teste aumenta a chance que um bug seja

    exposto em meu sistema? Preocupações no momento da escrita do teste
  6. • Meu teste aumenta a chance que um bug seja

    exposto em meu sistema? • O meu teste vai me ajudar a manter o sistema? Preocupações no momento da escrita do teste
  7. Maurício Aniche "As with production code, we must put extra

    effort into writing high-quality test code bases so they can be maintained and developed sustainably.”
  8. Maurício Aniche "As with production code, we must put extra

    effort into writing high-quality test code bases so they can be maintained and developed sustainably.”
  9. Maurício Aniche "As with production code, we must put extra

    effort into writing high-quality test code bases so they can be maintained and developed sustainably.”
  10. Estratégias para tornar meu teste mais rápido •Criar suíte de

    testes diferentes •Testes rápidos •Testes lentos
  11. Estratégias para tornar meu teste mais rápido •Criar suíte de

    testes diferentes •Testes unitários •Testes de integração
  12. @Test void purchaseSucceedsWhenEnoughInventory() { Product paperclip = new Product(1L, "Paperclip");

    Store store = new Store(); store.addInventory(paperclip, 100); Customer customer = new Customer(); assertTrue(customer.purchase(store, paperclip, 10)); assertEquals(90, store.getInventory(paperclip)); } ❌
  13. @Test void purchaseSucceedsWhenEnoughInventory() { //Arrange Product paperclip = new Product(1L,

    "Paperclip"); Store store = new Store(); store.addInventory(paperclip, 100); Customer customer = new Customer(); //Act boolean purchaseSucceeded = customer.purchase(store, paperclip,10); //Assert assertTrue(purchaseSucceeded); assertEquals(90, store.getInventory(paperclip)); } ✅
  14. @Test @DisplayName("increases balance when a deposit is made") void increaseBalanceWhenDepositIsMade()

    { BankAccount account = new BankAccount(100); account.deposit(100); assertEquals(200, account.getBalance()); } ✅
  15. @Test void categoryQueryParameter() throws Exception { List<ProductEntity> products = List.of(

    new ProductEntity().setId("1").setName("Envelope").setCategory("Office").setDescription("An Envelope").setStockAmount(1), //Mais objetos de produtos sendo criados ); for (ProductEntity product : products) { template.execute(createSqlInsertStatement(product)); } String responseJson = client.perform(get("/products?category=Office")) .andExpect(status().is(200)) .andReturn().getResponse().getContentAsString(); assertThat(toDTOs(responseJson)) .extracting(ProductDTO::getId) .containsOnly("1", "2"); } ❌
  16. @Test public void categoryQueryParameter() throws Exception { insertIntoDatabase( createProductWithCategory("1", "Office"),

    createProductWithCategory("2", "Office"), createProductWithCategory("3", "Hardware") ); String responseJson = requestProductsByCategory("Office"); assertThat(toDTOs(responseJson)) .extracting(ProductDTO::getId) .containsOnly("1", "2"); } ✅
  17. @Test @DisplayName("should return username derived from full name") void shouldReturnUsernameDerivedFromFullname()

    { var user = new User("Henrique", "Lopes Nóbrega", "[email protected]", LocalDate.parse("2000-09-12"), "+5584.....", "Rua Pipipi Popopo", "12345678910"); var username = user.getUsername(); assertThat(username).isEqualTo("henrique.nobrega"); } ❌
  18. @Test @DisplayName("should return username derived from full name") void shouldReturnUsernameDerivedFromFullname()

    { var user = anUser("Henrique", "Lopes Nóbrega"); var username = user.getUsername(); assertThat(username).isEqualTo("henrique.nobrega"); } ✅
  19. @Test @DisplayName("should return username derived from full name") void shouldReturnUsernameDerivedFromFullname()

    { var user = anUser(); //?? var username = user.getUsername(); assertThat(username).isEqualTo("henrique.nobrega"); } Mas cuidado para não esconder demais 😅
  20. Testes devem ser específicos •Devem ter um motivo claro para

    existir •Devem ter uma única e clara razão para falhar
  21. @Test @DisplayName("return false when token is invalid") void returnFalseWhenTokenIsInvalid() {

    // Para o token ser válido: // tamanho >= 10 // não pode ter número // precisa ter sido emitido nas últimas 48h // testa tamanho < 10 // testa se tem numero // testa se é mais antigo que 48h } ❌
  22. @Test @DisplayName("return false when token has not necessary length") void

    returnFalseWhenTokenHasNotNecessaryLength() { /*...*/ } @Test @DisplayName("return false if token has number") void returnFalseIfTokenHasNumber() { /*…*/ } @Test @DisplayName("return false if token has expired") void returnFalseIfTokenHasExpired() { /*...*/ } ✅
  23. Testes devem ser isolados •Cada teste prepara o que precisa

    •Cada teste limpa o que usa •Pode ser executado independente ou em conjunto
  24. Testes devem ser determinísticos •Con fi ança na suíte de

    testes •Causas principais para não determinismo •Concorrência
  25. Testes devem ser determinísticos •Con fi ança na suíte de

    testes •Causas principais para não determinismo •Concorrência •Async wait
  26. Testes devem ser determinísticos •Con fi ança na suíte de

    testes •Causas principais para não determinismo •Concorrência •Async wait •Dependência da execução de testes
  27. public class OrderBuilder { private Long orderId = 1L; private

    Customer customer = new Customer(...); /** … */ public OrderBuilder withId(Long orderId) { this.orderId = orderId; return this; } /** ... */ public Order build() { Order order = new Order(orderId, customer, discountRate, couponCode); orderItems.forEach(order::addOrderItem); return order; } }
  28. Testes devem ser fáceis de escrever •Escreva a infraestrutura necessária

    •Test Data Builders •Object Mother •Page Object
  29. public class LoginPage { private WebDriver driver; private By username

    = By.id("username"); private By password = By.id("password"); private By loginBtn = By.id("login"); public LoginPage(WebDriver driver) { this.driver = driver; } public HomePage login(String user, String pass) { driver.findElement(username).sendKeys(user); driver.findElement(password).sendKeys(pass); driver.findElement(loginBtn).click(); return new HomePage(driver); } }
  30. 1. Rápidos 2. Legíveis 3. Sensíveis ao comportamento 4. Especí

    fi cos 5. Isolados 6. Determinísticos 7. Fáceis de escrever