[tests] Add Subprocess TestCase#720
Conversation
- adds support for future patch_test.py - adds support for running tests in new interpreter instance - uses requests, gevent and celery as examples of usage in tox.ini
brettlangdon
left a comment
There was a problem hiding this comment.
what happens if a we run a clean test without this runner?
I assume they will just fail?
Any way we can block them from executing unless our runner is used? Or show a warning or something?
(probably not actually necessary since them failing tells you you did something wrong anyways).
brettlangdon
left a comment
There was a problem hiding this comment.
We might be able to just create a subclass of unittest.TestCase
It might require a little finesse to get correct though.
class DDTestCase(unittest.TestCase):
def run(self, result=None):
# TODO: Setup stuff
test_method = getattr(self, self._testMethod)
if not is_cleantest(test_method):
return super(self, DDTestCase).run(result=result)
if running_in_subprocess:
# TODO: Maybe we can do `pickle.loads(sys.STDIN)` to get the `result` from the caller?
super(self, DDTestCase).run(result=result)
# TODO: `pickle.dumps(result)`
else:
# TODO: Run subprocess to re-run this specific `test_method`
# TODO: `result = pickle.loads(process.stdout)` (if we do `pickle.loads(stdin)` above, otherwise we get the result and then update our existing `result` with the one from this subprocess)
If we do it this way then we can just do pytest tests/contrib/redis and do not need to change anything up there, and it means we can intermix "clean" tests with non-clean tests just by adding a decorator to the function.
While probably a little more complicated to get correct, this has less moving pieces, less things we need to think about when setting up a test, will be portable between test runners, etc.
(Make sure to not read this as a mandated change, just a different approach that we can have a conversation about).
|
Also, while we are here, not 100% sold on Even if we go for Clarity will usually always out-weight succinctness. |
The clean tests should run normally in whatever runner runs them.
They shouldn't. A downside is, is that we don't have a way to route cleantests to the cleanrunner. We can't ensure that they will be invoked by the cleantest runner.
I'm not sure if we can make the tests aware of the runner they are executed from.
This is an interesting idea. We lose the parallelism but gain compatibility with the other test frameworks, which I like. This approach also means each test case that we want to run clean will have to extend the base class and decorate the method (a slightly implicit constraint).
Agreed. I didn't spend too much time on the naming, and found that coming up with a concise name for this kind of behaviour is tricky. I'm completely open to naming changes as this was just a placeholder. I'm going to explore a more elegant solution to routing tests to a runner which removes the brittleness of needing to specify |
|
All your replies here sound great. Re: parallelism, leave that to the test runner. |
|
@brettlangdon I tried several different approaches with the ideas we discussed. Most failed with the serialization step as tracebacks are not serializable and hence we couldn't send back the required stack trace of the failed test case to the parent process. The approach I've switched to is to let the test run normally and use the return code to indicate success/failure. The appropriate result API methods are then called based accordingly but with an artificial exception raised (since we can't get this info from the child). The test results from the child process are printed to stderr for debugging. This from my limited testing works for pytest, nose and unittest. |
brettlangdon
left a comment
There was a problem hiding this comment.
Some initial questions/thoughts, but looks good, I like it
- use environment variables for subprocess detection - remove comments references to 'parallel' - correct examples - remove hasattr check
brettlangdon
left a comment
There was a problem hiding this comment.
minor nits, otherwise good to go.
brettlangdon
left a comment
There was a problem hiding this comment.
this is awesome. thanks for this work!!!
Overview
This PR introduces a subprocess test case which can be extended to achieve the functionality of running test cases in a new python process.
The test cases can be run in
pytestnoseandunittest.Example
Adding the following test case to the gevent test suite in a file
test_patch.py:Running with pytest:
Running with nosetests (note that the reported number of tests is off, but the dots indicate the tests have run):
Running with unittest: