Collegiale documentatie

Ik ken geen enkele ontwikkelaar die het leuk vindt om documentatie te schrijven. - Dat is waarschijnlijk de reden waarom ontwikkelaars zo graag zeggen: goede code documenteert zichzelf. Dat is het ultieme excuus om je alleen maar te hoeven focussen op de onderdelen van je werk die je wél leuk vindt, namelijk: code schrijven.

De crux is natuurlijk dat goede code zichzelf vaak documenteert via de aanwezigheid van unittests - en ik ken maar weinig ontwikkelaars die het leuk vinden om unittests te schrijven. De aan- of afwezigheid van unittests, verraadt of de bovenstaande uitspraak een diepgaande wijsheid is, of inderdaad een excuus.

Hoe dan ook, laatst kwam ik in de ongemakkelijke positie daadwerkelijk documentatie te moeten schrijven. Geen code, geen unittests - nee: een ouderwetse README.md met instructies voor mijn collega’s.

PDF’s testen

Dat zat zo: we gebruiken sinds kort een library genaamd QuestPDF om PDF-representaties te kunnen genereren van toetsen. (Zie ook deze blog.) Omdat ik nu eenmaal ik ben, heb ik me er hard voor gemaakt die functionaliteit grondig te testen.

De vraag is natuurlijk: hoe test je code die een toets als input verwacht, en een PDF als output uitspuugt? Dat is gelukkig een probleem dat mijn team en ik niet zelf hoeven op te lossen. Er bestaat een open source library genaamd Verify.QuestPDF - wat op zijn beurt een extensie is op een open source library genaamd Verify - die in deze behoefte voorziet.

Ik heb me dus een halve Sprint beziggehouden met het schrijven van tientallen unittests die elk hoekje en gaatje van onze AssessmentTestPdfGenerator test en was heel tevreden met mezelf.

“Wat doe ik verkeerd?”

Toen kreeg ik de vraag van mijn collega: “Hé, ik heb een unittest geschreven voor een nieuw stukje code, maar ik krijg ’m maar niet groen. Wat doe ik verkeerd?”

Het antwoord was: helemaal niets, je moet alleen even weten hoe Verify de uitkomst van haar tests, eh, verifieerd. Ik loodste mijn collega door het proces - en beloofde: ik zal hier even wat documentatie voor schrijven, want jij gaat hopelijk ongetwijfeld niet de laatste zijn die hier tegenaan loopt.

Ik ken geen enkele ontwikkelaar die het leuk vindt om documentatie te schrijven - ik ook niet - en dat is omdat goede documentatie schrijven moeilijk is. Het is moeilijk, omdat je je vanuit een positie van iemand die snapt hoe iets werkt, je in moet leven in iemand die dat begrip nog niet heeft. Dat “even” documentatie schrijven werd daarom al gauw “een uur” documentatie schrijven.

README.md

Maar het resultaat is volgens mij wel de moeite waard, dus laten we er even (…een uur?) naar kijken.

Instructions on how to use Verify to test PDF generation

TL;DR

Make sure this folder contains a file named {testClass}.{testName}.received.png and a file named {testClass}.{testName}.received.txt in order to make your tests pass. These files specify what correct PDF should look like for each test.

On Verify

The unit tests in this folder use Verify to assert the correct generation of PDF AssessmentTests. It also uses some code, based on Verify.QuestPDF1, to verify the contents of your newly generated PDFs. The code for this functionality can be found in the subfolder named VerifyQuestPDF2.

Verify is a library that requires you to specify what the correct result looks like in a very specific way. It assumes the existence of some files, and will compare the output of each unit test to those files.

Test outputs

Each Verify test produces (at least) two files in the same folder as the test:

  1. An image named {testClass}.{testName}.received.png

  2. A text file named {testClass}.{testName}.received.txt

These files represent the output of the test. The first file shows a representation of the PDF in an image format, the second file specifies the metadata of the generated PDF.

The files will be compared to two files named {testClass}.{testName}.verified.png and {testClass}.{testName}.verified.txt respectively, which are assumed to live in the same folder.

Why your test fails

If you write a new test, it will fail for two reasons.

  1. Verify will try to compare the image output of your test with a file named {testClass}.{testName}.verified.png. However, such a file does not yet exist. Since the test does not have anything to compare {testClass}.{testName}.received.png with, it will fail.

  2. Verify will compare the textual output of your test with a file named {testClass}.{testName}.verified.txt. By default, Verify will generate an empty document with this name. This will by definition not match the outcome of the test, since in your test you’ve generated a PDF, thus resulting in a failing test.

How to make your test(s) pass

In order to make your test pass, you will have to specify what a succesful outcome should look like for both files.

  1. First, inspect {testClass}.{testName}.received.png. If it matches your expectation, rename the file to {testClass}.{testName}.verified.png. (A new file named {testClass}.{testName}.received.png will be generated on each subsequent test run, so you don’t have to worry about losing any information.)

  2. Then, copy the contents of {testClass}.{testName}.received.txt to {testClass}.{testName}.verified.txt.

Now, Verify has an idea of what a successful test looks like. On each test run, it will compare these files with the output of the test, i.e. two newly generated files named *.received.*. If they match the verified results, the tests will pass.

Happy testing!

Commentaar

Ik zou graag de aandacht willen vestigen op de volgende punten:

Documentatie en code

Lang verhaal kort: er komen best wel wat overwegingen kijken bij het schrijven - en herschrijven! - van documentatie. Documentatie schrijven is net als code schrijven: een iteratief proces, waarbij je je bij elke stap af dient te vragen of je de boel wat schoner, wat helderder, wat toegankelijker hebt achtergelaten dan je het aantrof.

Nee, zo leuk als coderen zal het nooit worden. Maar elke keer als een ontwikkelaar de tijd neemt voor documentatie, plukt het team daar de vruchten van plukken. Dat “even” documenteren betaalt zich dubbel en dwars terug.


  1. Ik heb de code van Verify.QuestPDF onze codebase ingetrokken en licht aangepast, omdat deze me op bepaalde plekken beperkte in wat ik wilde. Het totale aantal regels code is beperkt en de werking mijn eigen wijzigingen heb ik via unittests gedocumenteerd (!). Daardoor is dit extra kleine beetje onderhoudslast dat ik op de schouders van mijn team leg, volgens mij gerechtvaardigd. ↩︎

  2. Het oorspronkelijke document linkt hier direct naar de folder in kwestie. ↩︎

communicatie · documentatie · samenwerking · software ontwikkelen · testen