From af9ae6753b7b3fd09966650cefcdbc3c60dac872 Mon Sep 17 00:00:00 2001 From: Christine Lytwynec Date: Wed, 18 Jun 2014 16:41:48 -0400 Subject: [PATCH] Deprecating acceptance_tests from rake to paver --- pavelib/__init__.py | 2 +- pavelib/acceptance_test.py | 47 +++++++ pavelib/utils/test/suites/__init__.py | 1 + pavelib/utils/test/suites/acceptance_suite.py | 123 ++++++++++++++++++ rakelib/acceptance_test.rake | 99 -------------- rakelib/acceptance_test_deprecated.rake | 28 ++++ 6 files changed, 200 insertions(+), 100 deletions(-) create mode 100644 pavelib/acceptance_test.py create mode 100644 pavelib/utils/test/suites/acceptance_suite.py delete mode 100644 rakelib/acceptance_test.rake create mode 100644 rakelib/acceptance_test_deprecated.rake diff --git a/pavelib/__init__.py b/pavelib/__init__.py index 7441132908..d20f1c0c10 100644 --- a/pavelib/__init__.py +++ b/pavelib/__init__.py @@ -1,4 +1,4 @@ """ paver commands """ -from . import assets, servers, docs, prereqs, quality, tests, js_test, i18n, bok_choy +from . import assets, servers, docs, prereqs, quality, tests, js_test, i18n, bok_choy, acceptance_test diff --git a/pavelib/acceptance_test.py b/pavelib/acceptance_test.py new file mode 100644 index 0000000000..b1a69ae552 --- /dev/null +++ b/pavelib/acceptance_test.py @@ -0,0 +1,47 @@ +""" +Acceptance test tasks +""" +from paver.easy import task, cmdopts, needs +from pavelib.utils.test.suites import AcceptanceTestSuite +from optparse import make_option + +try: + from pygments.console import colorize +except ImportError: + colorize = lambda color, text: text # pylint: disable-msg=invalid-name + +__test__ = False # do not collect + +@task +@needs( + 'pavelib.prereqs.install_prereqs', + 'pavelib.utils.test.utils.clean_reports_dir', +) +@cmdopts([ + ("system=", "s", "System to act on"), + ("fasttest", "a", "Run without collectstatic"), + ("extra_args=", "e", "adds as extra args to the test command"), + make_option("--verbose", action="store_const", const=2, dest="verbosity"), + make_option("-q", "--quiet", action="store_const", const=0, dest="verbosity"), + make_option("-v", "--verbosity", action="count", dest="verbosity"), +]) +def test_acceptance(options): + """ + Run the acceptance tests for the either lms or cms + """ + opts = { + 'fasttest': getattr(options, 'fasttest', False), + 'system': getattr(options, 'system', None), + 'verbosity': getattr(options, 'verbosity', 3), + 'extra_args': getattr(options, 'extra_args', ''), + } + + if opts['system'] not in ['cms', 'lms']: + msg = colorize( + 'red', + 'No system specified, running tests for both cms and lms.' + ) + print(msg) + + suite = AcceptanceTestSuite('{} acceptance'.format(opts['system']), **opts) + suite.run() diff --git a/pavelib/utils/test/suites/__init__.py b/pavelib/utils/test/suites/__init__.py index 737e7994af..44a57749dc 100644 --- a/pavelib/utils/test/suites/__init__.py +++ b/pavelib/utils/test/suites/__init__.py @@ -5,3 +5,4 @@ from .suite import TestSuite from .nose_suite import NoseTestSuite, SystemTestSuite, LibTestSuite from .python_suite import PythonTestSuite from .js_suite import JsTestSuite +from .acceptance_suite import AcceptanceTestSuite diff --git a/pavelib/utils/test/suites/acceptance_suite.py b/pavelib/utils/test/suites/acceptance_suite.py new file mode 100644 index 0000000000..d59552e75f --- /dev/null +++ b/pavelib/utils/test/suites/acceptance_suite.py @@ -0,0 +1,123 @@ +""" +Acceptance test suite +""" +from paver.easy import sh, call_task +from pavelib.utils.test import utils as test_utils +from pavelib.utils.test.suites import TestSuite +from pavelib.utils.envs import Env + +__test__ = False # do not collect + + +class AcceptanceTest(TestSuite): + """ + A class for running lettuce acceptance tests. + """ + def __init__(self, *args, **kwargs): + super(AcceptanceTest, self).__init__(*args, **kwargs) + self.report_dir = Env.REPORT_DIR / 'acceptance' + self.fasttest = kwargs.get('fasttest', False) + self.system = kwargs.get('system', None) + self.extra_args = kwargs.get('extra_args', '') + + def __enter__(self): + super(AcceptanceTest, self).__enter__() + self.report_dir.makedirs_p() + self._update_assets() + + def __exit__(self, exc_type, exc_value, traceback): + super(AcceptanceTest, self).__exit__(exc_type, exc_value, traceback) + test_utils.clean_mongo() + + @property + def cmd(self): + + report_file = self.report_dir / "{}.xml".format(self.system) + report_args = "--with-xunit --xunit-file {}".format(report_file) + + cmd = ( + "./manage.py {system} --settings acceptance harvest --traceback " + "--debug-mode --verbosity {verbosity} {report_args} {extra_args}".format( + system=self.system, + verbosity=self.verbosity, + report_args=report_args, + extra_args=self.extra_args, + ) + ) + + return cmd + + def _update_assets(self): + args = [self.system, '--settings=acceptance'] + + if self.fasttest: + args.append('--skip-collect') + + call_task('pavelib.assets.update_assets', args=args) + + +class AcceptanceTestSuite(TestSuite): + """ + A class for running lettuce acceptance tests. + """ + def __init__(self, *args, **kwargs): + super(AcceptanceTestSuite, self).__init__(*args, **kwargs) + self.root = 'acceptance' + self.db = Env.REPO_ROOT / 'test_root/db/test_edx.db' + self.db_cache = Env.REPO_ROOT / 'common/test/db_cache/lettuce.db' + self.system = kwargs.get('system', None) + self.fasttest = kwargs.get('fasttest', False) + + if self.system: + self.subsuites = [ + AcceptanceTest('{} acceptance'.format(self.system), **kwargs), + ] + else: + kwargs['system'] = 'lms' + lms = AcceptanceTest('lms acceptance', **kwargs) + kwargs['system'] = 'cms' + cms = AcceptanceTest('cms acceptance', **kwargs) + self.subsuites = [lms, cms] + + def __enter__(self): + super(AcceptanceTestSuite, self).__enter__() + test_utils.clean_test_files() + + if not self.fasttest: + self._setup_acceptance_db() + + + def _setup_acceptance_db(self): + """ + TODO: Improve the following + + Since the CMS depends on the existence of some database tables + that are now in common but used to be in LMS (Role/Permissions for Forums) + we need to create/migrate the database tables defined in the LMS. + We might be able to address this by moving out the migrations from + lms/django_comment_client, but then we'd have to repair all the existing + migrations from the upgrade tables in the DB. + But for now for either system (lms or cms), use the lms + definitions to sync and migrate. + """ + + if self.db.isfile(): + # Since we are using SQLLite, we can reset the database by deleting it on disk. + self.db.remove() + + if self.db_cache.isfile(): + # To speed up migrations, we check for a cached database file and start from that. + # The cached database file should be checked into the repo + + # Copy the cached database to the test root directory + sh("cp {db_cache} {db}".format(db_cache=self.db_cache, db=self.db)) + + # Run migrations to update the db, starting from its cached state + sh("./manage.py lms --settings acceptance migrate --traceback --noinput") + else: + # If no cached database exists, syncdb before migrating, then create the cache + sh("./manage.py lms --settings acceptance syncdb --traceback --noinput") + sh("./manage.py lms --settings acceptance migrate --traceback --noinput") + + # Create the cache if it doesn't already exist + sh("cp {db} {db_cache}".format(db_cache=self.db_cache, db=self.db)) diff --git a/rakelib/acceptance_test.rake b/rakelib/acceptance_test.rake deleted file mode 100644 index 290fdac01f..0000000000 --- a/rakelib/acceptance_test.rake +++ /dev/null @@ -1,99 +0,0 @@ -ACCEPTANCE_DB = File.join(REPO_ROOT, 'test_root/db/test_edx.db') -ACCEPTANCE_DB_CACHE = File.join(REPO_ROOT, 'common/test/db_cache/lettuce.db') -ACCEPTANCE_REPORT_DIR = report_dir_path('acceptance') -directory ACCEPTANCE_REPORT_DIR - -def run_acceptance_tests(system, harvest_args) - # Create the acceptance report directory - # because if it doesn't exist then lettuce will give an IOError. - report_dir = report_dir_path('acceptance') - - report_file = File.join(ACCEPTANCE_REPORT_DIR, "#{system}.xml") - report_args = "--with-xunit --xunit-file #{report_file}" - cmd = django_admin( - system, 'acceptance', 'harvest', '--debug-mode', - '--verbosity 2', report_args, harvest_args - ) - test_sh("#{system} acceptance tests", cmd) -end - -task :setup_acceptance_db do - # HACK: Since the CMS depends on the existence of some database tables - # that are now in common but used to be in LMS (Role/Permissions for Forums) - # we need to create/migrate the database tables defined in the LMS. - # We might be able to address this by moving out the migrations from - # lms/django_comment_client, but then we'd have to repair all the existing - # migrations from the upgrade tables in the DB. - # But for now for either system (lms or cms), use the lms - # definitions to sync and migrate. - - # Since we are using SQLLite, we can reset the database by deleting it on disk. - if File.exists?(ACCEPTANCE_DB) - File.delete(ACCEPTANCE_DB) - end - - # To speed up migrations, we check for a cached database file and start from that. - # The cached database file should be checked into the repo - if File.exists?(ACCEPTANCE_DB_CACHE) - - # Copy the cached database to the test root directory - sh("cp #{ACCEPTANCE_DB_CACHE} #{ACCEPTANCE_DB}") - - # Run migrations to update the db, starting from its cached state - sh(django_admin('lms', 'acceptance', 'migrate', '--noinput')) - - # If no cached database exists, syncdb before migrating, then create the cache - else - sh(django_admin('lms', 'acceptance', 'syncdb', '--noinput')) - sh(django_admin('lms', 'acceptance', 'migrate', '--noinput')) - - # Create the cache if it doesn't already exist - sh("cp #{ACCEPTANCE_DB} #{ACCEPTANCE_DB_CACHE}") - end - -end - -task :prep_for_acceptance_tests => [ - :clean_reports_dir, :clean_test_files, ACCEPTANCE_REPORT_DIR, - :install_prereqs, :setup_acceptance_db -] - -namespace :test do - namespace :acceptance do - task :all, [:harvest_args] => [ - :prep_for_acceptance_tests, - "^^lms:gather_assets:acceptance", - "^^cms:gather_assets:acceptance" - ] do |t, args| - run_acceptance_tests('lms', args.harvest_args) - run_acceptance_tests('cms', args.harvest_args) - end - - ['lms', 'cms'].each do |system| - desc "Run the acceptance tests for the #{system}" - task system, [:harvest_args] => [ - :prep_for_acceptance_tests, - "^^#{system}:gather_assets:acceptance" - ] do |t, args| - args.with_defaults(:harvest_args => '') - run_acceptance_tests(system, args.harvest_args) - end - - desc "Run acceptance tests for the #{system} without collectstatic or db migrations" - task "#{system}:fast", [:harvest_args] => [:clean_reports_dir, ACCEPTANCE_REPORT_DIR] do |t, args| - args.with_defaults(:harvest_args => '') - - begin - run_acceptance_tests(system, args.harvest_args) - ensure - Rake::Task[:'test:clean_mongo'].reenable - Rake::Task[:'test:clean_mongo'].invoke - end - end - end - end - desc "Run the lettuce acceptance tests for lms and cms" - task :acceptance, [:harvest_args] do |t, args| - Rake::Task["test:acceptance:all"].invoke(args.harvest_args) - end -end diff --git a/rakelib/acceptance_test_deprecated.rake b/rakelib/acceptance_test_deprecated.rake new file mode 100644 index 0000000000..2b4251fb45 --- /dev/null +++ b/rakelib/acceptance_test_deprecated.rake @@ -0,0 +1,28 @@ +# acceptance test tasks deprecated to paver + +require 'colorize' + +def deprecated(deprecated, deprecated_by, *args) + + task deprecated, [:harvest_args] do |t,args| + + # Need to install paver dependencies for the commands to work! + sh("pip install -r requirements/edx/paver.txt") + + args.with_defaults(:harvest_args => nil) + new_cmd = deprecated_by + + if !args.harvest_args.nil? + new_cmd = "#{new_cmd} --extra_args='#{args.harvest_args}'" + end + + puts("Task #{deprecated} has been deprecated. Use #{new_cmd} instead.".red) + sh(new_cmd) + end +end + +deprecated("test:acceptance", "paver test_acceptance") +deprecated("test:acceptance:cms", "paver test_acceptance -s cms") +deprecated("test:acceptance:cms:fast", "paver test_acceptance -s cms --fasttest") +deprecated("test:acceptance:lms", "paver test_acceptance -s lms") +deprecated("test:acceptance:lms:fast", "paver test_acceptance -s lms --fasttest")