Cypress изначально ориентирован на end-to-end тестирование веб-приложений, однако часто возникает необходимость взаимодействовать с базой данных для подготовки тестовых данных или проверки состояния приложения. Прямого встроенного механизма работы с SQL в Cypress нет, поэтому для выполнения SQL-запросов применяются обходные подходы с использованием Node.js и внешних библиотек.
Для работы с базой данных из Cypress на уровне Node.js используется
cy.task, который позволяет выполнять код на стороне Node, а
не в браузере. Это критически важно, поскольку браузер не имеет доступа
к файловой системе и сети напрямую для подключения к базе данных.
Пример подключения к базе данных MySQL:
// cypress/plugins/index.js
const mysql = require('mysql');
module.exports = (on, config) => {
const dbConfig = {
host: config.env.dbHost,
user: config.env.dbUser,
password: config.env.dbPassword,
database: config.env.dbName
};
on('task', {
queryDatabase({ sql, values }) {
const connection = mysql.createConnection(dbConfig);
return new Promise((resolve, reject) => {
connection.connect(err => {
if (err) return reject(err);
connection.query(sql, values, (error, results) => {
connection.end();
if (error) return reject(error);
resolve(results);
});
});
});
}
});
};
Здесь ключевые моменты:
cy.task для выполнения кода на
Node.js.После настройки задачи в plugins, SQL-запросы вызываются
из тестов через cy.task. Пример запроса данных из таблицы
users:
describe('Проверка пользователей', () => {
it('Должен получить список пользователей', () => {
cy.task('queryDatabase', { sql: 'SELECT * FROM users WHERE status = ?', values: ['active'] })
.then(users => {
expect(users).to.have.length.greaterThan(0);
users.forEach(user => {
expect(user.status).to.eq('active');
});
});
});
});
Особенности:
values используются для безопасной подстановки
параметров, предотвращая SQL-инъекции.Cypress через cy.task позволяет не только читать данные,
но и изменять их. Пример вставки нового пользователя:
cy.task('queryDatabase', {
sql: 'INSERT INTO users (name, email, status) VALUES (?, ?, ?)',
values: ['Иван Иванов', 'ivan@example.com', 'active']
}).then(result => {
expect(result.affectedRows).to.eq(1);
});
Обновление и удаление аналогичны:
cy.task('queryDatabase', {
sql: 'UPDATE users SE T status = ? WHERE id = ?',
values: ['inactive', 5]
});
cy.task('queryDatabase', {
sql: 'DELETE FROM users WHERE id = ?',
values: [10]
});
Важно проверять affectedRows для подтверждения того, что
операция затронула нужное количество записей.
Для комплексного тестирования часто используется подготовка базы перед выполнением тестов:
beforeEach(() => {
cy.task('queryDatabase', { sql: 'DELETE FROM users WHERE test_flag = 1' });
cy.task('queryDatabase', {
sql: 'INSERT INTO users (name, email, status, test_flag) VALUES (?, ?, ?, 1)',
values: ['Тестовый пользователь', 'test@example.com', 'active']
});
});
Подход позволяет:
Для сложных сценариев удобно использовать транзакции. Это обеспечивает откат всех изменений после теста и поддерживает консистентность данных. Пример с MySQL:
cy.task('queryDatabase', { sql: 'START TRANSACTION' });
cy.task('queryDatabase', {
sql: 'INSERT INTO orders (user_id, total) VALUES (?, ?)',
values: [1, 500]
});
cy.task('queryDatabase', { sql: 'ROLLBACK' });
Использование ROLLBACK гарантирует, что база вернется в
исходное состояние, что критично для повторяемых тестов.
При работе с SQL в Cypress важно отслеживать ошибки и логировать их для диагностики:
cy.task('queryDatabase', { sql: 'SELECT * FROM nonexistent_table' })
.then(results => {
// не будет вызвано
})
.catch(error => {
cy.log('Ошибка SQL запроса: ' + error.message);
});
Ключевые моменты:
catch.Для работы с другими базами, кроме MySQL, можно использовать:
pg.mssql.sqlite3.Принцип остается тем же: создается cy.task в плагинах,
соединение открывается на стороне Node.js, результат возвращается в
тест.
affectedRows: позволяет
убедиться, что запрос реально изменил базу.? и массив
values) для предотвращения SQL-инъекций.Работа с SQL через cy.task делает Cypress полноценным
инструментом для интеграционного тестирования, позволяя контролировать
состояние базы данных, проверять корректность бизнес-логики и
поддерживать надежность тестов даже при сложной архитектуре
приложения.