Monday, 18 January 2010

Better output testing HTML and other long strings

If you ever wrote or ran a website test in Perl, you probably used Rafaël Garcia-Suarez's wonderful Test::LongString, even if you never heard of it before. Not only is it used by lots of CPAN modules, it is the foundation of Test::WWW::Mechanize test functions, with flavors for Catalyst, PSGI, CGIApp and several others. But it doesn't have to be HTML content testing - any string output can be tested with its awesome functions.

Maybe Test::LongString's most common function is contains_string(), which you may know as Test::WWW::Mechanize's $mech->content_contains() method. When it fails, the failing test output shows the original string and the text it was trying to find:

# searched: "foo bar"
# can't find: "baz"

Problem is, when the original string is too long, you get only the beginning of it. This happens a lot when you're trying to find content inside HTML, like:

# searched: "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Trans"...
# can't find: "some random content"

Such output is only barely useful, and I got fed up of having to edit a test file manually, add diag() calls to see the complete output, then ack for the wanted string to see what went wrong. So I made a small patch to Test::LongString, which Rafaël promptly accepted (yup, he rocks, but we all know that ;-).

Now, whenever such test fails, you'll get two extra lines:

# searched: "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Trans"...
# can't find: "some random content"
# LCSS: "ome random content"
# LCSS context: "d="content" class="foo">Some random content!</div>"

"LCSS" stands for Longest Common SubString, meaning you get whatever matched the most inside the original content (note that LCSS is not the same as LCS, or Longest Common Subsequence, which would go for a non-sequential match as seen in diff-like outputs). And, of course, "LCSS context" means the surroundings of the LCSS string just found.

Now, just by looking at our example, we know exactly why the test failed, and we are free to fix either the test suite or the application.

Know what's best? You get all that for free, no need to change a single line in your tests. Just update Test::LongString to 0.12 or later and enjoy! :-)


  1. shame the POD's not been updated...

  2. Indeed. But Rafael is already aware of this and a new version with the documentation should come out soon. This is one of the reasons for this post =)

  3. BUUUUUU!!! te achei!!! =D (quer dizer, te acharam por mim, hahahaha!!!)
    aparece no meu blog, seu coisa! ó, nem li suas paradas de Perl, ñ entendo bulhufas, literalmente "pérolas aos porcos"!! XD (desculpe o trocadilho infame!!)

    Caraca, tem comment aqui até em chinês!! O.o Joga no google translator, hehehe

    saudade de vc, viiiu?? Depois eu te falo sobre meu amigo q te achou! ^_^