Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: speedier regression testing #1897

Merged
merged 6 commits into from
Dec 23, 2023
Merged

Conversation

KTibow
Copy link
Contributor

@KTibow KTibow commented Dec 22, 2023

Goes from 76 seconds to 61 seconds in my tests.
Two main changes:

  • instead of chunking the array, use workers that subtract as needed
    Bonus: this means that they go in alphabetical order
  • serve SVGs, optimized or not, on demand instead of warming them up
    This means no optimizing skipped tests
    Admittedly won't be as useful once the PR that moves skipping tests into the extractor gets merged, but hey, it'll still decrease initial startup time

*I was going to make it even faster with node-canvas, but the w3 tests are a bit eccentric and fail to render properly there, and I don't know of any other convenient rendering libs

@KTibow KTibow changed the title Speedier regression testing chore: speedier regression testing Dec 22, 2023
Copy link
Member

@SethFalco SethFalco left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, this looks great. Thank you!

I have a few ideas on how we can refactor this too, but I'll tackle them in a separate PR once this is merged.

test/regression.js Outdated Show resolved Hide resolved
test/regression.js Outdated Show resolved Hide resolved
Comment on lines 130 to 168
// setup server
const server = http.createServer((req, res) => {
if (req.url.startsWith('/original/')) {
const name = req.url.slice('/original/'.length);
if (originalFiles.has(name)) {
res.setHeader('Content-Type', 'image/svg+xml');
res.end(originalFiles.get(name));
const server = http.createServer(async (req, res) => {
const name = req.url.startsWith('/original/')
? req.url.slice('/original/'.length)
: req.url.startsWith('/optimized/')
? req.url.slice('/optimized/'.length)
: undefined;
let file;
if (name) {
try {
file = await fs.promises.readFile(
path.join(fixturesDir, name),
'utf-8',
);
} catch (error) {
res.statusCode = 404;
res.end();
return;
}
}

if (req.url.startsWith('/original/')) {
res.setHeader('Content-Type', 'image/svg+xml');
res.end(file);
return;
}
if (req.url.startsWith('/optimized/')) {
const name = req.url.slice('/optimized/'.length);
if (optimizedFiles.has(name)) {
res.setHeader('Content-Type', 'image/svg+xml');
res.end(optimizedFiles.get(name));
return;
const optimized = optimize(file, {
path: name,
floatPrecision: 4,
});
if (optimized.error) {
throw new Error(`Failed to optimize ${name}`, {
cause: optimized.error,
});
}
res.setHeader('Content-Type', 'image/svg+xml');
res.end(optimized.data);
return;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I really wanted to get rid of the whole HTTP server, since we should be able to just use setContent in Playwright. Unfortunately, there appears to be a bug that stops us from doing that right now.

Usage would be as follows, so much simpler:

const fixturesDir = path.join(__dirname, 'regression-fixtures');

const runTests = async ({ list }) => {
  let mismatched = 0;
  let passed = 0;

  const processFile = async (page, name) => {
    const original = await fs.promises.readFile(
      path.join(fixturesDir, name),
      'utf-8',
    );
    const optimized = optimize(original, {
      path: name,
      floatPrecision: 4,
    });

    await page.setContent(original);
    const originalBuffer = await page.screenshot({
      omitBackground: true,
      clip: { x: 0, y: 0, width, height },
    });

    await page.setContent(optimized.data);
    // …

test/regression.js Outdated Show resolved Hide resolved
@SethFalco
Copy link
Member

SethFalco commented Dec 23, 2023

I see… that would explain that logic. We had the fallback to empty response because some of the SVGs try to load other resources, and we want to ignore them.

Perhaps you can just put that back for now. Now that the issue with the name variable is fixed, it's not an immediate problem. I'll review that while refactoring the test suite.

Sorry for the bad call on my part!

@SethFalco SethFalco merged commit 16c6977 into svg:main Dec 23, 2023
10 checks passed
@SethFalco
Copy link
Member

I'm responding to this comment here, since it's more to do with our usage than the bug report itself:

microsoft/playwright#28778 (comment)

I initially didn't try it deliberately, since inlining an SVG and loading it via an <img> tag are different. While it would be nice to test both, figured it'd be best to stick to inline only for now.

However, I did just try it now and it does work… kind of. Failing tests went from 262 to 1,000+, and it's much slower. Possibly because of the URI encoding to make it work in a URL format, plus the browser has to load more data since the encoding makes the SVG fat.

I'll come back to that later, but for now, we can keep the HTTP server. 🤔

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants