Fun with software testing


Before I released PDF::Cairo, I gave it a basic test suite to make sure that everything at least loaded correctly. I wanted to fully exercise the various methods, but that wouldn’t tell me if they actually worked or not. I needed to put ink on the page, and then compare it with a reference page. Automatically, using tools likely to be available (or at least easily installed) on the target platforms. I decided to generate an N-page PDF with small pages, draw a single test per page, and convert the results to a series of PNG files; if they were byte-for-byte identical to the files generated from the reference PDF, the tests passed.

ImageMagick’s convert utility was out, even though I currently use it to import non-PNG images into PDF::Cairo, because it can choose between multiple PDF backends, and I didn’t want the added test complexity. I considered Ghostscript, which I have a few decades of practice with, but then I came across Poppler’s pdftocairo utility. Not only does it have the functionality I need, but it’s built on Cairo, FreeType, and Fontconfig, the same libraries I’m generating the PDFs with in the first place.

Here’s what it looks like:

my $pdf = PDF::Cairo->new(
    width => in(2),
    height => in(2),
    file => $OUT,
);
...
push(@test_desc, "bezier curves");
$pdf->move(10, 10);
$pdf->curve(20, 120, 40, 40, 140, 60);
$pdf->rel_curve(-10, 10, -40, 40, -100, -30);
$pdf->linedash([12, 4, 8], 2);
$pdf->linewidth(4);
$pdf->stroke;
$pdf->newpage;
...
$pdf->write;
...
SKIP: {
  my $tmp = `pdftocairo -v 2>&1` || '';
  skip("need poppler's pdftocairo to compare images")
    unless $tmp =~ /pdftocairo/;
  my $PDFTOCAIRO = "pdftocairo -png -r 200 -antialias gray";
  system("$PDFTOCAIRO t/02-cairo.pdf $TMP/ref");
  system("$PDFTOCAIRO $OUT $TMP/02");
  foreach my $i (1..@test_desc) {
    $i = sprintf("%02d", $i);
    my $test = "page $i: " . shift(@test_desc);
    subtest $test => sub {
      plan tests => 3;
      ok(-s "$TMP/ref-$i.png", "reference page non-empty?");
      ok(-s "$TMP/02-$i.png", "page non-empty?");
      ok(compare("$TMP/02-$i.png", "$TMP/ref-$i.png") == 0,
        "page matches reference?");
    }
  }
}

Works quite nicely on Mac and Linux, and the small page size speeds up the PNG conversion. To test text methods, I had to add a free TTF font from Google Fonts. I can’t really test the effect of Fontconfig font substitution, which also means that I can’t really test Pango font-handling; currently, the work-in-progress Pango tests only run if you install the fonts included in the tarball.

Naturally, the act of writing the tests smoked out half a dozen bugs, so once I had decent coverage of the main module, I pushed out a new release to Github and CPAN.


Comments via Isso

Markdown formatting and simple HTML accepted.

Sometimes you have to double-click to enter text in the form (interaction between Isso and Bootstrap?). Tab is more reliable.