Я тестирую CRUD для страницы в своем приложении, где для успешного создания реестра требуется уникальный идентификатор в виде 5-значного числа.
Я хотел бы получить случайный доступный идентификатор этой таблицы для использования в тестах, что может быть достигнуто с помощью следующего запроса sql:
cy.task(
'sqlQuery',
`select count(*) as "count" from clients where client_id = '${
Math.floor(Math.random() * 90000) + 10000
}'`
)
Дело в том, что случайное число, возможно, недоступно для использования в качестве идентификатора, поэтому мне нужно будет зациклить эту же задачу, пока не будет доступно сгенерированное число:
cy.task(
'sqlQuery',
`select count(*) as "count" from clients where client_id = '${
Math.floor(Math.random() * 90000) + 10000
}'`
).then((result: any) => {
if (result.rows[0].count === 0) {
// My code to submit the form with the generated number
// break the loop
} else {
// Repeat all of this (where i'm asking for help)
}
})
Если count возвращает 0, это означает, что его не использует реестр, иначе он недоступен.
Я предполагаю, что окончательным решением может быть использование некоторого цикла while, но я обнаружил, что этот способ будет более понятным для всех вас, кто знает, что мне нужно.
Я пробовал некоторые подходы, подобные этому, но просто обнаружил, что невозможно присвоить новое значение переменной внутри блока .then, поэтому кажется, что я сделал бесконечный цикл.
let available = false
do {
cy.task(
'sqlQuery',
`select count(*) as "count" from clients client_id = '${
Math.floor(Math.random() * 90000) + 10000
}'`
).then((result: any) => {
if (result.rows[0].count === 0) {
// Code to submit the form with the generated number
available = true
}
})
} while (available === false)
Да, это может быть решение для одного шага регистрации, но на самом деле, чтобы оптимизировать время, у меня есть 3 файла с таким тестом, работающим одновременно. По отдельности они работают нормально, используя auto_increment
, но при параллельном запуске все они будут выполнять регистрацию, получая один и тот же идентификатор, и некоторые из них в конечном итоге завершатся ошибкой позже при регистрации.
Спросите SQL, какие идентификаторы присутствуют, и проверьте случайный по ним?
Что-то вроде этого:
cy.task('sqlQuery', 'select client_id from clients')
.then((result: any) => {
const ids: string[] = result.rows;
function getNewId(trys = 0) {
if (trys > 1000) throw new Error('failed')
const newId = Math.floor(Math.random() * 90000) + 10000
if (ids.includes(newId)) {
return getNewId(++trys)
}
return newId
}
const newId = getNewId()
cy.wrap(newId).as('newId')
})
Обновлять
Изменена на рекурсивную функцию javascript, как я обнаружил при тестировании .should()
, она не переоценивается Math.floor(Math.random() * 90000) + 10000
Прошло некоторое время с тех пор, как я делал SQL, но, возможно, этот коррелированный подзапрос более эффективен.
SELECT last + 1 as newId FROM (
SELECT MAX(id) as last FROM clients
)
Спасибо за Ваш ответ. Ids
массив будет содержать все уже используемые IDS, а значит с ними нельзя создавать новые реестры. На самом деле я хочу наоборот, чтобы получить доступный идентификатор. Этого можно было бы добиться с помощью еще одного объявления массива, но я думаю, что это может быть не так эффективно, поскольку идентификатор может содержать до 5 цифр, у вас есть какие-либо идеи по этому поводу?
Хорошо, я увидел в вашем SQL clients client_id = '${random...
. Вы можете создать функцию либо с помощью javascript, либо с помощью Cypress .should()
. добавлю выше.
Большое спасибо, это было довольно близко к решению, но оно все еще возвращало недоступные идентификаторы, не уверен, но я думаю, это потому, что идентификаторы в этот момент были не массивом только с фактическими значениями идентификатора, а объектом с именем столбца и значением . Я просто изменил условие, чтобы вместо этого использовать некоторый доступ к значению id, и это решено :), просто я собираюсь улучшить тип позже. еще раз спасибо, было очень полезно.
Вы можете использовать такой запрос, чтобы получить 3 неиспользуемых идентификатора для ваших тестов.
MySQL:
SELECT a.id+1 as 'ids'
FROM clients a
WHERE
NOT EXISTS (SELECT * FROM clients b WHERE a.id+1 = b.id) AND
a.id+1 < 100000
ORDER BY a.id
LIMIT 3
Оракул 11:
SELECT a.id+1 as ids
FROM clients a
WHERE
NOT EXISTS (SELECT * FROM clients b WHERE a.id+1 = b.id) AND
a.id+1 < 10000 AND
rownum <= 3
ORDER BY a.id;
Оракул 12:
SELECT a.id+1 as ids
FROM clients a
WHERE
NOT EXISTS (SELECT * FROM clients b WHERE a.id+1 = b.id) AND
a.id+1 < 10000
ORDER BY a.id
FETCH FIRST 3 ROWS ONLY;
Это будет искать неиспользуемые идентификаторы, проверяя всегда следующий идентификатор, ограничивая его до 3 строк (вы можете ограничить количество, которое вам нужно) для повышения производительности. И только доступные идентификаторы до 100000 (имеет только 5 цифр)
Например:
У вашего стола есть идентификаторы (1, 3, 5, 6, 7, 9, 10)
Этот запрос проверит, существуют ли идентификаторы (2, 4, 6, 8, 10, 11)
в таблице. Если его нет, он вернется. Так что этот пример вернется (2, 4, 8)
Вы не можете получить это из значения
auto_increment
? Что-то вродеSHOW TABLE STATUS LIKE 'clients'
или сделайте запрос изinformation_schema