-
Notifications
You must be signed in to change notification settings - Fork 6
Allow parametrization to test descriptions #39
Conversation
83d860b
to
399128c
Compare
@hidmic For a black-box view of how this is going to work, take a look at https://github.com/ApexAI/apex_rostest/blob/399128c6a4cdb2a4c9f07430c0c946ac7025e558/apex_launchtest/examples/parameters.test.py This example runs, but it exits after the 1st parameter because i have no code to combine the results from multiple runs yet. The early-out is here: https://github.com/ApexAI/apex_rostest/pull/39/files#diff-aaece43019a305b833d34efac4246041R220 |
399128c
to
83444bc
Compare
@hidmic I got the parametrized example running today, but I'm seeing some exceptions coming out of launch. I will dig in but thought maybe you might recognize the stack-trace and instantly know what's going on. It doesn't happen every time: > apex_launchtest apex_launchtest/examples/parameters.test.py
. . .
ERROR:asyncio:Task exception was never retrieved
future: <Task finished coro=<LaunchService._process_one_event() done, defined at /opt/ApexOS/lib/python3.5/site-packages/launch/launch_service.p
y:177> exception=ProcessLookupError(3, 'No such process')>
Traceback (most recent call last):
File "/usr/lib/python3.5/asyncio/tasks.py", line 239, in _step
result = coro.send(None)
File "path/lib/python3.5/site-packages/launch/launch_service.py", line 179, in _process_one_event
await self.__process_event(next_event)
File "path/lib/python3.5/site-packages/launch/launch_service.py", line 199, in __process_event
visit_all_entities_and_collect_futures(entity, self.__context))
File "path/lib/python3.5/site-packages/launch/utilities/visit_all_entities_and_collect_futures_impl.py", line 38, in visit_all_entities
_and_collect_futures
sub_entities = entity.visit(context)
File "path/lib/python3.5/site-packages/launch/action.py", line 59, in visit
return cast(Optional[List[LaunchDescriptionEntity]], self.execute(context))
File "path/lib/python3.5/site-packages/launch/actions/opaque_function.py", line 74, in execute
return self.__function(context, *self.__args, **self.__kwargs)
File "path/lib/python3.5/site-packages/launch/actions/execute_process.py", line 269, in __on_signal_process_event
self._subprocess_transport.send_signal(typed_event.signal)
File "/usr/lib/python3.5/asyncio/base_subprocess.py", line 146, in send_signal
self._proc.send_signal(signal)
File "/usr/lib/python3.5/subprocess.py", line 1777, in send_signal
os.kill(self.pid, sig)
ProcessLookupError: [Errno 3] No such process I use a fresh launch service for each run, but I know there's some global state in there - maybe something is preventing us from calling launch.run successfully multiple times per process? One other wrinkle - I think our version of 'launch' is from ROS crystal |
83444bc
to
7e2da27
Compare
@pbaughman that used to happen when a signal was sent after the process had died, due to a race condition in the |
- Add the parametrization infrastrcture - Refactor the apex runner into an ApexRunner and a RunnerWorker - This veresion should still run existing tests. This is mostly a refactor commit Signed-off-by: Pete Baughman <pete.baughman@apex.ai>
78171d6
to
71bb59d
Compare
- Combine pre and post results into one set of results, add class names so the tests are distinguishable - Update tests to match new 'run' API that returns a dictionary of {test_run: result} instead of a tuple of (pre_shutdown, post_shutdown) results
Signed-off-by: Pete Baughman <pete.baughman@apex.ai>
71bb59d
to
d028b62
Compare
@pbaughman I've been pulling this branch, as well as other recent changes in this repository, back into core launch repositories to try this out. It looks like argument and attribute binding for post shutdown tests parameterized on the launch description is broken though. Can you confirm that's the case? Either that or I just messed up with all the cherry-picking and squashing I have been doing. :) |
Signed-off-by: Pete Baughman <pete.baughman@apex.ai>
@hidmic I think it works - I just pushed a commit that adds a post_shutdown_test to examples/parameters.test.py and it seems to run OK. The magic happens here which I'm sure was a conflict-heavy file, unfortunately. The code to bind to the post shutdown tests should be almost identical to the pre-shutdown tests right above. The main difference between the binding above and the binding below is we give proc_info and proc_output objects that don't have the 'assertWaitFor' methods, because it doesn't make sense to wait for IO or process shutdown after all of the processes have shut down. I wanted to give a good error message if someone waited for IO from a post-shutdown test (but I don't think I ever implemented the good error message) |
- Print an extra line that syas "Starting test run . . . " to show which args we're running with - Update the test names the same way pytest does - by appending '[value_of_arg, value_of_arg2, . . ]' - This information makes it into the junit XML too Signed-off-by: Pete Baughman <pete.baughman@apex.ai>
Alright, nevermind, found the problem. Parameterization support works just fine. |
09baebc
to
35d0dc3
Compare
@hidmic Ok, I think I've added everything I want to add to this. If you want to add feedback, this isn't going to change out from under you anymore. I'll also grab someone from Apex to look at it too |
@@ -29,7 +30,10 @@ | |||
def _load_python_file_as_module(python_file_path): | |||
"""Load a given Python launch file (by path) as a Python module.""" | |||
# Taken from apex_core to not introduce a weird dependency thing | |||
loader = SourceFileLoader('python_launch_file', python_file_path) | |||
loader = SourceFileLoader( | |||
os.path.basename(python_file_path), |
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 will give the tests a better name in the resulting XML. The TestRun
class in loader.py
uses the module name to construct the name of the test run. This information eventually makes it into the junit XML file and makes it a little easier to see where tests came from, and what parameters they ran with.
return result | ||
else: | ||
return result, {} | ||
class _LaunchDiedException(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.
The launch can die out from under you because of an error in the launch description, because all of the process accidentally died, or because the user hit ctrl+c. With the ApexRunner split into _RunnerWorker
and ApexRunner
I needed a way to communicate up to the ApexRunner
that this happened.
)(lambda: self._processes_launched.set()) | ||
|
||
# Data to squirrel away for post-shutdown tests | ||
self.proc_info = ActiveProcInfoHandler() |
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.
Since we're doing 100% of the loading and binding before any tests run now, we can reduce the scope of the proc_into and proc_output helper objects.
Previously, we delayed loading the tests until we were ready to run them, but the new TestRun
object over in loader.py
makes it easier to do the loading and binding and parametrization up front
@@ -34,19 +137,6 @@ def loadTestsFromTestCase(self, testCaseClass): | |||
|
|||
if getattr(testCaseClass, '__post_shutdown_test__', False) == load_post_shutdown: | |||
cases = super(_loader, self).loadTestsFromTestCase(testCaseClass) | |||
|
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 is all part of 'bind' on the TestRun object now - up above about 30 lines
Signed-off-by: Pete Baughman <pete.baughman@apex.ai>
35d0dc3
to
f5a9c2f
Compare
@jpsamper2009 or @left4taco Can one of you review this? |
Is this PR still WIP? If not, shall we remove the WIP in the title? |
@left4taco Whoops - fixed sorry |
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.
Good design. I left some of my questions. But those are quite trivial.
Thanks.
@@ -34,19 +137,6 @@ def loadTestsFromTestCase(self, testCaseClass): | |||
|
|||
if getattr(testCaseClass, '__post_shutdown_test__', False) == load_post_shutdown: |
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.
If a test case class has attribute __post_shutdown_test__
, I assume it could only be True
, right? For non-post_shut_down_test, they don't have this attribute at all.
Can we use has_attr
here?
self.test_args[k] = v | ||
test_args[k] = v | ||
|
||
self._test_run.bind( |
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.
Is it possible to change _test_run
to another name? There's already a _run_test_
function below. Might cause confusion.
Also the plural _test_runs
@@ -64,3 +64,13 @@ def startTest(self, test): | |||
def stopTest(self, test): | |||
self.__test_cases[test]['end'] = time.time() | |||
super().stopTest(test) | |||
|
|||
def append(self, results): |
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.
Might not be proper to use TestResult
as the class name as it's the same with unittest.TestResult
Allow the launch to be parametrized, so that one call to apex_launchtest can cause several launches to happen.
Architecture
When we load the module, resolve any parametrization of the
generate_test_description
function. We can load the tests at this point too, instead of waiting until the run starts. The ApexRunner class is now responsible for looping over all of the test runs and combining the results. Running the launch and running the tests is now delegated to a private class called the RunnerWorker.Side Note: Once this is done, it will make Issue 9 a lot easier to complete. We'll just need the loader to produce multiple test runs for the tests that want to run in isolation, creating a new LaunchDescription every time.
Todo
Signed-off-by: Pete Baughman pete.baughman@apex.ai