New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
run: add optional exit-status test #367
run: add optional exit-status test #367
Conversation
0959e57
to
6622070
Compare
Sincere apologies for the churn; I was obviously not as well prepared as I thought I was. CI is now green. I would appreciate any feedback, whether big-picture or details. FWIW we've been using a (narrower-focused) variant of this code on our containers projects, and the enhanced logging makes it soooo much easier to track down bugs, often with just a glance at the BATS results. |
This looks very interesting! I have yet to review it in more details, for now what I see is
|
re: nonconflicting re: expect - does anyone still use it? I used it heavily in the 80s and 90s, but haven't heard it mentioned even once in any of my programming communities in over ten years. Even if it's still in use (and I hope it is, because it's such a neat tool), is there likely to be any overlap of tcl-expect being used inside a BATS script? re: whole-string matches - my bad, I should've spent more time documenting it. Yes, it should be possible to use any operator, including the nonexistent Thank you for your feedback! Coming up with good names is difficult for me, but I promise to give it a lot of thought over the next day or two. |
I think most of the supported use cases in this PR are already implemented. As far as I see, there are three main features:
We already know when not to use run and have bats-assert which gives us:
The advantages with the approach in this PR seem to be:
Did I miss something? Only the 3rd point seems to be lacking right now. |
@martin-schulze-vireso thank you, I was not acquainted with bats-assert. I'll be taking a close look at it soon. |
Some more thoughts on After reading and fixing lots of bats code using
as in all the other cases not using run will result in a simpler/better code. I won't duplicate the examples here, please see https://github.com/kolyshkin/bats-core/blob/patch-2/README.md#run-test-other-commands (make sure to also scroll down to "when not to use run"). Now, if users follow this advice, the result is OK, but it's not uniform. In some cases Here is a not-so-good example when run is used everywhere (I've seen lots of such code recently): @test foo {
run cmd start something ...
[ "$status" -eq 0 ]
id="$output"
run cmd exec "$id" something ...
echo "cmd exec something: $output"
[ "$status" -eq 0 ]
[[ "$output" == *"success"* ]]
run cmd exec "$id"_bad something ...
[ "$status" -ne 0 ]
[[ "$output" == *"invalid id"* ]]
run cmd exec "$id" false
[ "$status" -ne 0 ] The problem is, it is too verbose. To fix this, it can be rewritten to @test foo {
id=$(cmd start something ...)
output=$(cmd exec "$id" something ...)
echo "cmd exec something: $output"
[[ "$output" == *"success"* ]]
run cmd exec "$id"_bad something ...
[ "$status" -ne 0 ]
[[ "$output" == *"invalid id"* ]]
! cmd exec "$id" false This is better, but have the following issues:
The new proposed @test foo {
erun cmd start something ... # implicit zero status check
id="$output"
erun cmd exec "$id" something ... # implicit logging, too!
[[ "$output" == *"success"* ]]
erun '!' cmd exec "$id"_bad something ...
[[ "$output" == *"invalid id"* ]]
erun '!' cmd exec "$id" false Now this is both uniform and compact (note I'm using '!' to signify I want to check that cmd exited with non-zero), plus errors are (presumably) reported better. Finally, if we add the proposed expect to the list, we can improve error reporting for mismatched output. Hope that all make sense. |
Okay, this is what I did not notice above and it all makes sense now. I think we should separate the discussion into two parts: The output checking and the return code checks. bats-assert offers solutions for both, which rely on I think the output checking will always require an additional command, or the *run statement would become very convoluted. Therefore, the current bats-assert solution is close to optimal in this regard. However, the return code checks are more interesting for this PR. I think the proposed solution of an exit code checked run command that offers the same output parsing interface to be compatible with existing assert_output solutions would enhance readability a lot. It would suffice to allow for exit code =0, !=0 (and maybe =X) to solve 99% of cases and the rest should be dealt with via explicit checking of To stay with the naming above, I would propose the following terse syntax:
|
Thank you both for the suggestions and encouragement. I haven't played with bats-assert yet because of installation and come-up-to-speed-itis, but I did take a few moments to adopt your ideas. In particular:
|
a6acf1e
to
155b1ec
Compare
While working on #368 I noticed that the current debug trap tracing can be problematic with the run function. This might hit you as well, so quick heads up: please add a test that verifies the correct error location being reported for your new run function. |
Yikes. Thank you; seems like my best course is to wait for #368 to merge, then rebase on it. |
155b1ec
to
880da53
Compare
I've pushed one more commit; this time converging on And, I had a chance to use
I also like the vertical layout:
In the world I code in, too often I have to hand-edit an error log to put expected vs actual on top of each other, to see the actual differences. |
I did not look into it that deep but I see two ways this can play out: Either your code already works as intended, or rebasing won't be enough. I had to do special case handling with aborting during
I think you should look into assert_equal for a fair comparison. I can highly recommend the readme at https://github.com/bats-core/bats-assert to see a list of all supported tests. Regarding the naming: When we are okay with using the first parameter to indicate return code checks, we could simply upgrade the |
7ebb6ec
to
8102a0f
Compare
I've addressed the wrong-line-number issue, although I'm not sure I've done so in the best possible way. I've left it as a separate commit for ease of review.
That would prevent the usage I most like: |
Well, I don't know either but I added a rationale to the other issue (#377 (comment)). However, I agree that return code checks should be default. In a sense we already have this situation by having "normal" commands (without
I was a bit unclear. I think we should have something like:
The advantage over a separate function is the unified control flow, which reduces special case handling. I'd also like @kolyshkin and @sublimino to weigh in on this. Apart from that: Did you look into the asserts library? (Especially |
Nice. I like the This has grown somewhat beyond the scope of my original submission, so I've prepared a separate local branch with just the changes to |
@edsantiago check out #467. I think that will be a useful feature for you. |
e548553
to
a25cd7b
Compare
I rebased onto current master and resolved the conflicts. I also restructured the test code and removed the tracing parts that might go into #467 and |
a25cd7b
to
9670499
Compare
One thing that is still missing is the printing of $output. I removed that because it is intended for the trace feature. However, I find the usecase of printing the output on error quite compelling. So when we don't check the exit code, run should behave as before and remain silent. When we do exit code checking and the check fails, I'd propose to print output. |
@edsantiago Do you mind reviewing if I broke some of your intentions? @bats-core/bats-core I'd also like the other maintainers' opinions on this. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@martin-schulze-vireso thank you for taking this on again. Looks good at first pass, but by now this is different enough from my original PR that I'm OK with you closing and resubmitting as yours.
@edsantiago I am okay with sharing the fame for your ground work if you are okay with sharing the |
If `run` is invoked with '=N' or '!' as its first argument, it will check the exit code of the invoked command and fail if it does not match the requirement (exact N for =N, or any nonzero for '!').
d3df2eb
to
066d271
Compare
Bats 1.7.0 emits a warning if a command passed to 'run' returns with an exit code of 127 [1]. This requires Bats >= 1.5.0, which is present in Fedora >=35, and supports specifying the exit code as an argument to Bats' 'run' command [2]. However, bats_require_minimum_version can't be used, because it's only available from Bats 1.7.0, which is new enough that it's absent in Fedora 35. [1] Bats commit c6dc2f88361a4f5b bats-core/bats-core#547 https://bats-core.readthedocs.io/en/stable/warnings/BW01.html [2] bats-core/bats-core#367 bats-core/bats-core#507 https://bats-core.readthedocs.io/en/stable/writing-tests.html [3] Bats commit 71d6b71cebc3d32b bats-core/bats-core#556 https://bats-core.readthedocs.io/en/stable/warnings/BW02.html containers#1081
Bats 1.7.0 emits a warning if a command passed to 'run' returns with an exit code of 127 [1]: BW01: `run`'s command `/opt/bin/toolbox run non-existent-command` exited with code 127, indicating 'Command not found'. Use run's return code checks, e.g. `run -127`, to fix this message. (from function `run' in file /usr/lib/bats-core/test_functions.bash, line 299, in test file test/system/104-run.bats, line 148) This requires Bats >= 1.5.0, which is present in Fedora >=35, and supports specifying the exit code as an argument to Bats' 'run' command [2]. However, bats_require_minimum_version can't be used, because it's only available from Bats 1.7.0, which is new enough that it's absent from Fedora 35. [1] Bats commit c6dc2f88361a4f5b bats-core/bats-core#547 https://bats-core.readthedocs.io/en/stable/warnings/BW01.html [2] bats-core/bats-core#367 bats-core/bats-core#507 https://bats-core.readthedocs.io/en/stable/writing-tests.html [3] Bats commit 71d6b71cebc3d32b bats-core/bats-core#556 https://bats-core.readthedocs.io/en/stable/warnings/BW02.html containers#1081
Bats 1.7.0 emits a warning if a command passed to 'run' returns with an exit code of 127 [1]: BW01: `run`'s command `/opt/bin/toolbox run non-existent-command` exited with code 127, indicating 'Command not found'. Use run's return code checks, e.g. `run -127`, to fix this message. (from function `run' in file /usr/lib/bats-core/test_functions.bash, line 299, in test file test/system/104-run.bats, line 148) This requires Bats >= 1.5.0, which is present in Fedora >=35, and supports specifying the exit code as an argument to Bats' 'run' command [2]. However, bats_require_minimum_version can't be used, because it's only available from Bats 1.7.0, which is new enough that it's absent from Fedora 35. [1] Bats commit c6dc2f88361a4f5b bats-core/bats-core#547 https://bats-core.readthedocs.io/en/stable/warnings/BW01.html [2] bats-core/bats-core#367 bats-core/bats-core#507 https://bats-core.readthedocs.io/en/stable/writing-tests.html [3] Bats commit 71d6b71cebc3d32b bats-core/bats-core#556 https://bats-core.readthedocs.io/en/stable/warnings/BW02.html containers#1081
If
run
is invoked with '=N' or '!' as itsfirst argument, it will check the exit code
of the invoked command and fail if it does
not match the requirement (exact N for =N,
or any nonzero for '!').
Additionally,
run
now logs each command invokedas well as its entire output. This will be invisible
when tests pass, but will be shown on test failure
and may offer crucial context for someone analyzing
a failed run.
Signed-off-by: Ed Santiago santiago@redhat.com