-
Notifications
You must be signed in to change notification settings - Fork 20
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
Add support for cargo test #39
Add support for cargo test #39
Conversation
Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #39 +/- ##
===========================================
+ Coverage 46.98% 66.02% +19.04%
===========================================
Files 6 6
Lines 166 209 +43
Branches 24 30 +6
===========================================
+ Hits 78 138 +60
+ Misses 74 50 -24
- Partials 14 21 +7 ☔ View full report in Codecov by Sentry. |
Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
@luca-della-vedova would it make sense to switch to https://nexte.st/ ? It'd mean depending on the |
I'm mostly neutral about this, while it would make the integration a lot easier and more feature complete (i.e. no need to write our own xml generation, per test output), it has two main drawbacks I can think of:
Whichever approach we take imho it would just be a stopgap until cargo test can output machine readable format, but that seems to be progressing very slowly |
I agree, not having support for doctests is unfortunate. If we can support plain |
Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
This should now be ready for review. I added unit tests to the sample package so the CI should prove that it works but if you want to try yourself: Install this package (and the matching colcon-ros-cargo if you want to try a ros package)
Then do a I tested it on ros2-rust and rmf_site, for example (current main):
On the other hand, if I edit the formatting to be a bit messed up and a unit test to fail the output becomes:
@esteve I can't seem to ask for review from you but happy to have your input |
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.
I don't think its required to merge this PR, but we really need some documentation in the README for this repo.
It'd be nice to have some kind of translation, this colcon command, translates to this cargo command. Especially now that this isn't a 1:1 (e.x colcon test
translates to cargo build ... & cargo fmt ...
)
if CARGO_EXECUTABLE is None: | ||
# TODO(luca) log this as error in the test result file | ||
raise RuntimeError("Could not find 'cargo' executable") |
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.
nit: Any reason we shouldn't just log this and return early like we do with the RuntimeError directly above?
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.
Fair point, I just left it unchanged to avoid touching up too much. This behavior is also what the build
task does
colcon-cargo/colcon_cargo/task/cargo/build.py
Lines 47 to 69 in 9fdb14f
try: | |
env = await get_command_environment( | |
'build', args.build_base, self.context.dependencies) | |
except RuntimeError as e: | |
logger.error(str(e)) | |
return 1 | |
self.progress('prepare') | |
rc = self._prepare(env, additional_hooks) | |
if rc: | |
return rc | |
# Clean up the build dir | |
build_dir = Path(args.build_base) | |
if args.clean_build: | |
if build_dir.is_symlink(): | |
build_dir.unlink() | |
elif build_dir.exists(): | |
shutil.rmtree(build_dir) | |
# Invoke build step | |
if CARGO_EXECUTABLE is None: | |
raise RuntimeError("Could not find 'cargo' executable") |
cargo test
going to touch on the build
task!What the TODO documents is that I was pondering whether we should create a test-result file for this case or just exit early with an error. I suspect we should still create a test result file hence I noted that down as a TODO.
For reference making it a return code would produce this result:
While currently (RuntimeError
) this is the output:
My recommendation here would be to decide which looks best and do a followup PR that fixes it for both the build and test task. It will be a choice between verbosity (raise exception, get full backtrace) and simplicity (return error code, simple and concise error message). But as a spoiler I do agree with you that the concise error code looks a lot better, most people probably don't want a backtrace of colcon's task spawning
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.
I think raising the runtime error is fine. It's what colcon-cmake
does if cmake
isn't found. Personally I like the distinction between "an error in the test run" which is indicated by the test result output containing error listings and an "an error running the tests" which is indicated by the colcon exception.
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.
Removed the TODO b3ef3cd
nargs='*', metavar='*', type=str.lstrip, | ||
help='Pass arguments to Cargo projects. ' | ||
'Arguments matching other options must be prefixed by a space,\n' | ||
'e.g. --cargo-args " --help"') | ||
|
||
async def test(self, *, additional_hooks=None): # noqa: D102 |
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.
Can we actually add a docstring here? Perhaps just mentioning at a high level the two cargo commands running and why?
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.
I'm not sure what to say about the why we run tests / fmt 😅 but very valid, I added a docstring saying what we run (test and fmt) and what we don't and why we don't (docs) bf3637e
colcon_cargo/task/cargo/test.py
Outdated
logger.error(str(e)) | ||
return 1 | ||
|
||
# Disable color to avoid escape sequences in test result file | ||
env['NO_COLOR'] = '1' |
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.
Does --color never
in the cargo commands not work? Or is this colored output from somewhere else?
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.
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.
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.
Actually I noticed that the output without the NO_COLOR=1
environment argument or, as you mentioned, cargo [cmd] -- color never [args]
is OK. The color itself is present in the output to the console but the stdout itself of the test that is logged to the test-result
file is not colored, so it's actually not harmful (and maybe even a bit helpful?) so I took it out in d2ea503.
testsuite.attrib['errors'] = str(0) | ||
testsuite.attrib['failures'] = str(failures) | ||
testsuite.attrib['skipped'] = str(0) | ||
testsuite.attrib['tests'] = str(2) |
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.
Perhaps I'm misunderstanding, but it seems like we're hard coding the report to always list 2 tests run?
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.
Yes that is the case, all the output from cargo test
is collated into a single result, and the result of cargo fmt --check
is into another result. This is due to it not being possible right now to separate the result of cargo test
by test case (unless we migrate to nextest or try to parse human readable output. It's part of the "what's next" in the PR description (Test granularity)
Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
This reverts commit dc8d9c9. Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
Thanks for all the feedback! For this I added a root level example of Edit: For the translation it's kinda noted under the "What's next" section in Ideally I would like some command line parameter where users can specify what kind of tests they want, i.e. enable / disable format, doc tests, etc. The risk there however, is the good old "bikeshedding" where I feel we might get stuck on details like what to call the CLI parameter, what it should look like etc. For this reason I thought a first implementation of |
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.
I agree that for now its better to have something than to bike shed. The last thing I want is for this PR to stall out over something benign.
This is a good first pass at getting colcon test
functionality for rclrs packages.
LGTM. Thanks for putting this together!
Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
if CARGO_EXECUTABLE is None: | ||
# TODO(luca) log this as error in the test result file | ||
raise RuntimeError("Could not find 'cargo' executable") |
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.
I think raising the runtime error is fine. It's what colcon-cmake
does if cmake
isn't found. Personally I like the distinction between "an error in the test run" which is indicated by the test result output containing error listings and an "an error running the tests" which is indicated by the colcon exception.
Signed-off-by: Luca Della Vedova <lucadv@intrinsic.ai>
It seems a pre-existing problem with The good news is that the fix is fairly straightforward, and I've opened a PR to fix this that targets this branch: luca-della-vedova#2 |
nargs='*', metavar='*', type=str.lstrip, | ||
help='Pass arguments to Cargo projects. ' | ||
'Arguments matching other options must be prefixed by a space,\n' | ||
'e.g. --cargo-args " --help"') | ||
|
||
async def test(self, *, additional_hooks=None): # noqa: D102 |
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.
async def test(self, *, additional_hooks=None): # noqa: D102 | |
async def test(self, *, additional_hooks=None): |
I don't think we need the # noqa: D102
anymore since the docstring has been added.
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.
This looks quite good 👍
I recommend merging in luca-della-vedova#2 before we merge this so that library-only packages work right away, but that could also be left for a follow-up PR.
Since luca-della-vedova#2 is a bit tangential to this PR that hasn't been widely reviewed yet (it's a new feature to allow building pure library targets, that is not currently supported in |
Closes #3
This PR improves support for cargo test by adding test result generation, as well as support for doc tests and
cargo fmt
tests.I made the following choices:
cargo test
andcargo fmt
) into a single test and report whether the whole command succeeded or failed as a single test case. This is different from the "grep approach", but that is imho not a very reliable idea because there is no guarantee that the human readable formatting will stay the same and it might break without any notice. The alternative of using json requires nightly so that is also out of the question (until it is stabilized, at which point we should revisit this implementation).cargo_test.xml
file, similar to what we do for Python packages (pytest.xml
) but different from what we do for C++ packages. Happy to revisit this if there is a strong feeling.What's next:
colcon-ros-cargo
. Add colcon test verb colcon-ros-cargo#19time
to the test result file, I didn't add it first becausecargo test
already reports time but we are not parsing it, and reimplementing a stopwatch in Python feels unnecessary.