Urgent.News

What's breaking now, across thousands of outlets.

Tech

Tests for a PDF ·

My CV comes equipped with a test suite. It's either an acceptable practice or indicative of a larger issue. The reason behind it is that I am not the first reader; the applicant tracking system (ATS) is. This system requires textual content. Every visual aspect of the document, including the font, margins, and positioning of dates, is invisible to the ATS.

The only thing it can discern is what pdftotext scrapes off the page. Consequently, the resume is crafted as a Typst document, compiled into a directory named dist/, and the make test runs a Python script, inspecting each PDF discovered within. There are four checks: the first three are conducted out of caution, while the fourth is the primary focus.

A PDF can be a picture of a document. If the text layer is broken or absent, the file appears empty to parsers between the developer and the human reader, which constitutes the vast majority of the audience. The number 200 serves as an arbitrary threshold, distinguishing "text is present" from "text is not present." The tests validate the output.

The template aims to ensure the output is easily readable; it employs a single-column layout without tables, a half-inch margin, and job titles presented as comma-separated plain text instead of icons. A two-column layout is a traditional method to feed a parser your job titles alongside your dates. This comment is a common piece of advice found on resume advice websites.

Ligatures can transform "ffi" into a single glyph, resulting in "oce" being handed to the recruiter instead of "office." I believed this enough to document it. However, I never verified if it held true. Two files were almost identical, differing by only one boolean line: In one, the line contained 61 characters. With ligatures activated, Typst generates 53 glyphs in the content stream.

In the absence of ligatures, 61 glyphs are produced. The ligatures are genuine and function as intended, collapsing eight characters into four glyphs. Despite both PDFs containing a ToUnicode CMap, this table maps glyph 0x0002 to the letters "f, f, i." Typst writes the same glyph either way. The pdffonts tool has been alerting me to this discrepancy all along, even though I kept the setting.

This measure is taken to safeguard against extractors that ignore ToUnicode or producers that fail to write one. Both scenarios are known to exist. I am merely unable to name the specific ATS that is prone to this error, nor can any of the resources I consulted. This highlights a significant problem within this niche: the underlying issue exists in principle, remains unobservable in practice, yet the remedy is free, leading everyone to adopt it without measuring its effectiveness.

I am now among those who have measured it and implemented the solution, even though it comes at a cost. Disabling ligatures also affects the em dash, making dates appear in a less conventional format. The build generates dist/resume/Ata Kuyumcu - CV.pdf. The dictionary is indexed based on dist/resume/main.pdf, which was the original filename before I altered it to provide recruiters with a more appealing download option.

In every test run, relative was False. I confirmed this by manually changing the expected author to someone else and rerunning the suite; the outcome was positive, indicating the check compares documents rather than the author's name. The suite cannot determine if the CV was authored by someone else entirely. This was the sole assertion in the file that validated which document this is.

The remaining four checks assess the file's features. A valid header, metadata, pages, and text confirm that the document is a PDF of your CV, satisfying all four test conditions. The assertion that was supposed to verify the author's name silently fails when the filename is renamed, while the tests continue to print "Author: Ata Kuyumcu" above the check that lacks any comparison.

A similar flaw surfaced in Continuous Integration (CI). The templates request the use of Charis SIL; however, the runner failed to install it. Typst responded to a missing font family with a warning and exited with a zero status code. As a result, CI published a perfectly valid PDF with fallback serif for three weeks, while all four checks were content with the result.

The remediation entails installing the font and adding a single line of code. The version of Charis SIL is pinned at 6.101 since Charis version 7 renames the font family to simply "Charis." Typst resolves fonts by family name, so a newer, improved version of the correct font would still yield a silent fallback. Although there are four checks that describe a file, one solely describes the document and does not run, one employs a grep for a font, and the template incorporates defensive settings against a reader I have never encountered.

When examining it from this perspective, the scoreboard doesn't present a compelling case. Nonetheless, the 200-character check remains the one I would retain if I could only keep one, as it is the most likely to fail. This is because "the text layer broke" is an actual occurrence in PDFs, which remains undetectable visually. The other measures stem from conjectures about what a parser desires, with occasional instances, such as ligatures, allowing me to prove my guess was incorrect and proceeding nonetheless.

I did address the author check, though not by rectifying the key. Correcting the key would have left the shape of the bug intact: a lookup that yields nothing does nothing, quietly, and the next filename change would restart the cycle. Now, the check uses a constant compared across every PDF in dist/, eliminating the risk of a lookup that consistently fails.

I verified the effectiveness of this fix by intentionally corrupting the constant, causing the suite to display red, which is the check I should have performed initially on the original version.

Written by urgent.news from Lobsters's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.

Read the original at blog.lvmbdv.dev →

More in Tech

More from Tuesday 4 August →