]> git.lyx.org Git - lyx.git/commitdiff
LyXHTML: add a script to validate all the generated files.
authorThibaut Cuvelier <tcuvelier@lyx.org>
Thu, 22 Dec 2022 23:47:45 +0000 (00:47 +0100)
committerThibaut Cuvelier <tcuvelier@lyx.org>
Sun, 25 Dec 2022 19:37:04 +0000 (20:37 +0100)
It could be a part of the standard test suite, but it might be quite long to run.

This test ensures that the generated XHTML files are valid HTML5 files, i.e. should display fine in all browsers.

development/thorough_export_tests/lyxhtml_validity.py [new file with mode: 0644]

diff --git a/development/thorough_export_tests/lyxhtml_validity.py b/development/thorough_export_tests/lyxhtml_validity.py
new file mode 100644 (file)
index 0000000..12c0cbd
--- /dev/null
@@ -0,0 +1,97 @@
+# Stricter version of the export tests: validate the XHTML code produced by
+# LyX' lyxhtml output as HTML5. It also validates the CSS and MathML parts.
+# Validation errors usually are mistakes in the generator.
+#
+# Call:
+#     python lyxhtml_validity.py PATH_TO_LYX/lyx
+#
+# Written with Python 3.8.8.
+# Requirements:
+# - Python package: html5validator: at least v0.4.2
+# - Java runtime engine (JRE): at least v8 (depending on html5validator)
+# Run:
+#     pip install html5validator>=0.4.2
+
+import collections
+import glob
+import sys
+import tempfile
+import os
+
+import html5validator
+
+
+if len(sys.argv) != 2:
+    print('Expecting one argument, the path to the LyX binary to test')
+if not os.path.exists(sys.argv[1]):
+    print('The given path does not point to an existing file')
+if not os.access(sys.argv[1], os.X_OK):
+    print('The given path does not point to an executable file')
+
+
+PATH_SCRIPT = os.path.dirname(os.path.realpath(__file__))
+PATH_EXPORT_TESTS = os.path.realpath(PATH_SCRIPT + '/../../autotests/export/')
+PATH_LYX = sys.argv[1]
+
+
+TestFile = collections.namedtuple(
+    "TestFile", ["lyx_path", "lyx_file_name", "xhtml_path", "xhtml_file_name"]
+)
+
+validator = html5validator.Validator(format='text')
+
+
+with tempfile.TemporaryDirectory() as out_dir_name:
+    all_lyx_files = glob.glob(PATH_EXPORT_TESTS + '/**/*.lyx', recursive=True)
+    all_files = [
+        TestFile(
+            lyx_path=path,
+            lyx_file_name=os.path.basename(path),
+            xhtml_path = os.path.join(out_dir_name, os.path.basename(path)),
+            xhtml_file_name=os.path.basename(path).replace('.lyx', '.html')
+        ) for path in all_lyx_files
+    ]
+    
+    # Generate XHTML files.
+    print(
+        f'Exporting {len(all_lyx_files)} LyX files to LyXHTML format in the ' +
+        f'directory {out_dir_name}'
+    )
+    
+    for file in all_files:
+        print(f'* Generating {file.lyx_file_name}...')
+        os.system(f'{PATH_LYX} --export-to xhtml "{file.xhtml_path}" "{file.lyx_path}"')
+        print(f'> Done generating {file.lyx_path} to {file.xhtml_path}')
+        
+        # print()
+        # print(open(file.xhtml_path, 'r').read())
+
+    print(f'Exported successfully all {len(all_lyx_files)} files!')
+
+    # Validate the XHTML files.
+    print(f'Validating {len(all_lyx_files)} XHTML files...')
+    
+    n_valid = 0
+    n_invalid = 0
+    for file in all_files:
+        print(f'* Validating {file.xhtml_file_name}...')
+        error_count = validator.validate([file.xhtml_file_name])
+        # Caution: this call outputs all validation errors to stdout!
+        # This line is equivalent to running vnu on the corresponding file.
+        # https://github.com/validator/validator
+        
+        if error_count == 0:
+            n_valid += 1
+            print(f'> Found no validation error!')
+        else:
+            n_invalid += 1
+            print(f'> Found {error_count} validation error{"" if error_count == 1 else "s"}!')
+
+    print(f'Validated all {len(all_lyx_files)} files! Among them:')
+    print(f'> {n_valid} were valid ({100.0 * n_valid / len(all_files)}%)')
+    print(f'> {n_invalid} were invalid ({100.0 * n_invalid / len(all_files)}%)')
+    
+    if n_invalid == 0:
+        print("That's excellent! Give yourself a pat on the back!")
+    elif 100.0 * n_invalid / len(all_files) <= 5.0:
+        print("That's a pretty good job!")