Zum Inhalt springen
iSAQB-blog Examination to AsciiDoc-cover-website-310321

Migrating the iSAQB® Mock Exami­nation to AsciiDoc

The iSAQB provides a mock exam for the Foundation Level certification. This post shows how we moved this exam from docx format to AsciiDoc, facili­tating colla­bo­ration and enabling automated generation of the required multi­lingual document variants. So, this is the story of how we moved from Microsoft Word to AsciiDoc for the colla­bo­ration on files whilst also reducing overhead for formatting to a minimum.

Context
To facilitate prepa­ration for the iSAQB CPSA-Foundation Level exami­nation, the iSAQB maintains a freely available mock exami­nation, containing around 40 questions. In addition, a second document containing the correct solutions to the questions is available. These document-pairs are maintained in several languages, starting with English, German, and Spanish.

Right from its creation in mid-2020, the iSAQB used Microsoft Word (‚*.docx‚) for this purpose in a disctinct GitHub repository, allowing for public issue tracking and change requests. Questions, answers and different language versions were all kept in separate documents. Each version was then converted to PDF files which are available for download.

As the mock exam has been actively used by more than 100 people since then, dozens of change requests were raised and numerous bugs identified in either questions or anwsers. That resulted in frequent updates to the ‚*.docx‚ files without any proper option to see what had changed in each commit. Language versions got out of sync, and due to the lack of proper diff capabi­lities, reviews of changes became incre­a­singly difficult.

Start from scratch: Collecting requirements
We (the authors, Ben and Gernot) started improving the maintenance and publi­shing process of these documents by collecting some requirements:

  1. Questions and corre­sponding answers need to be absolutely in sync. The (PDF) output for questions and answers shall be contained in two separate documents, but the content (source) shall be a single source. See below for an excerpt of a hypothe­tical question document (left side) plus answer document (right side).
  2. Multiple language versions (English, German, Spanish, and others) need to be kept in sync.
  3. Downloadable documents shall be PDF, formatting should follow iSAQB conven­tions, using the same layout and fonts that are used for other official iSAQB documents.
  4. Changes to both questions and answers shall be documented by a detailed changelog, so that trainers of iSAQB courses and workshops can track those changes and update their own derived artifacts accord­ingly. Side note: One of our colleagues maintains the mock exami­nation as an online quiz with automatic score calculation.
  5. Contri­bu­tions and sugges­tions for impro­ve­ments shall be simple and trans­parent (like in GitHub pull requests)
  6. The tooling shall be platform independent, as contri­butors cannot be forced to use a specific operating system.

Overall approach
Several other official iSAQB documents are already maintained in AsciiDoc format, layouted and published by a fully automated workflow. As the existing approach has been working smoothly for more than 2 years for multiple curricula in multiple languages, we decided to take that as a starting point. As an added benefit, these proven and public tooling allows everyone to provide insights on and sugges­tions for impro­ve­ments to the mock exam by using GitHub issues, or even create pull requests.

Our workhorse is an automated document build process based upon Gradle and AsciiDoctor. We assume that you (dear readers) know about markup languages like Markdown and AsciiDoc , therefore we will skip an intro­duction to their under­lying concepts (the link section below contains some references).

AsciiDoc for complex documents AsciiDoc has been created with large and complex documents in mind, which is why it provides some highly useful features: Our most valuable of those is the flexible ‚include‘:
The diagram below shows our modula­riz­ation approach, which is centered around the separation of concerns principle. Starting from the root document, an asciidoc file, other files are included. These files are either content fileor structure files:

  •  Content files, as the name implies, carry the documents‘ content—in our case explana­tions, exami­nation rules etc. They do not contain any additional include directives.
  • Structure files, on the other hand, include other files only.

Mock exam document structure
As we love the separation-of-concern principle so much, we factored out a few parts into separate files:

  • ‚setup.adoc‚: declares several specific AsciiDoctor variables we require for building the documents. We will describe those in detail below.
  • ‚i18n-definitions.adoc‚ declares variables for trans­la­tions, like „table of contents“ and other stuff.
  • ‚introduction.adoc‚ contains a description of the types of questions plus some forma­lities required by iSAQB.
  • ‚q‑structure.adoc‚ is the structure-file containing all include state­ments for all of the question files.

Multi-lingual documents
Remember our requi­rement No. 2: Support multiple languages. Our content files contain text in several languages (currently English and German).

How come our output documents are either English or German? The answer lies in the combi­nation of the ‚include‚ statement with the powerful AsciiDoctor ‚tag‚ mechanism plus our automated build. Let’s begin with the tagged-include. See the following diagram for an example:

Within our content documents, the specific trans­la­tions are placed within a pair of ‚tags=‚ as shown in the diagram above and the AsciiDoc example below. The important part of the include statement is contained in the square brackets: ‚[tags=„EN“]‚. Only the parts of each AsciiDoc document are included, which are written between the beginning ‚// tag::EN[]‚ and end ‚// end::EN[]‚ of such a named tag. These tag state­ments are always written in a commented line, so they can never be confused with real document content.

// tag::EN[]
What is the result of "6 * 7"?
// end::EN[]

// tag::DE[]
Was ist das Ergebnis von "6 * 7"?
// end::DE[]

Now we’re getting close – but how to build two different languages with the same structure file? This is where the concept of AsciiDoctor variables comes into play:
Our include state­ments contain the language as a variable, which itself is set by the Gradle build process. The real include statement, taken from the ‚q‑structure.adoc‚ file, reads as follows:

include::question01.adoc[{include_configuration}]

The ‚{include_configuration}‚ variable is either set to „EN“ and „DE“, depending on what language version shall be generated. Neat, right? This include-tag-build combi­nation allows us to implement the „single-source“ principle, keeping a single exami­nation question in multiple languages in a single file.

Creating question and answer sheets
But we’re still not finished: Apart from generating multiple languages in distinct PDF documents, we need to generate a separate document for questions and answers. For this purpose, we make use of AsciiDoctor variables again, combined with the ‚ifdef::‚ directive. Take a look at the following snippet, taken from our ‚setup.adoc‚ file (inden­tation added for better readability):

:withAnswers!:
:n: [ ]
:y: [ ]
ifdef::withAnswers[]
:n: [ ]
:y: [X]
endif::withAnswers[]

We declare two variables, ‚:n:‚ (no, repre­senting a wrong answer) and ‚:y‚ (yes, repre­senting a correct answer). The appro­xi­mately 40 different exami­nation question files are all written as follows (some formating tags excluded for better readability):

// tag::EN[]

=== Question 3

A-Question: Select one option 1 Point

What is the result of "6 * 7"

{n} a) 67
{n} b) 13
{y} c) 42

// end::EN[]

The third and correct answer is preceeded by the yes variable ‚{y}‚, as AsciiDoctor variables are declared within ‚:‚, but used within ‚{}‚. Again, our Gradle build sets the variable :withAnswers: to both ‚true‚ and ‚false‚ subse­quently, resulting in one document generated with only ‚[ ]‚. Due to the flexi­bility of Gradle, it’s easy to change the name of the generated build artifacts to „mock-exam-questions-en.pdf“ when the ‚withAnswers‚ variable is ‚false‚, and to „mock-exam-answers-en.pdf“ when it’s ‚true‚. Finally, it’s done! We created a build matrix for documents! Really cool, and incredibly more fun than editing a ‚docx‚ binary document. But wait (again) – what about styling and layout? We need to use the official iSAQB font (actually, a free Roboto font).

Layout and styling with AsciiDoctorPDF
AsciiDoc can be trans­formed directly to PDF via AsciiDoc­torPDF. There we can configure formatting and styles in YAML: Logos, spacing, margins, table formats, fonts, anything you need. We outsourced this confi­gu­ration to a separate Git repository – an approach already in use with other iSAQB documents. We add this repository as Git submodule, which may sound cumbersome at first, but it allows us to change essential layout options centrally (for example, adding a new logo to the headers of all documents, not only the mock-exam discussed here). In such a case, the individual document reposi­tories only need to update the pdf-theme submodule via the Git command ‚git submodule update‚. We’re honest with you: Confi­guring styling and layout in YAML isn’t exactly for the fainthe­arted. But as the braver one of us, Ben has already conquered this dungeon in his quest for properly layouting various curricula, we could easily reuse his former effort.

Automatic releases with GitHub Actions
Alright, let’s recap: We have our toolchain (Gradle/AsciiDoctorPDF), content and structure files, the possi­bility to create language- and content-specific results, and a styling confi­gu­ration that ensures beautiful and consistent output. All that’s missing is some automation. Since all our stuff is already on GitHub, it only seems natural to use GitHub Actions to automa­ti­cally create new releases. We defined some workflow scripts which generate the PDF files for us, for a specific version. (All releases are available from the iSAQB GitHub overview page.)

In addition to the script that creates real releases, we also added automated builds for pull requests and the main branch of the repository. This guarantees that no broken files or code are checked in with a pull request that would break our release build. The only fiddly part of the release process is the definition of the release version number. At the moment, it has to be defined in its own file and adjusted manually with each new release. However, we’re already working on extracting that information from the release tags that we use to mark our releases and trigger the automated build.

The Future
As exami­nation candi­dates usually fail at the same questions, trainers always have to explain these questions over and over again. We currently think of including explana­tions for the most difficult questions in the answer documents to give candi­dates the chance to under­stand why specific options are correct or wrong. To enable these explana­tions, we have added another variable to our include concept, called ‚:explanation:‚. If this variable is set during build, then we will also include content written between the ‚tag::[explanation]‚. As of March 2021, this has not been used in any of the mock exami­nation questions, but in our opinion it’s only a matter of time until the first volun­teers contribute explana­tions or links, to facilitate exami­nation prepa­ration for future iSAQB candidates.

Conclusion
Although binary document formats like ‚*.docx‚ are ubiquitous and accepted, they impose restric­tions not suitable for complex document requirements. A purely textual format like AsciiDoc enables highly flexible confi­gu­ration and generation options—plus adjus­table options for output and styling. Besides, it’s in line with estab­lished colla­bo­rative develo­pment processes and more fun for developers. Did we mention that AsciiDoctor rocks? It allows for great modula­riz­ation and seperation-of-concern.

Acknow­led­ge­ments
Thanks to the numerous contri­butors to the content of the iSAQB mock exami­nation and the members of the iSAQB Foundation Level Working Group. Our work of initially creating and maintaining the toolchain that now drives most iSAQB documents was made possible by countless contri­bu­tions by other volun­teers: Special thanks to Ralf D. Müller, Peter Götz, Alexander Heusingfeld, Alexander Lorz and Roger Rhoades.

Without the awesome under­lying open source tools like AsciiDoc, AsciiDoctor, Gradle and AsciiDoc­torPDF, the approach described in this post would not have been possible. We are grateful to the authors and maintainers of these libraries and frameworks!

Despite having families and non-IT hobbies, doing open source work is a source of pleasure and satis­faction for both of us. May this post motivate others to invest time and energy in free software.

Links and further information
iSAQB public document site: The collection of iSAQB documents that are already maintained in AsciiDoc and build/published automatically.

AsciiDoctor: Transform AsciiDoc into HTML or other formats.

AsciiDoc­torPDF: Natively converts AsciiDoc into PDF, taking the pain out of creating PDF documents from AsciiDoc. Used for iSAQB documents.

AsciiDoctor IntelliJ plugin: Created and maintained by Alexander Schwartz.

Teilen Sie diesen Artikel:

An diesem Artikel beteiligt

Benjamin Wolf
Organisation
INNOQ
Land
Deutschland

Dr. Gernot Starke
Organisation
arc42
Land
Deutschland

Bleiben Sie informiert mit dem iSAQB®-Newsletter!

Nach oben scrollen