В документации Playwright есть такой пример параметризации. Оно работает:
const people = ['Alice', 'Bob'];
for (const name of people) {
test(`testing with ${name}`, async () => {
// ...
});
// You can also do it with test.describe() or with multiple tests as long the test name is unique.
}
Однако я хочу получать массив данных перед каждым тестом и генерировать тестовый цикл.
//data like data[] = [{name:'Alice',age:'20'},..]
let data: any[] = [];
test.beforeEach(async ({ request }) => {
data = await getData(request);
});
for (let i = 0; i < data.length; i++) {
test(`testing with ${name}`, async (page) => {
// ...
});
}
В коде визуальной студии отображается ошибка: тест не найден.
Но это работает, когда я присваиваю точное значение let data: any[] =[{name:'Alice',age:'20'}];.
Я тестирую аналогичный случай https://github.com/microsoft/playwright/issues/9916Как правильно запустить отдельные тесты драматурга из динамического массива встроенных URL-адресов?
да, имя файла — xxx.spec.ts. Это работает, когда я присваиваю точное значение, пусть data: Any[] =[{name:'Alice',age:'20'}]
Отвечает ли это на ваш вопрос? Как правильно запустить отдельные тесты драматурга из динамического массива встроенных URL-адресов?






У меня плохое решение, которое определяет длину массива.
let data: any[] = new Array(10);
Затем тесты можно определить с помощью VScode
for (let i = 0; i < data.length; i++) {
test(`testing with ${name}`, async page => {
if (data[i] !== undefined) {
// test
}
// ...
});
}
Спасибо за ответ, приятно видеть обходной путь. Придирка: VSCode — это всего лишь редактор. Playwright — это библиотека, которая обнаруживает тесты.
Это потому, что вы используете перехватчик beforeEach и, скорее всего, метод getData присваивает неопределенное значение data или data длина равна нулю.
Я рекомендую вам отладить то, что назначается data в хуке beforeEach.
Еще одна важная вещь: хук beforEach запускается один раз перед КАЖДЫМ тестом. В твоем случае,
data;data пусто, тестовый запуск останавливается и процесс завершается с ошибкой: No Test found.
Решение:
import { test } from '@playwright/test';
import { getData } from '../utils/getData';
test.describe('Some feature', () => {
let data: string[] = [];
data = getData(); // Assuming it returns an array of strings
data.forEach(testName => {
test(`Test name: ${testName}`, () => {
console.info('Logging test name:', testName);
});
});
});
Похоже, что длина data должна быть больше 0 перед началом тестов. В противном случае, поскольку массив пуст и тесты на итерации цикла запускаться не будут.
Я не уверен, как вы реализовали приспособление request. Если это не сработает, импортируйте его в модуль и передайте непосредственно getData.
Мне это, к сожалению, не подходит. Я получаю ошибку, TypeError: Cannot read properties of undefined (reading 'length') относится к data.length. Хотя было бы круто/оптимально, если бы это сработало. Опечатка: beforAll.
Возможно. Можете ли вы попробовать отладку request? проверьте, не является ли он неопределенным или вы получаете его с правильной структурой. Следующее — убедиться, что getData работает правильно, убедиться, что он выдает ошибку, если что-то не так, чтобы вы знали, где ваше приложение дает сбой.
Это не связано с request, оно терпит неудачу, даже если data = ["a", "b", "c"], поэтому фундаментальная установка здесь, похоже, не работает независимо от getData. Пробовали ли вы запустить этот код самостоятельно, чтобы убедиться, что он работает? Проблема описана в моем ответе: обнаружение тестов — это двухэтапный процесс, поэтому на первом этапе не выполняются перехватчики, а асинхронный код практически запрещен.
Я обновил решение. Это сработало для меня. Перед началом тестов вам следует убедиться, что data имеет длину.
Ваше обновление удаляет async/await, о чем и идет вопрос. Можете ли вы обновить, чтобы использовать это? В вашем ответе по-прежнему написано «Решение: используйте test.beforeAll», но этого больше нет в вашем коде.
Давайте продолжим обсуждение в чате.
Фундаментальная проблема заключается в том, что Playwright запускает тестовый код дважды. Первый проход синхронный и предположительно используется для определения количества вызовов test(). Второй проход фактически выполняет тесты. Регистрация чего-либо на верхнем уровне тестового файла показывает этот двухэтапный процесс.
К сожалению, в настоящее время нет очевидного способа использовать асинхронный код на верхнем уровне на начальном этапе обнаружения теста.
Это работает:
import {test} from "@playwright/test"; // ^1.42.1
(async () => {
for (const name of ["a", "b", "c"]) {
test(`testing with ${name}`, async () => {
// ...
});
}
})();
но это не обнаруживает тесты:
import {setTimeout} from "node:timers/promises";
import {test} from "@playwright/test";
(async () => {
await setTimeout(0); // actually do something async
for (const name of ["a", "b", "c"]) {
test(`testing with ${name}`, async () => {
// ...
});
}
})();
Более того, хуки before не участвуют в процессе обнаружения тестов. Следующий код
import {test} from "@playwright/test";
console.info("TEST SUITE");
test.beforeAll(() => console.info("BEFORE"));
for (const name of ["a", "b", "c"]) {
test(`testing with ${name}`, async () => {
// ...
});
}
выходы:
$ npx playwright test
TEST SUITE
Running 3 tests using 1 worker
TEST SUITE
✓ 1 pw.test.js:7:7 › testing with a (5ms)
BEFORE
✓ 2 pw.test.js:7:7 › testing with b (4ms)
✓ 3 pw.test.js:7:7 › testing with c (2ms)
3 passed (270ms)
Согласно этому комментарию, одним из обходных путей является использование test.step():
import {test} from "@playwright/test";
let people = [];
test.beforeAll(async ({request}) => {
const url = "https://jsonplaceholder.typicode.com/users";
const response = await request.get(url);
people = (await response.json()).map(e => e.name);
});
test("test", async () => {
for (const name of people) {
await test.step(`testing with ${name}`, async () => {
// ...
});
}
});
Проблема в том, что в выводе отсутствуют имена тестовых примеров:
$ npx playwright test
Running 1 test using 1 worker
✓ 1 pw.test.js:11:5 › test (8ms)
1 passed (407ms)
Другой обходной путь — сгенерировать данные в отдельном скрипте перед запуском тестов, сохранить их в файле и синхронно прочитать файл в начале тестов. Например:
генерировать-люди-data.js:
const fs = require("node:fs/promises");
(async () => {
const url = "https://jsonplaceholder.typicode.com/users";
const response = await fetch(url);
const people = (await response.json()).map(e => e.name);
await fs.writeFile("people.json", JSON.stringify(people));
})();
люди.test.js:
import fs from "node:fs";
import {test} from "@playwright/test";
const json = fs.readFileSync("people.json", {encoding: "utf-8"});
const people = JSON.parse(json);
for (const name of people) {
test(`testing with ${name}`, async () => {
// ...
});
}
Бегать:
$ node generate-people-data && npx playwright test
Running 10 tests using 1 worker
✓ 1 pw.test.js:7:7 › testing with Leanne Graham (9ms)
✓ 2 pw.test.js:7:7 › testing with Ervin Howell (4ms)
✓ 3 pw.test.js:7:7 › testing with Clementine Bauch (1ms)
✓ 4 pw.test.js:7:7 › testing with Patricia Lebsack (1ms)
✓ 5 pw.test.js:7:7 › testing with Chelsey Dietrich (1ms)
✓ 6 pw.test.js:7:7 › testing with Mrs. Dennis Schulist (1ms)
✓ 7 pw.test.js:7:7 › testing with Kurtis Weissnat (1ms)
✓ 8 pw.test.js:7:7 › testing with Nicholas Runolfsdottir V (1ms)
✓ 9 pw.test.js:7:7 › testing with Glenna Reichert (1ms)
✓ 10 pw.test.js:7:7 › testing with Clementina DuBuque (3ms)
10 passed (253ms)
Если вам не нравится &&, вы можете запустить npx playwright test на последнем этапе скрипта-генератора.
Другой вариант — метод синхронной выборки из другого потока.
Возможно, в текущей версии есть более элегантный подход, или будущие версии Playwright будут поддерживать обнаружение асинхронных тестов.
Есть ли в имени вашего тестового файла
.spec.или.test.? Существует ли тестовый файл в месте, которое будет выбрано вашим файлом playwright.config?