Devops Integrated Tests - QuantumBitBR/API_5SEM GitHub Wiki

DevOps - Integration Tests

Visão Geral

Conceito

O teste de integração é um nível de teste de software que verifica a interação entre diferentes módulos, componentes ou sistemas para garantir que eles funcionem corretamente quando combinados.
Ele ocorre após os testes unitários (que avaliam partes individuais do código) e antes dos testes de sistema (que verificam o software como um todo).

Fluxo de Desenvolvimento de Testes de Integração

Para o bom desenvolvimento voltado para para testes de Integração, devemos destacar uma pessoa do time para atuar como QA, pois ele será o responsável por desenvolver a dinâmica dos testes. Este documento descreve as atividades do profissional de QA (Quality Assurance) ao longo de uma sprint em equipes ágeis, com foco em integração contínua de qualidade no desenvolvimento.


Antes da Sprint (Planejamento e Preparação)

1. Participa do planejamento da sprint (Sprint Planning)

  • Entende as histórias do backlog priorizadas.
  • Ajuda a definir critérios de aceitação claros com o Product Owner (PO).
  • Estima o esforço de testes em conjunto com os desenvolvedores.

2. Prepara casos de teste antecipadamente

  • Cria casos de teste com base nas histórias e nos critérios de aceitação.
  • Inicia a elaboração de testes manuais e automatizados antes mesmo da implementação.

Durante a Sprint (Execução e Integração)

3. Trabalha lado a lado com os desenvolvedores

  • Testa os incrementos à medida que são entregues (teste contínuo).
  • Participa de testes de integração e testes de API, se necessário.
  • Fornece feedback rápido — quanto mais cedo os problemas forem detectados, melhor.

4. Automatiza testes (quando possível)

  • Integra testes automatizados ao pipeline de CI/CD.
  • Automatiza testes funcionais .

5. Participa do Daily Scrum (reunião diária)

  • Reporta bugs encontrados, dúvidas sobre critérios, dependências e impedimentos.
  • Alinha com os desenvolvedores sobre funcionalidades prontas para teste.

Final da Sprint (Revisão e Retrospectiva)

6. Garante que todas as histórias tenham passado pelos testes antes da Review

  • Valida os critérios de aceitação.
  • Confirma se a Definition of Done (DoD) foi atendida.

7. Participa da Sprint Review (Revisão)

  • Pode demonstrar funcionalidades testadas.
  • Aponta possíveis limitações ou áreas que requerem atenção futura.

8. Participa da Retrospectiva

  • Colabora para melhorar o processo de testes e integração com o time.
  • Apresenta sugestões sobre qualidade, automação, ambiente e comunicação.

Relevância para o projeto

  • Confiança nas alterações de código.
  • Documentação viva da lógica implementada.
  • Detecção precoce de erros e regressões.
  • Facilidade para refatorações seguras.
  • Redução de falhas em produção.

Implementação de Testes de Integração

Stack de Testes Utilizada

  • JUnit 5 (@Test, integração com Spring)
  • Spring Boot Test (carregamento do contexto completo da aplicação)
  • WebTestClient (para chamadas HTTP reativas)
  • AssertJ (para assertions fluentes)
  • Spring SQL Support (@Sql para scripts de inserção e limpeza)
  • Testcontainers (PostgreSQL) (banco de dados isolado e real para testes de integração)

Dependências no pom.xml

<dependencies>
    <!-- Starter de testes do Spring Boot (JUnit, AssertJ, Mockito etc.) -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
&lt;!-- WebFlux (necessário para o WebTestClient) --&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.springframework.boot&lt;/groupId&gt;
    &lt;artifactId&gt;spring-boot-starter-webflux&lt;/artifactId&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;

&lt;!-- Testcontainers: PostgreSQL + JUnit 5 --&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.testcontainers&lt;/groupId&gt;
    &lt;artifactId&gt;junit-jupiter&lt;/artifactId&gt;
    &lt;version&gt;1.19.7&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;
&lt;dependency&gt;
    &lt;groupId&gt;org.testcontainers&lt;/groupId&gt;
    &lt;artifactId&gt;postgresql&lt;/artifactId&gt;
    &lt;version&gt;1.19.7&lt;/version&gt;
    &lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;

</dependencies>

Exemplo Prático com Testcontainers

package com.quantum.stratify.integracao;

import com.quantum.stratify.web.dtos.PercentualStatusUsuarioDTO; import com.quantum.stratify.web.dtos.TotalCardsDTO; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.reactive.AutoConfigureWebTestClient; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.DynamicPropertyRegistry; import org.springframework.test.context.DynamicPropertySource; import org.springframework.test.context.jdbc.Sql; import org.springframework.test.web.reactive.server.WebTestClient; import org.testcontainers.containers.PostgreSQLContainer; import org.testcontainers.junit.jupiter.Container; import org.testcontainers.junit.jupiter.Testcontainers;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

@Testcontainers @AutoConfigureWebTestClient @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @Sql(scripts = { "classpath:sql/userStories/delete.sql", "classpath:sql/userStories/insert.sql" }, executionPhase = Sql.ExecutionPhase.BEFORE_TEST_METHOD) @Sql(scripts = "classpath:sql/userStories/delete.sql", executionPhase = Sql.ExecutionPhase.AFTER_TEST_METHOD) class UserStoryIT {

@Container
static PostgreSQLContainer&lt;?&gt; postgresContainer = new PostgreSQLContainer&lt;&gt;("postgres:15")
        .withDatabaseName("testdb")
        .withUsername("test")
        .withPassword("test");

@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
    registry.add("spring.datasource.url", postgresContainer::getJdbcUrl);
    registry.add("spring.datasource.username", postgresContainer::getUsername);
    registry.add("spring.datasource.password", postgresContainer::getPassword);
    registry.add("spring.datasource.driver-class-name", postgresContainer::getDriverClassName);
    registry.add("spring.liquibase.enabled", () -&gt; true);
    registry.add("spring.liquibase.change-log", () -&gt; "classpath:db/changelog/changelog-master.xml");
}

@Autowired
WebTestClient testClient;

@Test
void deveRetornarTotalCards_status200() {
    TotalCardsDTO responseBody = testClient.get()
            .uri("/userStory/total-cards")
            .exchange()
            .expectStatus().isOk()
            .expectBody(TotalCardsDTO.class)
            .returnResult()
            .getResponseBody();

    assertThat(responseBody).isNotNull();
    if (responseBody != null) {
        assertThat(responseBody.quantidadeUserStories()).isEqualTo(1);
    }
}

@Test
void deveRetornarPercentualPorStatus_status200() {
    List&lt;PercentualStatusUsuarioDTO&gt; responseBody = testClient.get()
            .uri("/userStory/percentual-por-status")
            .exchange()
            .expectStatus().isOk()
            .expectBodyList(PercentualStatusUsuarioDTO.class)
            .returnResult()
            .getResponseBody();

    assertThat(responseBody).isNotNull();
    assertThat(responseBody).hasSize(1);
}

}

Regras Gerais para Testes de Integração

Configuração do Ambiente

  • @SpringBootTest: carrega o contexto completo da aplicação.
  • webEnvironment = RANDOM_PORT: evita conflito de portas entre testes paralelos.
  • @Testcontainers e @Container: inicializa PostgreSQL real isolado.
  • @Sql: prepara o estado do banco (inserção e limpeza de dados).
@Sql(scripts = {"cleanup.sql", "insert.sql"}, executionPhase = BEFORE_TEST_METHOD)
@Sql(scripts = "cleanup.sql", executionPhase = AFTER_TEST_METHOD)

Convenções

  • Use nomes de métodos de teste descritivos e padronizados:
    • Em português: deveRetornarTempoMedioDoProjeto()
    • Ou em inglês: shouldReturnAverageTimePerProject()
  • Deixe os testes independentes entre si.
⚠️ **GitHub.com Fallback** ⚠️