Транспортир E2E - как вы управляете базой данных?
В настоящее время я опираюсь на стек Node + Angular и использую Karma и Protractor для тестирования.
В настоящее время мне трудно понять, как работать с тестами E2E, которые создают и редактируют данные, а также с необходимостью загрузки ожидаемых данных.
Поиск в Google обнаруживает множество различных пользовательских методов. Я часто читаю "вы должны настроить свои данные" или "просто создать макет", не вдаваясь в подробности общего процесса. Другие вкладывают слишком много усилий в создание совершенно нового макета модуля с нуля.
Я просто хотел бы знать, как люди в настоящее время делают это, и есть ли стандарт для этого? Или люди склонны просто издеваться над серверной частью? Дразнить бэкэнд не так просто, как в Karma, потому что вы в браузере.
Я, как и ожидалось, использую MongoDB, поэтому было бы неплохо получить некоторое представление о том, что другие делают в этом сценарии. Было бы хорошо, в частности, автоматизировать загрузку приборов и очистку базы данных через Protractor.
5 ответов
Этого можно добиться тремя способами:
1) Первый способ - написать простые пользовательские API-интерфейсы для тестирования, которые можно использовать перед запуском тестов транспортира (файл конфигурации транспортира onPrepare). В onPrepare вы можете запустить скрипт, который создает данные в вашей базе данных, которые вы позже будете использовать в целях тестирования. Этот сценарий должен содержать логику для передачи необходимых записей базы данных в базу данных. Вы также можете заставить этот сценарий запускаться на CI до того, как ваш транспортир проверяет фазу CI. Таким образом, у вас будут все необходимые записи базы данных, загруженные в базу данных до начала тестов. Минусы этого в том, что ваши тесты будут запускаться немного дольше. Другой минус заключается в том, что если между тестами есть настройка, вам придется запускать настройку между тестами.
2) Второй способ сделать это - использовать пакет npm ng-apimock. Я бы не рекомендовал использовать это, потому что насмешки - не лучшая идея для тестов e2e. Тем не менее, использование ng-apimock позволит вам определить значения API, которые вы хотите имитировать, и отправить их на фиктивный сервер. Затем вы можете использовать это значение позже в своих тестах с помощью selectScenario. Существует плагин protractor ngapimock, который вы можете использовать для этого. Также функция, называемая сквозной передачей, позволит вашему ответу API не использовать макет, а использовать фактический бэкэнд API. Этот инструмент используется для более быстрой разработки внешнего интерфейса, если он еще не готов. Если вы используете ngapimock, убедитесь, что вы периодически поддерживаете свои макеты, иначе тесты не пройдут.
3) Третий способ сделать это - инициализировать базу данных, которая будет использоваться только для тестирования. Это означает, что когда вы инициализируете свою базу данных, просто убедитесь, что присутствуют только те данные, которые вам нужны для тестирования. Запустите тесты, а затем уничтожьте базу данных. Таким образом, вам нужно будет поддерживать сценарий запуска базы данных для добавления разных значений в разные таблицы.
Надеюсь это поможет.
Транспортир предназначен только для тестирования e2e. это означает, что это не имеет ничего общего с вашей базой данных. Вы можете использовать средство запуска задач (например, grunt или gulp), чтобы очистить и заполнить базу данных, а после этого позволить исполнителю задач запустить тесты транспортира (я никогда не делал последнего, но я думаю, что это возможно). ну, я знаю, что это не тот ответ, к которому ты стремился, но, возможно, я мог бы указать тебе правильное направление.
Вы можете управлять своей базой данных через REST API (веб-сервис).
Я хочу показать пример, как удалить пользователя из базы данных с помощью веб-сервиса с транспортиром. В моем примере я использую Oracle как базу данных.
class OracleDatabaseAccess {
private readonly BASE_API_URL: string = browser.params.someUrlToYourRest;
public request<T>(query: string): promise.Promise<T[]> {
return this.get<T[]>(this.BASE_API_URL, 'sql?query=' + this.fixQuery(query));
}
public update<T>(query: string): promise.Promise<T[]> {
return this.get<T[]>(this.BASE_API_URL, 'update?query=' + this.fixQuery(query));
}
public get<T>(url: string, path: string): promise.Promise<T> {
const http = new HttpClient(url);
http.failOnHttpError = true;
const responsePromise: ResponsePromise = http.get(path);
return responsePromise.body.then(body => {
return JSON.parse(body.toString());
}) as promise.Promise<T>;
}
private fixQuery(query: string): string {
if (query.includes('%')) {
query = query.split('%').join('%25');
}
if (query.includes(';')) {
query = query.replace(';', '');
}
return query;
}
}
class Queries {
private oracleDataBaseAccess: OracleDatabaseAccess = new OracleDatabaseAccess();
deleteUser(userId: string): promise.Promise<{}> {
return this.oracleDataBaseAccess.update(`delete from users where userId='${userId}'`);
}
}
Используя request
методом вы можете выбрать записи из базы данных. Кроме того, используяupdate
вы можете вставить данные.
Вы можете использовать Queries
в вашем describe
в beforeAll
или afterAll
. Например, наbeforeAll
вы создаете нескольких пользователей, и на afterAll
вы их удалите.
В основном вам дадут создать отдельную среду для тестирования сквозных тестов.
Где после каждого выполнения текста вам нужно отдыхать в своей базе данных с помощью сценария сброса базы данных
Мы используем библиотеку npm oracledb для создания данных и настройки тестовых данных.
Приведенный ниже код используется для того же
import * as oracledb from 'oracledb';
connectDb(username: string, password: string, SID: string, setting_name: string, value: string) {
return browser.driver.sleep(1000).then(() => {
oracledb.getConnection(
{
user: username,
password: password,
connectString: SID
},
function (err, connection) {
if (err) {
console.error(err.message);
return;
}
connection.execute(
// The statement to execute
//<Place the Query that needs to be executed>,
UPDATE <table name> SET VALUE=:value WHERE NAME=:setting_name
{
//The paramaters to be substituted in the query.
value: value,
setting_name: setting_name
},
{ autoCommit: true },
// Optional execute options argument, such as the query result format
// or whether to get extra metadata
// { outFormat: oracledb.OBJECT, extendedMetaData: true },
// The callback function handles the SQL execution results
function (error, result) {
if (error) {
console.error(error.message);
doRelease(connection);
return;
}
doRelease(connection);
});
});
});
function doRelease(connection) {
connection.close(
function (err) {
if (err) {
console.error(err.message);
}
});
}
}