NoSQL-базы в современных стеках
NoSQL-базы обменивают жёсткую схему и ACID-гарантии SQL на гибкость, масштабируемость и производительность в конкретных случаях. Как QA-инженеру вам нужны разные подходы к тестированию для каждого типа.
| Тип | Примеры | Случай использования | Фокус тестирования |
|---|---|---|---|
| Документное | MongoDB, CouchDB | Гибкие схемы, вложенные данные | Согласованность схемы, индексация |
| Key-Value | Redis, Memcached | Кеширование, сессии, счётчики | TTL, вытеснение, типы данных |
| Wide-Column | DynamoDB, Cassandra | Высокая масштабируемость, time-series | Стратегия партиционирования, согласованность |
| Графовое | Neo4j, Neptune | Связи, сети | Корректность обходов |
Тестирование MongoDB
MongoDB хранит данные как JSON-подобные документы (BSON). Коллекции по умолчанию не применяют схему, что означает — ваше приложение и тесты должны валидировать структуру данных.
Тестирование валидации схемы
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 }
}
}
}
});
Тест-кейсы:
// Валидный документ — должен пройти
db.users.insertOne({ name: "Alice", email: "alice@test.com", age: 30 });
// Отсутствует обязательное поле — должен не пройти
db.users.insertOne({ name: "Bob" });
// Невалидный тип — должен не пройти
db.users.insertOne({ name: "Charlie", email: "charlie@test.com", age: "thirty" });
Тестирование запросов
const result = db.orders.aggregate([
{ $match: { status: "completed" } },
{ $group: { _id: "$userId", totalSpent: { $sum: "$total" } } },
{ $sort: { totalSpent: -1 } },
{ $limit: 10 }
]);
Тестирование индексов
db.users.createIndex({ email: 1 }, { unique: true });
db.users.find({ email: "alice@test.com" }).explain("executionStats");
// Ищите stage "IXSCAN" (не "COLLSCAN")
Тестирование Redis
Redis — хранилище key-value в памяти для кеширования, сессий, rate limiting и real-time функций.
Тестирование типов данных
# 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 "Новый заказ" "Платёж получен"
LRANGE notifications:123 0 -1
# Set
SADD user:123:roles "admin" "editor" "admin"
SMEMBERS user:123:roles # {"admin", "editor"} — без дубликатов
# Sorted Set
ZADD leaderboard 100 "Alice" 200 "Bob" 150 "Charlie"
ZREVRANGE leaderboard 0 2 WITHSCORES
Тестирование TTL
SET session:abc123 "user-data" EX 60
TTL session:abc123 # Возвращает оставшиеся секунды
EXISTS session:abc123 # 1 (существует)
# Через 60 секунд...
EXISTS session:abc123 # 0 (истёк)
Тестирование инвалидации кеша
- Cache hit: Данные в Redis, приложение возвращает закешированное значение.
- Cache miss: Данных нет в Redis, приложение запрашивает БД и кеширует результат.
- Cache invalidation: Данные обновлены в БД, закешированное значение инвалидировано.
- Stale cache: После инвалидации следующий запрос возвращает свежие данные.
Тестирование DynamoDB
DynamoDB — полностью управляемое wide-column хранилище AWS.
Тестирование дизайна ключей
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
Упражнение: Лаборатория тестирования NoSQL
Часть 1: Тестирование MongoDB
docker run -d --name mongo-test -p 27017:27017 mongo:7
Задание 1.1: Создайте коллекцию с валидацией схемы для “products”. Проверьте отклонение невалидных документов.
Задание 1.2: Вставьте 1,000 товаров с различными категориями. Напишите aggregation-запросы и проверьте результаты.
Задание 1.3: Создайте составной индекс {category: 1, price: -1}. Проверьте через explain(), что запросы используют индекс.
Часть 2: Тестирование Redis
docker run -d --name redis-test -p 6379:6379 redis:7
Задание 2.1: Реализуйте и протестируйте хранилище сессий с TTL 300 секунд.
Задание 2.2: Реализуйте и протестируйте rate limiter: 10 запросов в минуту на пользователя.
Задание 2.3: Протестируйте инвалидацию кеша: закешируйте профиль, обновите «БД», инвалидируйте кеш, проверьте, что следующее чтение получит свежие данные.
Часть 3: Тестирование DynamoDB
docker run -d --name dynamo-test -p 8000:8000 amazon/dynamodb-local
Задание 3.1: Создайте таблицу Orders с userId (partition key) и orderId (sort key). Вставьте 50 заказов и протестируйте паттерны запросов.
Задание 3.2: Протестируйте conditional writes — обновите статус только если он “pending”.
Результаты
- MongoDB: Тесты валидации, проверка aggregation, доказательство использования индексов.
- Redis: Тесты TTL, rate limiter, инвалидация кеша.
- DynamoDB: Тесты паттернов запросов, conditional writes.
- Сравнительная таблица различий тестирования SQL и NoSQL.