r-string
Style nit:
cmd = re.sub(
r'\s+', r' ',
"""bin/ ...
Habitually using raw strings for regexes is terrific,
thank you for doing that.
Prefer a simple ' '
for that second argument,
which is just plain text.
(In contrast, prefer to always make regexes r-strings,
even if they do not yet have any special characters
where it would make a difference.
It is a kindness to the reader.)
Consider breaking out a tiny trivial helper which turns
newlines into SPACE, since this is just a source code
formatting typographic detail we're dealing with here.
DRY
It's slightly tedious to see repetitions of
test/fixtures/create_workflow_input
.
Consider assigning it to in_folder
,
and then an f-string can expand several mentions of it.
Also, the print(cmd)
debug is perhaps a bit too chatty.
error paths
It's not completely obvious to me that the try
is a win.
returncode = res.returncode
except ... as e:
returncode = e.returncode
Then later we test whether that code is zero.
Specifying , check=True
is usually exactly what you want,
so nothing will sneak past you.
But here?
Well, you're checking anyway, so maybe don't even specify it,
don't request an exception.
error_msg = str(e)
...
... f'Failed ... error_msg={error_msg}'
No need for the str()
call,
as an f-string will do that anyway.
The else
clause and the assert
message are tightly linked.
If they weren't we would get "NameError: name 'error_msg' is not defined".
This code is too tricky.
If you retain the try
, then do the error reporting
within the else
clause.
It would be better to raise ValueError(...)
or
an app specific error, than to assert
.
I guess this is pytest
showing its influence.
I feel the current assert should "never" trigger,
it is "impossible",
while the one down in test_workflow_input()
is essentially the self.assertEqual()
check of results which might often show a Red test result.
f-string shorthand
Your f'... returncode={returncode}, ...'
could be
more conveniently expressed
with f'... {returncode=}, ...'
In recent interpreter versions, they mean the same thing.
It's just shorthand for a commonly seen pattern.
docstrings
# Run the script to be tested, capture its stdout to a file:
def test_run_create_workflow_input():
...
# Compare observed and expected script output:
def test_workflow_input():
Those aren't really comments which explain some tricky code.
They give the
contract
for each function, so they should be docstrings.
Please """spell them properly""".
use Path
> test/obs/workflow_input.yml""")
...
with open('test/obs/workflow_input.yml') as f:
It's not terrible that we're repeating the filename.
But it does make me slightly sad.
Consider defining a Path which both use,
or consider returning a Path for subsequent use.
with open('test/obs/workflow_input.yml') as f:
obs_lines = f.readlines()
with open('test/fixtures/workflow_input.yml') as f:
exp_lines = f.readlines()
Using a context handler is certainly a Good Thing.
Consider making those .yml names Path
s rather than str
s.
Then you could take advantage of the .read_text()
convenience method offered by Path.