Bases de Datos NoSQL en Stacks Modernos
Las bases de datos NoSQL intercambian el schema rígido y las garantías ACID de SQL por flexibilidad, escalabilidad y rendimiento en casos de uso específicos. Como ingeniero QA, necesitas enfoques de testing diferentes para cada tipo.
| Tipo | Ejemplos | Caso de Uso | Foco del Testing |
|---|---|---|---|
| Documento | MongoDB, CouchDB | Schemas flexibles, datos anidados | Consistencia de schema, indexación |
| Key-Value | Redis, Memcached | Caching, sesiones, contadores | TTL, eviction, tipos de datos |
| Wide-Column | DynamoDB, Cassandra | Alta escala, time-series | Estrategia de partición, consistencia |
| Graph | Neo4j, Neptune | Relaciones, redes | Correctitud de traversal |
Testing de MongoDB
MongoDB almacena datos como documentos JSON-like (BSON). Las colecciones no aplican schema por defecto, lo que significa que tu aplicación — y tus tests — deben validar la estructura de datos.
Testing de Validación de Schema
db.createCollection("users", {
validator: {
$jsonSchema: {
bsonType: "object",
required: ["name", "email"],
properties: {
name: { bsonType: "string", minLength: 1 },
email: { bsonType: "string", pattern: "^.+@.+\\..+$" },
age: { bsonType: "int", minimum: 0, maximum: 150 }
}
}
}
});
Casos de prueba:
// Documento válido — debe tener éxito
db.users.insertOne({ name: "Alice", email: "alice@test.com", age: 30 });
// Campo requerido faltante — debe fallar
db.users.insertOne({ name: "Bob" });
// Tipo inválido — debe fallar
db.users.insertOne({ name: "Charlie", email: "charlie@test.com", age: "thirty" });
Testing de Queries
const result = db.orders.aggregate([
{ $match: { status: "completed" } },
{ $group: { _id: "$userId", totalSpent: { $sum: "$total" } } },
{ $sort: { totalSpent: -1 } },
{ $limit: 10 }
]);
Testing de Índices
db.users.createIndex({ email: 1 }, { unique: true });
db.users.find({ email: "alice@test.com" }).explain("executionStats");
// Busca stage "IXSCAN" (no "COLLSCAN")
Testing de Redis
Redis es un almacén key-value en memoria usado para caching, sesiones, rate limiting y funcionalidades en tiempo real.
Testing de Tipos de Datos
# String
SET user:123:name "Alice"
GET user:123:name
# Hash
HSET user:123 name "Alice" email "alice@test.com"
HGETALL user:123
# List
LPUSH notifications:123 "Nuevo pedido" "Pago recibido"
LRANGE notifications:123 0 -1
# Set
SADD user:123:roles "admin" "editor" "admin"
SMEMBERS user:123:roles # {"admin", "editor"} — sin duplicados
# Sorted Set
ZADD leaderboard 100 "Alice" 200 "Bob" 150 "Charlie"
ZREVRANGE leaderboard 0 2 WITHSCORES
Testing de TTL
SET session:abc123 "user-data" EX 60
TTL session:abc123 # Retorna segundos restantes
EXISTS session:abc123 # 1 (existe)
# Después de 60 segundos...
EXISTS session:abc123 # 0 (expirado)
Testing de Invalidación de Cache
- Cache hit: Datos en Redis, app retorna valor cacheado.
- Cache miss: Datos no en Redis, app consulta BD y cachea resultado.
- Cache invalidation: Datos actualizados en BD, valor cacheado invalidado.
- Stale cache: Después de invalidación, siguiente solicitud retorna datos frescos.
Testing de DynamoDB
DynamoDB es un wide-column store completamente gestionado de AWS.
Testing de Diseño de Keys
import boto3
dynamodb = boto3.resource('dynamodb', endpoint_url='http://localhost:8000')
table = dynamodb.Table('Orders')
table.put_item(Item={
'userId': 'user-123',
'orderId': 'order-456',
'total': 99.99,
'status': 'pending'
})
response = table.query(
KeyConditionExpression='userId = :uid',
ExpressionAttributeValues={':uid': 'user-123'}
)
assert len(response['Items']) >= 1
Ejercicio: Laboratorio de Testing NoSQL
Parte 1: Testing de MongoDB
docker run -d --name mongo-test -p 27017:27017 mongo:7
Tarea 1.1: Crea una colección con validación de schema para “products”. Prueba que documentos inválidos sean rechazados.
Tarea 1.2: Inserta 1,000 productos con varias categorías. Escribe queries de aggregation y verifica resultados.
Tarea 1.3: Crea un índice compuesto en {category: 1, price: -1}. Verifica con explain() que los queries usen el índice.
Parte 2: Testing de Redis
docker run -d --name redis-test -p 6379:6379 redis:7
Tarea 2.1: Implementa y prueba un session store con TTL de 300 segundos.
Tarea 2.2: Implementa y prueba un rate limiter: 10 solicitudes por minuto por usuario.
Tarea 2.3: Prueba invalidación de cache: cachea perfil, actualiza “BD”, invalida cache, verifica que próxima lectura traiga datos frescos.
Parte 3: Testing de DynamoDB
docker run -d --name dynamo-test -p 8000:8000 amazon/dynamodb-local
Tarea 3.1: Crea tabla Orders con userId (partition key) y orderId (sort key). Inserta 50 pedidos y prueba patrones de query.
Tarea 3.2: Prueba conditional writes — actualiza estado solo si es “pending”.
Entregables
- MongoDB: Tests de validación, verificación de aggregation, prueba de uso de índices.
- Redis: Tests de TTL, rate limiter, invalidación de cache.
- DynamoDB: Tests de patrones de query, conditional writes.
- Resumen comparativo de diferencias entre testing SQL y NoSQL.