Hello Marc,

On Thu, 14 Nov 2024 17:06:11 +0100
Marc Chantreux <m...@unistra.fr> wrote:

> 
> I also realized I was unconfortable to touch anything without having a
> test suite so I was trying to find some existing use of dformat to make
> sure the rendering was ok.
> 

Though a project of much smaller scale and lesser complexity than `dformat`, I
experience(d) a similar situation.  Instead of the intended edit/update to
newer standards of the original source code itself, I started to build tests
to learn how the program works _for now_; a bit like a safety net for future
edits.  Especially for processing options I usually don't use, or not that
often.

Today, I noticed the sequence of i) defining a structure in `chem`, ii)
passing through the preprocessors to eventually iii) let `groff` write a
postscript yields plain ASCII.  This allows to monitor changes with Python's
`pytest` «from the outside».  That is, contrasting to check a specific Python
function with `pytest`, to aliment the whole executable like black box with a
string and only check if its digest/output still is the same.  I compiled this
concept in script `test_case.py` attached -- `pytest` would report if/which
of these tests failed.

In perspective to expand «test coverage» of `chem`, additional tests were
useful.  One could organize them with a label in the test script, to call
`pytest` to probe only those sharing a marker in common.  To illustrate this
optional constraint, this email equally includes `pytest.ini`.

Though seemingly simple (no processing of binary data like a .pdf), there
might be other approaches more efficient and obvious to those in the know,
backed by their studies of computer science.  While I have not, suggestions are
welcome to perhaps improve `chem` a little bit.  (Personally I would prefer if
the example tested would yield indentations expressed only by explicit blank
spaces, instead of a mixture of spaces and tabs.)

`Dformat` could be direction somewhat independent from `chem`.  My first
attempt to install it locally (based on commit `e74ea9a` in your repository)
failed which I attribute to an unrecognized error on my side.  I'll send you
my log separately.

Regards,

Norwid

Attachment: pytest.ini
Description: Binary data

#!/usr/bin/env python3
"""proposal to test the results generated by groff preprocessor chem

With plain text output of `chem`, it could be checked by Python's
non-standard module `pytest`.  One possible workflow to use this script
in Linux Debian is

- have an instance of Python
- set up a Python virtual environment proper by the commands of

``` shell
python -m venv sup
source ./sup/bin/activate
pip install pytest  # cable to PyPI
```

- to run tests by `python -m pytest`.  The report to the CLI can be more
  verbose (with the optional flag `-v`), include results of print command
  (`-s`), or exit after the first test to fail (`-x`),
- optional: uncomment the marker in line 61; this and the then mandatory
  file `pytest.ini` allow to constrain the tests performed to a sub set.
  For the present case / as a  demonstration, the call then were

  ```shell
  python -m pytest -m chem
  ```

  which still can be combined with all other optional pyest parameters.

Written in Linux Debian 13/trixie with Python (version 3.12.6) and
additional `pytest` (8.3.3) and `pluggy` (1.5.0, both installed from
Debian's repositories)."""

import os
import subprocess as sub

import pytest  # resolve this dependency via PyPI/pip


def test_equality():
    assert 67 == 67


def test_where_is_awk():
    """reach out to awk on the CLI

    In Linux Debian 13/trixie `which awk` defaults to `/usr/bin/awk`"""
    result = sub.run(
        ["which", "awk"],
        stdout=sub.PIPE,
        stderr=sub.PIPE,
        text=True,
        check=True)
    assert result.stdout.strip() == "/usr/bin/awk"


def test_where_is_chem():
    """reach out to chem as packaged by Debian"""
    result = sub.run(
        ["which", "chem"],
        stdout=sub.PIPE,
        stderr=sub.PIPE,
        text=True,
        check=True)
    assert result.stdout.strip() == "/usr/bin/chem"


# @pytest.mark.chem  # uncomment this for an optional `pytest -m chem`
def test_chem_example_01():
    """test first example in the documentation

    Some characters in the strings submitted to be written or/and tested
    may have a meaning to the shell (default Debian: bash).  To prevent
    this complication / a need to escape them, it is safer to process
    them as r-strings, than plain strings."""
    probe_in = str("""
.cstart
    CH3
    bond
    CH2
    bond
.cend
    """)

    expected_out = str(r""".PS
copy "/usr/share/groff/1.23.0/pic/chem.pic"
	textht = 0.16; textwid = .1; cwid = 0.12
	lineht = 0.2; linewid = 0.2
Last: 0,0

#    CH3
Last: CH3: atom("CH\s-3\d3\u\s+3", 0.3, 0.16, 0.06, 0.16, 0.12, 0.015) with .L.w at Last.e

#    bond
Last: bond(0.2, 90, from Last.R.e )

#    CH2
Last: CH2: atom("CH\s-3\d2\u\s+3", 0.3, 0.16, 0.06, 0.16, 0.12, 0.015) with .L.w at Last.end

#    bond
Last: bond(0.2, 90, from Last.R.e )
.PE
""")

    with open("input.ms", mode="w", encoding="utf8") as newfile:
        newfile.write(probe_in)

    sub.run(
        "chem input.ms > output.txt",
        shell=True,
        text=True,
        check=True)

    with open("output.txt", mode="r", encoding="utf-8") as source:
        read_out = source.read()
        print(read_out)  # for an optional more verbose output by `pytest -s`
    assert read_out == expected_out

    os.remove("output.txt")

Reply via email to