mirror of
https://github.com/microsoft/playwright.git
synced 2025-01-06 03:16:17 +03:00
feat(runner): allow running last failed tests (#30533)
Fixes: https://github.com/microsoft/playwright/issues/30506
This commit is contained in:
parent
8e6272b1e3
commit
a2eb43b335
@ -19,7 +19,7 @@
|
||||
import type { Command } from 'playwright-core/lib/utilsBundle';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { Runner } from './runner/runner';
|
||||
import { Runner, readLastRunInfo } from './runner/runner';
|
||||
import { stopProfiling, startProfiling, gracefullyProcessExitDoNotHang } from 'playwright-core/lib/utils';
|
||||
import { serializeError } from './util';
|
||||
import { showHTMLReport } from './reporters/html';
|
||||
@ -183,6 +183,11 @@ async function runTests(args: string[], opts: { [key: string]: any }) {
|
||||
if (!config)
|
||||
return;
|
||||
|
||||
if (opts.lastFailed) {
|
||||
const lastRunInfo = await readLastRunInfo(config);
|
||||
config.testIdMatcher = id => lastRunInfo.failedTests.includes(id);
|
||||
}
|
||||
|
||||
config.cliArgs = args;
|
||||
config.cliGrep = opts.grep as string | undefined;
|
||||
config.cliGrepInvert = opts.grepInvert as string | undefined;
|
||||
@ -338,6 +343,7 @@ const testOptions: [string, string][] = [
|
||||
['-gv, --grep-invert <grep>', `Only run tests that do not match this regular expression`],
|
||||
['--headed', `Run tests in headed browsers (default: headless)`],
|
||||
['--ignore-snapshots', `Ignore screenshot and snapshot expectations`],
|
||||
['--last-failed', `Run last failed tests`],
|
||||
['--list', `Collect all the tests and report them, but do not run`],
|
||||
['--max-failures <N>', `Stop after the first N failures`],
|
||||
['--no-deps', 'Do not run project dependencies'],
|
||||
|
@ -15,6 +15,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { monotonicTime } from 'playwright-core/lib/utils';
|
||||
import type { FullResult, TestError } from '../../types/testReporter';
|
||||
@ -93,6 +94,8 @@ export class Runner {
|
||||
if (modifiedResult && modifiedResult.status)
|
||||
status = modifiedResult.status;
|
||||
|
||||
await writeLastRunInfo(testRun, status);
|
||||
|
||||
await reporter.onExit();
|
||||
|
||||
// Calling process.exit() might truncate large stdout/stderr output.
|
||||
@ -144,3 +147,25 @@ export class Runner {
|
||||
return { testFiles: affectedTestFiles(resolvedFiles) };
|
||||
}
|
||||
}
|
||||
|
||||
export type LastRunInfo = {
|
||||
status: FullResult['status'];
|
||||
failedTests: string[];
|
||||
};
|
||||
|
||||
async function writeLastRunInfo(testRun: TestRun, status: FullResult['status']) {
|
||||
await fs.promises.mkdir(testRun.config.globalOutputDir, { recursive: true });
|
||||
const lastRunReportFile = path.join(testRun.config.globalOutputDir, 'last-run.json');
|
||||
const failedTests = testRun.rootSuite?.allTests().filter(t => !t.ok()).map(t => t.id);
|
||||
const lastRunReport = JSON.stringify({ status, failedTests }, undefined, 2);
|
||||
await fs.promises.writeFile(lastRunReportFile, lastRunReport);
|
||||
}
|
||||
|
||||
export async function readLastRunInfo(config: FullConfigInternal): Promise<LastRunInfo> {
|
||||
const lastRunReportFile = path.join(config.globalOutputDir, 'last-run.json');
|
||||
try {
|
||||
return JSON.parse(await fs.promises.readFile(lastRunReportFile, 'utf8')) as LastRunInfo;
|
||||
} catch (e) {
|
||||
}
|
||||
return { status: 'passed', failedTests: [] };
|
||||
}
|
||||
|
@ -818,3 +818,24 @@ test('wait for workers to finish before reporter.onEnd', async ({ runInlineTest
|
||||
expect(secondIndex).not.toBe(-1);
|
||||
expect(secondIndex).toBeLessThan(endIndex);
|
||||
});
|
||||
|
||||
test('should run last failed tests', async ({ runInlineTest }) => {
|
||||
const workspace = {
|
||||
'a.spec.js': `
|
||||
import { test, expect } from '@playwright/test';
|
||||
test('pass', async () => {});
|
||||
test('fail', async () => {
|
||||
expect(1).toBe(2);
|
||||
});
|
||||
`
|
||||
};
|
||||
const result1 = await runInlineTest(workspace);
|
||||
expect(result1.exitCode).toBe(1);
|
||||
expect(result1.passed).toBe(1);
|
||||
expect(result1.failed).toBe(1);
|
||||
|
||||
const result2 = await runInlineTest(workspace, {}, {}, { additionalArgs: ['--last-failed'] });
|
||||
expect(result2.exitCode).toBe(1);
|
||||
expect(result2.passed).toBe(0);
|
||||
expect(result2.failed).toBe(1);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user