For apple-notes-to-sqlite I needed to write some tests that simulated executing the
osascript command using the Python
I wanted my tests to run on Linux CI machines, where that command would not exist.
After failing to use
unittest.mock.patch to solve this, I went looking for alternatives. I found pytest-subprocess.
Here's the relevant section of the test I wrote:
from apple_notes_to_sqlite.cli import cli, COUNT_SCRIPT FAKE_OUTPUT = b""" The stuff I would expect to be returned by log lines in my osascript script. """ def test_apple_notes_to_sqlite_dump(fp): fp.register_subprocess(["osascript", "-e", COUNT_SCRIPT], stdout=b"2") fp.register_subprocess(["osascript", "-e", fp.any()], stdout=FAKE_OUTPUT) runner = CliRunner() with runner.isolated_filesystem(): result = runner.invoke(cli, ["--dump"]) # ...
fp is the fixture provided by the package (you need to
pip install pytest-subprocess for this to work).
COUNT_SCRIPT here is the first of my
osascript constants. It looks like this (in
COUNT_SCRIPT = """ tell application "Notes" set noteCount to count of notes end tell log noteCount """
That first fixture line says that any time my program calls
osascript -e that-count-script the return value sent to standard output should be a binary string
fp.register_subprocess(["osascript", "-e", COUNT_SCRIPT], stdout=b"2")
The second call to
subprocess made by my script is more complicated - it involves a script that is dynamically generated.
fp.register_subprocess(["osascript", "-e", fp.any()], stdout=FAKE_OUTPUT)
I eventually figured that using
fp.any() was easier than specifying the exact script. This is a wildcard value which matches any string. It returns the full
FAKE_OUTPUT variable as the simulated standard out.
What's useful about
pytest-subprocess is that it works for both
subprocess.check_output() and more complex
subprocess.Popen() calls - both of which I was using in this script.
Created 2023-03-08T21:36:34-08:00 · Edit