4

I'm writing python unit tests that test against a REST API that needs to be running as another process.

The REST server is a tomcat application that I call from the shell to run in development mode, so what I am looking to do in the python test is:

  1. Start the server, return when the server is up.
  2. Run unit tests
  3. Send the server Ctrl+D so it shuts down gracefully.

Is there a way to use a single point of entry for python so that the server starts and unit tests run all from one python script call?

I've look around at python subprocess and multithreading in python, but I still don't quite see how to get there from here.

For those that are familiar, this is an Atlassian JIRA plugin we are developing, so the actual shell command is "atlas-run".

serv-inc
  • 35,772
  • 9
  • 166
  • 188
MStudley
  • 685
  • 1
  • 5
  • 7
  • 1
    1.) How is the server called from the commandline? Can you use the `pexpect` module? 2.) Once the server is up, just run the `unittest.main()`. 3.) Can you use the `signal` module to catch `SIGQUIT` and `pexpect` it to the server? – wflynny Nov 20 '14 at 21:14
  • I was not aware of pexpect, I'm looking into that now, thanks for that! The server is called by CDing to the root directory of the plugin project and running "atlas-run" from the command line. – MStudley Nov 21 '14 at 18:44

1 Answers1

3

Since no one has offered any code to help with this problem, I would do something like the following. Turns out pexpect is very powerful and you don't need the signal module.

import os
import sys
import pexpect

def run_server():
    server_dir = '/path/to/server/root'
    current_dir = os.path.abspath(os.curdir)

    os.chdir(server_dir)
    server_call = pexpect.spawn('atlas-run')
    server_response = server_call.expect(['Server Error!', 'Sever is running!'])
    os.chdir(current_dir)
    if server_response:
        return server_call #return server spawn object so we can shutdown later
    else:
        print 'Error starting the server: %s'%server_response.after
        sys.exit(1)

def run_unittests():
    # several ways to do this. either make a unittest.TestSuite or run command line
    # here is the second option
    unittest_dir = '/path/to/tests'
    pexpect.spawn('python -m unittest discover -s %s -p "*test.py"'%unittest_dir)
    test_response = pexpect.expect('Ran [0-9]+ tests in [0-9\.]+s') #catch end
    print test_response.before #print output of unittests before ending.
    return

def main():
    server = run_sever()
    run_unittests()
    server.sendcontrol('d') #shutdown server

if __name__ == "__main__":
    main()
wflynny
  • 18,065
  • 5
  • 46
  • 67
  • 1
    This works! I am going the TestSuite route instead of running the unit tests in another process, but still - awesome answer. Thanks! – MStudley Nov 21 '14 at 22:57