Testing Antora sites

This project provides utilities and guidelines for testing Antora documentation sites.

Quarkiverse projects usually host their Antora documentation in a dedicated docs Maven module. After adding the quarkus-antora dependency, you can not only life-edit the site in Quarkus dev mode but also

  • Test that Antora is able to generate the site from your AsciiDoc sources

  • Ensure that all external links are valid.

Basic @QuarkusTest

The way we test the site generation is not much different from testing any other Quarkus application.

First, you need to add the necessary dependencies

        <dependency>
            <groupId>io.quarkiverse.antora</groupId>
            <artifactId>quarkus-antora</artifactId>
        </dependency>

        <!-- Test dependencies -->
        <dependency>
            <groupId>io.quarkus</groupId>
            <artifactId>quarkus-junit5</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>io.rest-assured</groupId>
            <artifactId>rest-assured</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.assertj</groupId>
            <artifactId>assertj-core</artifactId>
            <scope>test</scope>
        </dependency>

Then you can add a basic @QuarkusTest as follows:

import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.Test;

import io.quarkus.test.junit.QuarkusTest;
import io.restassured.RestAssured;
import io.restassured.http.ContentType;

@QuarkusTest /* the @QuarkusTest annotation lets Quarkus build and start the Antora site on http://localhost:8081/ */
public class AntoraSiteTest {

    @Test
    public void getIndex() {

        /*
         * If the site was built successfully,
         * we can get the index page and check that
         * it contains some expected content
         */
        RestAssured
                .given()
                .contentType(ContentType.HTML)
                .get("/quarkus-antora/dev/index.html")
                .then()
                .statusCode(200)
                .body(CoreMatchers.containsString("<h1 class=\"page\">Quarkus Antora</h1>"));
    }
    ...
}

The sample code snippets used in this section come from the docs module of Quarkus Antora

Antora takes care for validating internal cross-references but it does not help much with ensuring that external links point to existing resources.

That’s where the AntoraTestUtils class provided by Quarkus Antora may come in handy.

To use it, you need to add the following dependency:

        <dependency>
            <groupId>io.quarkiverse.antora</groupId>
            <artifactId>quarkus-antora-utils</artifactId>
            <scope>test</scope>
        </dependency>

Then you can use it in a test as follows:

    @Test
    public void externalLinks() {

        Set<String> ignorables = Set.of(
                /* Broken links available in test-page.adoc for the sake of testing */
                "https://salkjasjhashgajhhsahgahjas.com",
                "https://quarkus.io/fake-page",
                "https://quarkus.io/guides/building-native-image#fake-fragment");

        AntoraTestUtils.assertExternalLinksValid(err -> ignorables.contains(err.uri()));
    }

In the test, we instruct the link validator to ignore some remote URIs, that we intentionally placed into test-page.adoc for the sake of testing AntoraTestUtils itself.

If you would like to see the dead link detection in action, just remove the links from the ignorables Set. After that, you should see test fail with a report like the following:

[ERROR]   AntoraSiteTest.externalLinks:41
 - /home/user/projects/quarkus-antora/docs/modules/ROOT/pages/test-page.adoc:15
     - https://quarkus.io/fake-page
         - 404
 - /home/user/projects/quarkus-antora/docs/modules/ROOT/pages/test-page.adoc:14
     - https://salkjasjhashgajhhsahgahjas.com
         - Unknown host salkjasjhashgajhhsahgahjas.com
 - /home/user/projects/quarkus-antora/modules/ROOT/pages/test-page.adoc:16
     - https://quarkus.io/guides/building-native-image#fake-fragment
         - Could not find #fake-fragment