1

TL;DR: How do I get a pytest plugin to redirect the running tests to a spawned process (inside a different environment/python interpreter)?


I'm developing a python script that is run by a python interpreter embedded inside a third party application (Namely, IDA). I'm now in the process of creating tests for my script using pytest, using a pytest plugin I wrote for the application. Because the application makes certain modules available only within it's own interpreter any tests must be running in a python interpreter inside the application.

I would like to improve my pytest plugin by allowing it to execute the pytest session inside the third party application, instead inside a vanilla interpreter.

I know how to cause my tests and pytest to run inside the application, which will be something similar to this:

subprocess.call("C:\Program Files\IDA\idaq.exe" -S <My script>", shell=True)

I'm struggling with where (a pytest hook, I assume, but which one?) should I spawn the pytest session inside? How can I make sure that test arguments are passed along to the new process?

I assume this is possible as a pytest plugin, because it somewhat resembles the xdist plugin.

NirIzr
  • 3,131
  • 2
  • 30
  • 49
  • 1
    Not sure if this helps [link](http://stackoverflow.com/questions/25188119/test-if-code-is-executed-from-within-a-py-test-session) – Macintosh_89 Aug 24 '16 at 13:49
  • Thanks, this might help a bit although I can quite easily find out if my code is running from inside the application. – NirIzr Aug 24 '16 at 13:54

1 Answers1

2

I will not answer this too in-depth, unless someone comes by and shows interest, because it'll be kinda long

I've managed to do this by an approach similar to how pytest-xdist does it's distributed execution, where instead of using execnet to execute python interpreters remotely, I'm using subprocess.Popen to spawn an instance of the third party application (pointing to a python script for it to execute). I'm using multiprocessing.Listener and multiprocessing.Client to create a communication channel that can serialize (basic) python objects.

I then, like xdist, created an additional pytest plugin that is being registered by the script the application loads. That pytest plugin registers a handful of hooks using pytest's available hooking facilities that are then communicated back to the original pytest instance, which will fire them again to simulate them being fired by pytest itself.

For anyone interested in an example which I believe is simpler to understand than pytest-xdist, relevant code can be found on my github repo.

NirIzr
  • 3,131
  • 2
  • 30
  • 49