diff --git a/tetras_extraction/macao_12/script/src/test.py b/tetras_extraction/macao_12/script/src/test.py
index 7ec2a965c1b9f8e561c56538d316dde12a8d613c..d0500446047a845f9d4d7c29440d7692d0d6766c 100644
--- a/tetras_extraction/macao_12/script/src/test.py
+++ b/tetras_extraction/macao_12/script/src/test.py
@@ -1,12 +1,94 @@
+# pyright: reportIndexIssue=false, reportCallIssue=false, reportArgumentType=false
+# (This simplifies attribute access for `SPARQLResult`s, it is acceptable in a
+# testing context because an AttributeError means that the test failed.)
+
 import subprocess
 import unittest
 from pathlib import Path
 
-from common import RESULT_DIR
+from rdflib import Graph
+
+import extract
+from common import *
 
 TESTS_DIR = Path(RESULT_DIR + "/../tests").resolve()
 
 
+class TestExtracted(unittest.TestCase):
+    """Test the RDF data extracted from the source"""
+
+    def __init__(self, methodName):  # pyright: ignore[reportMissingParameterType]
+        super().__init__(methodName)
+        self.graph = Graph()
+
+    def runTest(self):
+        extract.main()
+        # Load graph
+        self.graph.bind("", NS)
+        self.graph.parse(RDF_SCHEMA_FILE)
+        self.graph.parse(RDF_CONTENT_FILE)
+
+        self.maxDiff = None  # see full diff on failure
+        with self.subTest("pg8251"):
+            result = self.graph.query(
+                """
+                            select * where {
+                            ?act :id ?id .
+                            optional { ?act :index ?index }
+                            optional { ?act :description ?description }
+                            optional { ?act :commentaireSugg ?commentaireSugg }
+                            optional { ?act :commentaireSucces ?commentaireSucces }
+                            optional { ?act :aReponse ?reponse }
+                            filter(?act = :pg8251)
+                        }"""
+            )
+            self.assertGreater(len(result), 0)
+            # Check values of SPARQL variables
+            # Expected values are copied from the original source by hand
+            act = next(iter(result))
+            self.assertEqual(str(act["id"]), "pg8251")
+            self.assertEqual(str(act["index"]), "3")
+            self.assertEqual(
+                str(act["description"]),
+                """<div id="STY_question" class="STY_question" style="  "><p align=""><br><br><br><br>
+        <table class="STY_tableau" width="300" cellpadding="3" cellspacing="0" valign="top" border="0">
+            <tr>
+                <td valign="top">
+                    <script type="text/javascript">ajDocW(PF_clipAV('clipAV74', 'e29_macao1_2a3.swf', '18', '18', 'false', 'Flash', 'false', '', 'Quality:high;wmode:transparent', ''));</script>
+                </td>
+                <td valign="top"><p align="">"Will you post this letter tomorrow?"<br>"Don't worry, I will see to it."
+                </p>
+                    <p align=""> </p></td>
+            </tr>
+            <tr>
+                <td valign="top">
+                    <script type="text/javascript">ajDocW(PF_clipAV('clipAV66', 'e29_macao1_2a4.swf', '18', '18', 'false', 'Flash', 'false', '', 'Quality:high;wmode:transparent', ''));</script>
+                </td>
+                <td valign="top">"Will you come?"<br>"Yes, I will."</td>
+            </tr>
+        </table>
+        <br><br>Dans la réponse de chaque dialogue, l'auxiliaire WILL est-il prononcé de façon identique ? Ecoutez de
+        nouveau les réponses et sélectionnez l'un des deux choix :</p></div><div id="divConsigne" onclick="SPE_clicDansBulle(event,'divConsigne')"></div>""",
+            )
+            self.assertEqual(
+                str(act["commentaireSucces"]),
+                """<div id="divCmtSucces" onclick="SPE_clicDansBulle(event,'divCmtSucces')"><p align="">
+        <br><br><br><br><br><br><br><br><br><br>Bien !</p>
+        <p align="">L'auxiliaire de la première réponse comporte une <b><a class="STY_lienDansZoneComt"
+                                                                           href="javascript:parent.SCO_ouvrirDoc('voyelle_reduite','htm')">voyelle
+            réduite</a></b> ; ce n'est pas le cas de la deuxième réponse.</p></div>""",
+            )
+            self.assertEqual(
+                str(act["commentaireSugg"]),
+                """<div id="divSugg1" onclick="SPE_clicDansBulle(event,'divSugg1')"><p align="">
+        <br><br><br><br><br><br><br><br><br><br>Non. Vous vous êtes trompé.</p>
+        <p align="">L'auxiliaire de la première réponse comporte une <b><a class="STY_lienDansZoneComt"
+                                                                           href="javascript:parent.SCO_ouvrirDoc('voyelle_reduite','htm')">voyelle réduite</a></b>
+            ; ce n'est pas le cas de la deuxième réponse. Vous pouvez réécouter chaque énoncé en cliquant sur le
+            haut-parleur.</p></div>""",
+            )
+
+
 class CompareFiles(unittest.TestCase):
     """A test case that checks every file in `TESTS_DIR`, finds the corresponding
     file in the generated results (in `RESULT_DIR`) and compares them using