Pruebas de integración de C++ con Docker
El desarrollo moderno en C++ no solo requiere escribir código de calidad, sino también garantizar su funcionamiento confiable en condiciones reales. Las pruebas de integración son una etapa clave que permite verificar la interacción de los componentes del sistema: bases de datos, servicios de red, sistema de archivos. El uso de Docker para estos fines proporciona un entorno aislado y reproducible, ideal para pipelines de CI/CD. En este artículo, analizaremos cómo configurar las pruebas de integración de aplicaciones C++ con Docker y proporcionaremos ejemplos prácticos.
¿Por qué Docker para las pruebas de integración de C++?
Los enfoques tradicionales para las pruebas de integración de C++ a menudo enfrentan problemas:
- Dependencia del entorno: las pruebas pueden funcionar en la máquina del desarrollador, pero fallar en el servidor de compilación debido a diferentes versiones de bibliotecas.
- Complejidad de configuración: para probar con una base de datos real o una API externa se requiere configuración manual.
- Ejecución paralela: varias ejecuciones de prueba pueden entrar en conflicto debido a recursos compartidos.
Docker resuelve estos problemas proporcionando contenedores ligeros y aislados. Puede levantar una base de datos de prueba, ejecutar su servicio C++ y realizar las pruebas, todo dentro de un solo archivo docker-compose. Esto garantiza que el entorno sea idéntico en cualquier máquina.
Configuración del proyecto: ejemplo básico
Consideremos un servicio C++ simple que guarda datos en PostgreSQL. Para las pruebas de integración necesitaremos:
- El propio código C++ con las pruebas (usamos Google Test).
- Un
Dockerfilepara compilar y ejecutar las pruebas. - Un archivo
docker-compose.ymlpara la orquestación de contenedores.
Estructura del proyecto:
my_cpp_project/├── src/│ ├── main.cpp│ ├── database.cpp│ └── database.h├── tests/│ └── test_integration.cpp├── CMakeLists.txt├── Dockerfile└── docker-compose.yml
Dockerfile:
FROM gcc:latest AS builder
WORKDIR /appCOPY . .
RUN apt-get update && apt-get install -y cmake libpq-devRUN cmake -B build -DCMAKE_BUILD_TYPE=ReleaseRUN cmake --build build
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y libpq-devCOPY --from=builder /app/build/tests /app/testsCOPY --from=builder /app/build/my_app /app/my_app
ENTRYPOINT ["/app/tests"]docker-compose.yml:
version: '3.8'services: db: image: postgres:15 environment: POSTGRES_USER: testuser POSTGRES_PASSWORD: testpass POSTGRES_DB: testdb ports: - "5432:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U testuser -d testdb"] interval: 5s timeout: 5s retries: 5
test: build: . depends_on: db: condition: service_healthy environment: DB_HOST: db DB_PORT: 5432 DB_USER: testuser DB_PASSWORD: testpass DB_NAME: testdbEscribiendo pruebas de integración en C++
Ahora crearemos una prueba que verifique la escritura y lectura de la base de datos. Usamos Google Test y la biblioteca libpqxx para trabajar con PostgreSQL.
tests/test_integration.cpp:
#include <gtest/gtest.h>#include <pqxx/pqxx>#include <string>
class DatabaseTest : public ::testing::Test {protected: void SetUp() override { conn = new pqxx::connection( "host=" + std::string(std::getenv("DB_HOST")) + " port=" + std::string(std::getenv("DB_PORT")) + " user=" + std::string(std::getenv("DB_USER")) + " password=" + std::string(std::getenv("DB_PASSWORD")) + " dbname=" + std::string(std::getenv("DB_NAME")) ); }
void TearDown() override { delete conn; }
pqxx::connection* conn;};
TEST_F(DatabaseTest, CanInsertAndRetrieveData) { pqxx::work txn(*conn); txn.exec("CREATE TABLE IF NOT EXISTS test_table (id SERIAL PRIMARY KEY, value TEXT)"); txn.exec("INSERT INTO test_table (value) VALUES ('hello')"); pqxx::result res = txn.exec("SELECT value FROM test_table"); EXPECT_EQ(res[0][0].as<std::string>(), "hello"); txn.commit();}```