Commit db285cab by Ben Patterson

Paver: Ability to run only servers or only tests

This would allow a user to set up and run servers, with an open prompt for killing
them. Likewise a user could open a different terminal session and run tests only.

How-to:
* At a terminal/ssh session, start bok-choy servers with
    `paver test_bokchoy --serversonly`
    (or, if you've already run collectstatic on your system:
    `paver test_bokchoy --serversonly --fasttest`)
* When the above is running, you can now open a separate terminal/ssh session
and run:
    `paver test_bokchoy -t my_tests --testsonly`

Keep in mind, the 'testsonly' flag does no setup. There is some minimal teardown; however,
such as clearing mongo and flushing the lms database. (Some tests have non-unique identifiers
and could not be run more than once.)
parent 7d9ac7da
...@@ -22,6 +22,8 @@ __test__ = False # do not collect ...@@ -22,6 +22,8 @@ __test__ = False # do not collect
@cmdopts([ @cmdopts([
('test_spec=', 't', 'Specific test to run'), ('test_spec=', 't', 'Specific test to run'),
('fasttest', 'a', 'Skip some setup'), ('fasttest', 'a', 'Skip some setup'),
('serversonly', 'r', 'Prepare suite and leave servers running'),
('testsonly', 'o', 'Assume servers are running and execute tests only'),
('extra_args=', 'e', 'adds as extra args to the test command'), ('extra_args=', 'e', 'adds as extra args to the test command'),
('default_store=', 's', 'Default modulestore'), ('default_store=', 's', 'Default modulestore'),
make_option("--verbose", action="store_const", const=2, dest="verbosity"), make_option("--verbose", action="store_const", const=2, dest="verbosity"),
...@@ -33,7 +35,10 @@ __test__ = False # do not collect ...@@ -33,7 +35,10 @@ __test__ = False # do not collect
def test_bokchoy(options): def test_bokchoy(options):
""" """
Run acceptance tests that use the bok-choy framework. Run acceptance tests that use the bok-choy framework.
Skips some setup if `fasttest` is True. Skips some static asset steps if `fasttest` is True.
Using 'serversonly' will prepare and run servers, leaving a process running in the terminal. At
the same time, a user can open a separate terminal and use 'testsonly' for executing tests against
those running servers.
`test_spec` is a nose-style test specifier relative to the test directory `test_spec` is a nose-style test specifier relative to the test directory
Examples: Examples:
...@@ -53,6 +58,8 @@ def test_bokchoy(options): ...@@ -53,6 +58,8 @@ def test_bokchoy(options):
opts = { opts = {
'test_spec': getattr(options, 'test_spec', None), 'test_spec': getattr(options, 'test_spec', None),
'fasttest': getattr(options, 'fasttest', False), 'fasttest': getattr(options, 'fasttest', False),
'serversonly': getattr(options, 'serversonly', False),
'testsonly': getattr(options, 'testsonly', False),
'default_store': getattr(options, 'default_store', 'split'), 'default_store': getattr(options, 'default_store', 'split'),
'verbosity': getattr(options, 'verbosity', 2), 'verbosity': getattr(options, 'verbosity', 2),
'extra_args': getattr(options, 'extra_args', ''), 'extra_args': getattr(options, 'extra_args', ''),
......
...@@ -55,3 +55,7 @@ class TestPaverBokChoyCmd(unittest.TestCase): ...@@ -55,3 +55,7 @@ class TestPaverBokChoyCmd(unittest.TestCase):
self.request.test_spec = "test_foo.py" self.request.test_spec = "test_foo.py"
self.request.default_store = "invalid" self.request.default_store = "invalid"
self.assertEqual(self.request.cmd.strip(), self._expected_command(self.request.test_spec, "invalid")) self.assertEqual(self.request.cmd.strip(), self._expected_command(self.request.test_spec, "invalid"))
def test_serversonly(self):
self.request.serversonly = True
self.assertEqual(self.request.cmd.strip(), "")
""" """
Class used for defining and running Bok Choy acceptance test suite Class used for defining and running Bok Choy acceptance test suite
""" """
from time import sleep
from paver.easy import sh from paver.easy import sh
from pavelib.utils.test.suites import TestSuite from pavelib.utils.test.suites import TestSuite
from pavelib.utils.envs import Env from pavelib.utils.envs import Env
...@@ -23,7 +25,9 @@ class BokChoyTestSuite(TestSuite): ...@@ -23,7 +25,9 @@ class BokChoyTestSuite(TestSuite):
log_dir - directory for test output log_dir - directory for test output
report_dir - directory for reports (e.g., coverage) related to test execution report_dir - directory for reports (e.g., coverage) related to test execution
xunit_report - directory for xunit-style output (xml) xunit_report - directory for xunit-style output (xml)
fasttest - when set, skip various set-up tasks (e.g., DB migrations) fasttest - when set, skip various set-up tasks (e.g., collectstatic)
serversonly - prepare and run the necessary servers, only stopping when interrupted with Ctrl-C
testsonly - assume servers are running (as per above) and run tests with no setup or cleaning of environment
test_spec - when set, specifies test files, classes, cases, etc. See platform doc. test_spec - when set, specifies test files, classes, cases, etc. See platform doc.
default_store - modulestore to use when running tests (split or draft) default_store - modulestore to use when running tests (split or draft)
""" """
...@@ -35,6 +39,8 @@ class BokChoyTestSuite(TestSuite): ...@@ -35,6 +39,8 @@ class BokChoyTestSuite(TestSuite):
self.xunit_report = self.report_dir / "xunit.xml" self.xunit_report = self.report_dir / "xunit.xml"
self.cache = Env.BOK_CHOY_CACHE self.cache = Env.BOK_CHOY_CACHE
self.fasttest = kwargs.get('fasttest', False) self.fasttest = kwargs.get('fasttest', False)
self.serversonly = kwargs.get('serversonly', False)
self.testsonly = kwargs.get('testsonly', False)
self.test_spec = kwargs.get('test_spec', None) self.test_spec = kwargs.get('test_spec', None)
self.default_store = kwargs.get('default_store', None) self.default_store = kwargs.get('default_store', None)
self.verbosity = kwargs.get('verbosity', 2) self.verbosity = kwargs.get('verbosity', 2)
...@@ -55,9 +61,32 @@ class BokChoyTestSuite(TestSuite): ...@@ -55,9 +61,32 @@ class BokChoyTestSuite(TestSuite):
test_utils.clean_test_files() test_utils.clean_test_files()
msg = colorize('green', "Checking for mongo, memchache, and mysql...") msg = colorize('green', "Checking for mongo, memchache, and mysql...")
print(msg) print msg
bokchoy_utils.check_services() bokchoy_utils.check_services()
if not self.testsonly:
self.prepare_bokchoy_run()
msg = colorize('green', "Confirming servers have started...")
print msg
bokchoy_utils.wait_for_test_servers()
if self.serversonly:
self.run_servers_continuously()
def __exit__(self, exc_type, exc_value, traceback):
super(BokChoyTestSuite, self).__exit__(exc_type, exc_value, traceback)
msg = colorize('green', "Cleaning up databases...")
print msg
# Clean up data we created in the databases
sh("./manage.py lms --settings bok_choy flush --traceback --noinput")
bokchoy_utils.clear_mongo()
def prepare_bokchoy_run(self):
"""
Sets up and starts servers for bok-choy run. This includes any stubbed servers.
"""
sh("{}/scripts/reset-test-db.sh".format(Env.REPO_ROOT)) sh("{}/scripts/reset-test-db.sh".format(Env.REPO_ROOT))
if not self.fasttest: if not self.fasttest:
...@@ -90,32 +119,41 @@ class BokChoyTestSuite(TestSuite): ...@@ -90,32 +119,41 @@ class BokChoyTestSuite(TestSuite):
) )
# Ensure the test servers are available # Ensure the test servers are available
msg = colorize('green', "Starting test servers...") msg = colorize('green', "Confirming servers are running...")
print(msg) print msg
bokchoy_utils.start_servers(self.default_store) bokchoy_utils.start_servers(self.default_store)
msg = colorize('green', "Waiting for servers to start...") def run_servers_continuously(self):
print(msg) """
bokchoy_utils.wait_for_test_servers() Infinite loop. Servers will continue to run in the current session unless interrupted.
"""
def __exit__(self, exc_type, exc_value, traceback): print 'Bok-choy servers running. Press Ctrl-C to exit...\n'
super(BokChoyTestSuite, self).__exit__(exc_type, exc_value, traceback) print 'Note: pressing Ctrl-C multiple times can corrupt noseid files and system state. Just press it once.\n'
msg = colorize('green', "Cleaning up databases...") while True:
print(msg) try:
sleep(10000)
# Clean up data we created in the databases except KeyboardInterrupt:
sh("./manage.py lms --settings bok_choy flush --traceback --noinput") print "Stopping bok-choy servers.\n"
bokchoy_utils.clear_mongo() break
@property @property
def cmd(self): def cmd(self):
"""
This method composes the nosetests command to send to the terminal. If nosetests aren't being run,
the command returns an empty string.
"""
# Default to running all tests if no specific test is specified # Default to running all tests if no specific test is specified
if not self.test_spec: if not self.test_spec:
test_spec = self.test_dir test_spec = self.test_dir
else: else:
test_spec = self.test_dir / self.test_spec test_spec = self.test_dir / self.test_spec
# Skip any additional commands (such as nosetests) if running in
# servers only mode
if self.serversonly:
return ""
# Construct the nosetests command, specifying where to save # Construct the nosetests command, specifying where to save
# screenshots and XUnit XML reports # screenshots and XUnit XML reports
cmd = [ cmd = [
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment