[Erp5-report] r28043 - /erp5/trunk/products/ERP5Type/tests/

nobody at svn.erp5.org nobody at svn.erp5.org
Thu Jul 9 14:32:10 CEST 2009


Author: jm
Date: Thu Jul  9 14:32:09 2009
New Revision: 28043

URL: http://svn.erp5.org?rev=28043&view=rev
Log:
Unit tests:
* Slightly change purpose of some options, so that --load and --save can be combined:
  * --load reuses an existing unit test instance.
  * --save runs in persistent mode. Tests are skipped if --load is unset.
* --data_fs_path just allows to specify a Data.fs path other than the default one. Before this commit, the option was used without --load or --save. To get the previous behaviour, it must be used with --load. Note that it is now possible to use it with --save, what overwrites or modifies it.
* if --load is used and MySQL dump is missing, --recreate_catalog is automatically set.
* Drop now useless 'erp5_force_data_fs' environment variable.
* Import Products and static files in the correct order (= same as a normal instance).
* Enable DeadlockDebugger and start ZServer.

Modified:
    erp5/trunk/products/ERP5Type/tests/ERP5TypeTestCase.py
    erp5/trunk/products/ERP5Type/tests/custom_zodb.py
    erp5/trunk/products/ERP5Type/tests/runFunctionalTest.py
    erp5/trunk/products/ERP5Type/tests/runUnitTest.py

Modified: erp5/trunk/products/ERP5Type/tests/ERP5TypeTestCase.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/tests/ERP5TypeTestCase.py?rev=28043&r1=28042&r2=28043&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/tests/ERP5TypeTestCase.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/tests/ERP5TypeTestCase.py [utf8] Thu Jul  9 14:32:09 2009
@@ -34,17 +34,7 @@
 import transaction
 from Testing import ZopeTestCase
 from Testing.ZopeTestCase.PortalTestCase import PortalTestCase, user_name
-from Products.ERP5Type.tests.utils import getMySQLArguments
 from Products.CMFCore.utils import getToolByName
-from Products.ERP5Type.Utils import getLocalPropertySheetList, \
-                                    removeLocalPropertySheet, \
-                                    importLocalPropertySheet
-from Products.ERP5Type.Utils import getLocalDocumentList, \
-                                    removeLocalDocument, \
-                                    importLocalDocument
-from Products.ERP5Type.Utils import getLocalConstraintList, \
-                                    removeLocalConstraint, \
-                                    importLocalConstraint
 from Products.DCWorkflow.DCWorkflow import ValidationFailed
 from Products.ERP5Type.Base import _aq_reset
 from zLOG import LOG, DEBUG
@@ -53,6 +43,9 @@
 install_product_quiet = 1
 # Quiet messages when installing business templates
 install_bt5_quiet = 0
+
+import OFS.Application
+OFS.Application.import_products()
 
 # Std Zope Products
 ZopeTestCase.installProduct('ExtFile', quiet=install_product_quiet)
@@ -161,10 +154,6 @@
      or os.path.isdir(os.path.join(product_dir, product_name, 'Constraint')) \
      or os.path.isdir(os.path.join(product_dir, product_name, 'Tool')):
     ZopeTestCase.installProduct(product_name, quiet=install_product_quiet)
-
-# Install Document types (circumvent different init order in ZopeTestCase)
-from Products.ERP5Type.InitGenerator import initializeProductDocumentRegistry
-initializeProductDocumentRegistry()
 
 from AccessControl.SecurityManagement import newSecurityManager, noSecurityManager
 
@@ -226,7 +215,8 @@
     """
 
     def dummy_test(self):
-      ZopeTestCase._print('All tests are skipped with --save option.')
+      ZopeTestCase._print('All tests are skipped when --save option is passed '
+                          'with --update_business_templates or without --load')
 
     def getRevision(self):
       try:
@@ -328,7 +318,7 @@
       erp5_catalog_storage = os.environ.get('erp5_catalog_storage',
                                             'erp5_mysql_innodb_catalog')
       update_business_templates = os.environ.get('update_business_templates') is not None
-      erp5_load_data_fs = os.environ.get('erp5_load_data_fs') is not None
+      erp5_load_data_fs = int(os.environ.get('erp5_load_data_fs', 0))
       if update_business_templates and erp5_load_data_fs:
         update_only = os.environ.get('update_only', None)
         template_list = (erp5_catalog_storage, 'erp5_core', 'erp5_xhtml_style') + tuple(template_list)
@@ -393,7 +383,6 @@
       global current_app
       current_app = self.app
       self._updateConnectionStrings()
-      self._recreateCatalog()
 
     def afterSetUp(self):
       '''Called after setUp() has completed. This is
@@ -431,13 +420,12 @@
       """Clear activities and catalog and recatalog everything.
       Test runner can set `erp5_tests_recreate_catalog` environnement variable,
       in that case we have to clear catalog. """
-      portal = self.getPortal()
       if int(os.environ.get('erp5_tests_recreate_catalog', 0)):
         try:
-          self.login()
           _start = time.time()
           if not quiet:
             ZopeTestCase._print('\nRecreating catalog ... ')
+          portal = self.getPortal()
           portal.portal_activities.manageClearActivities()
           portal.portal_catalog.manage_catalogClear()
           transaction.commit()
@@ -448,7 +436,6 @@
             ZopeTestCase._print('done (%.3fs)\n' % (time.time() - _start,))
         finally:
           os.environ['erp5_tests_recreate_catalog'] = '0'
-          noSecurityManager()
 
     # Utility methods specific to ERP5Type
     def getTemplateTool(self):
@@ -698,25 +685,23 @@
                 ZopeTestCase._print('done (%.3fs)\n' % (time.time() - _start))
               # Release locks
               transaction.commit()
-
-            if os.environ.get('erp5_load_data_fs'):
-              # Import local PropertySheets, Documents
-              for id_ in getLocalPropertySheetList():
-                importLocalPropertySheet(id_)
-              for id_ in getLocalDocumentList():
-                importLocalDocument(id_)
-              for id_ in getLocalConstraintList():
-                importLocalConstraint(id_)
-            else:
-              # Remove all local PropertySheets, Documents
-              for id_ in getLocalPropertySheetList():
-                removeLocalPropertySheet(id_)
-              for id_ in getLocalDocumentList():
-                removeLocalDocument(id_)
-              for id_ in getLocalConstraintList():
-                removeLocalConstraint(id_)
+            self.portal = portal
+            portal_activities = getattr(portal, 'portal_activities', None)
+
+            if len(setup_done) == 1: # make sure it is run only once
+              try:
+                from Products import DeadlockDebugger
+              except ImportError:
+                pass
+              from Testing.ZopeTestCase.utils import startZServer
+              ZopeTestCase._print('Running ZServer on port %i\n'
+                                  % startZServer()[1])
+              if portal_activities is not None:
+                portal_activities.distributingNode = portal_activities.getCurrentNode()
+                portal_activities._nodes = portal_activities.distributingNode,
 
             self._updateConnectionStrings()
+            self._recreateCatalog()
 
             update_business_templates = os.environ.get('update_business_templates') is not None
             BusinessTemplate_getModifiedObject = aq_base(getattr(portal, 'BusinessTemplate_getModifiedObject', None))
@@ -762,7 +747,6 @@
                 start = time.time()
               # setUpOnce method may use self.app and self.portal
               self.app = app
-              self.portal = portal
               setup_once()
               if not quiet:
                 ZopeTestCase._print('done (%.3fs)\n' % (time.time() - start))
@@ -775,7 +759,6 @@
 
             transaction.commit()
 
-            portal_activities = getattr(portal, 'portal_activities', None)
             if portal_activities is not None:
               if not quiet:
                 ZopeTestCase._print('Executing pending activities ... ')
@@ -804,33 +787,6 @@
             # Reset aq dynamic, so all unit tests will start again
             _aq_reset()
 
-            if os.environ.get('erp5_save_data_fs'):
-              # Quit the test in order to get a clean site
-              if not quiet:
-                ZopeTestCase._print('done (%.3fs)\n' % (time.time()-_start,))
-                ZopeTestCase._print('Data.fs created\n')
-              transaction.commit()
-              ZopeTestCase.close(app)
-              instance_home = os.environ['INSTANCE_HOME']
-              # The output of mysqldump needs to merge many lines at a time
-              # for performance reasons (merging lines is at most 10 times
-              # faster, so this produce somewhat not nice to read sql
-              command = 'mysqldump %s > %s/dump.sql' \
-                          % (getMySQLArguments(), instance_home)
-              if not quiet:
-                ZopeTestCase._print('Dumping MySQL database with %s... ' \
-                                      % command)
-              os.system(command)
-              if not quiet:
-                ZopeTestCase._print('done\n')
-              if not quiet:
-                ZopeTestCase._print('Dumping static files... ')
-              for dir in ('Constraint', 'Document', 'PropertySheet', 'Extensions'):
-                os.system('rm -rf %s/%s.bak' % (instance_home, dir))
-                os.system('cp -ar %s/%s %s/%s.bak' % (instance_home, dir, instance_home, dir))
-              if not quiet:
-                ZopeTestCase._print('done\n')
-
             # Log out
             if not quiet:
               ZopeTestCase._print('Logout ... \n')
@@ -844,18 +800,6 @@
           else:
             transaction.commit()
             ZopeTestCase.close(app)
-
-        if os.environ.get('erp5_load_data_fs'):
-          # Import local PropertySheets, Documents
-          # when loading an environnement
-          for id_ in getLocalPropertySheetList():
-            importLocalPropertySheet(id_)
-          for id_ in getLocalDocumentList():
-            importLocalDocument(id_)
-          for id_ in getLocalConstraintList():
-            importLocalConstraint(id_)
-          _aq_reset()
-
       except:
         f = StringIO()
         traceback.print_exc(file=f)

Modified: erp5/trunk/products/ERP5Type/tests/custom_zodb.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/tests/custom_zodb.py?rev=28043&r1=28042&r2=28043&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/tests/custom_zodb.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/tests/custom_zodb.py [utf8] Thu Jul  9 14:32:09 2009
@@ -7,18 +7,19 @@
 from Products.ERP5Type.tests.utils import getMySQLArguments
 
 instance_home = os.environ.get('INSTANCE_HOME')
-data_fs_path = os.environ.get('erp5_tests_data_fs_path')
-new_data_fs_path = os.path.join(instance_home, 'Data.fs')
+data_fs_path = os.environ.get('erp5_tests_data_fs_path',
+                              os.path.join(instance_home, 'Data.fs'))
+load = int(os.environ.get('erp5_load_data_fs', 0))
+save = int(os.environ.get('erp5_save_data_fs', 0))
 
-if os.environ.get('erp5_load_data_fs'):
-  if os.environ.get('erp5_force_data_fs'):
-    Storage = FileStorage(new_data_fs_path)
+if load:
+  dump_sql = os.path.join(instance_home, 'dump.sql')
+  if os.path.exists(dump_sql):
+    print("Restoring MySQL database ... ")
+    ret = os.system("mysql %s < %s" % (getMySQLArguments(), dump_sql))
+    assert not ret
   else:
-    Storage = DemoStorage(base=FileStorage(new_data_fs_path), quota=(1<<20))
-  print("Restoring MySQL database ... ")
-  ret = os.system("mysql %s < %s/dump.sql" % (
-                getMySQLArguments(), instance_home))
-  assert ret == 0
+    os.environ['erp5_tests_recreate_catalog'] = '1'
   print("Restoring static files ... ")
   for dir in ('Constraint', 'Document', 'PropertySheet', 'Extensions'):
     if os.path.exists(os.path.join(instance_home, '%s.bak' % dir)):
@@ -26,7 +27,7 @@
       shutil.rmtree(full_path)
       shutil.copytree(os.path.join(instance_home, '%s.bak' % dir),
                       full_path, symlinks=True)
-elif os.environ.get('erp5_save_data_fs'):
+else:
   print("Cleaning static files ... ")
   for dir in ('Constraint', 'Document', 'PropertySheet', 'Extensions'):
     full_path = os.path.join(instance_home, dir)
@@ -34,10 +35,12 @@
       assert os.path.isdir(full_path)
       for f in glob.glob('%s/*' % full_path):
         os.unlink(f)
-  if os.path.exists(new_data_fs_path):
-    os.remove(new_data_fs_path)
-  Storage = FileStorage(new_data_fs_path)
-elif data_fs_path:
+  if save and os.path.exists(data_fs_path):
+    os.remove(data_fs_path)
+
+if save:
+  Storage = FileStorage(data_fs_path)
+elif load:
   Storage = DemoStorage(base=FileStorage(data_fs_path), quota=(1<<20))
 else:
   Storage = DemoStorage(quota=(1<<20))

Modified: erp5/trunk/products/ERP5Type/tests/runFunctionalTest.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/tests/runFunctionalTest.py?rev=28043&r1=28042&r2=28043&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/tests/runFunctionalTest.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/tests/runFunctionalTest.py [utf8] Thu Jul  9 14:32:09 2009
@@ -135,7 +135,7 @@
         os.kill(firefox_pid, signal.SIGTERM)
 
 def startZope():
-  os.environ['erp5_force_data_fs'] = "1"
+  os.environ['erp5_save_data_fs'] = "1"
   os.system('%s/bin/zopectl start' % instance_home)
   sleep(2) # ad hoc
 

Modified: erp5/trunk/products/ERP5Type/tests/runUnitTest.py
URL: http://svn.erp5.org/erp5/trunk/products/ERP5Type/tests/runUnitTest.py?rev=28043&r1=28042&r2=28043&view=diff
==============================================================================
--- erp5/trunk/products/ERP5Type/tests/runUnitTest.py [utf8] (original)
+++ erp5/trunk/products/ERP5Type/tests/runUnitTest.py [utf8] Thu Jul  9 14:32:09 2009
@@ -5,11 +5,10 @@
 import re
 import getopt
 import unittest
-
-WIN = False
-if os.name == 'nt':
-  import shutil
-  WIN = True
+import shutil
+import errno
+
+WIN = os.name == 'nt'
 
 
 __doc__ = """%(program)s: unit test runner for the ERP5 Project
@@ -23,20 +22,20 @@
   --portal_id=STRING         force id of the portal. Useful when using
                              --data_fs_path to run tests on an existing
                              Data.fs
-  --data_fs_path=STRING      Path to the original Data.fs to run tests on an
-                             existing environment. The Data.fs is opened read
-                             only
+  --data_fs_path=STRING      Use the given path for the Data.fs
   --bt5_path                 Path to the Business Templates. Default is
                              INSTANCE_HOME/bt5.
   --recreate_catalog=0 or 1  recreate the content of the sql catalog. Default
                              is to recreate, unless using --data_fs_path
-  --save                     add erp5 sites and business templates in Data.fs
-                             and exit without invoking any tests
-  --load                     load Data.fs and skip adding erp5 sites and
-                             business templates
+  --save                     Run unit tests in persistent mode (if unset,
+                             existing Data.fs, dump.sql and *.bak static
+                             folders are not modified). Tests are skipped
+                             if business templates are updated
+                             or if --load is unset.
+  --load                     Reuse existing instance (created with --save).
   --erp5_sql_connection_string=STRING
                              ZSQL Connection string for erp5_sql_connection, by
-                             default, it will use "test test"                            
+                             default, it will use "test test"
   --cmf_activity_sql_connection_string=STRING
                              ZSQL Connection string for
                              cmf_activity_sql_connection (if unset, defaults to
@@ -45,7 +44,7 @@
                              ZSQL Connection string for
                              erp5_sql_deferred_connection (if unset, defaults
                              to erp5_sql_connection_string)
-  --email_from_address=STRING 
+  --email_from_address=STRING
                              Initialise the email_from_address property of the
                              portal, by defaults, CMFActivity failures are sent
                              on localhost from this address, to this address
@@ -58,7 +57,7 @@
                              Run only specified test methods delimited with
                              commas (e.g. testFoo,testBar). This can be regular
                              expressions.
-  -D                         
+  -D
                              Invoke debugger on errors / failures.
   --update_business_templates
                              Update all business templates prior to runing
@@ -174,10 +173,6 @@
 class ERP5TypeTestLoader(unittest.TestLoader):
   """Load test cases from the name passed on the command line.
   """
-  def __init__(self, save=0):
-    if save:
-      self.testMethodPrefix = 'dummy_test'
-
   def loadTestsFromName(self, name, module=None):
     """This method is here for compatibility with old style arguments.
     - It is possible to have the .py prefix for the test file
@@ -249,7 +244,10 @@
   else:
     products_home = os.path.join(instance_home, 'Products')
 
-  from Testing import ZopeTestCase
+  import OFS.Application
+  import_products = OFS.Application.import_products
+  from Testing import ZopeTestCase # This will import custom_zodb.py
+  OFS.Application.import_products = import_products
 
   try:
     # On Zope 2.8, ZopeTestCase does not have any logging facility.
@@ -299,29 +297,31 @@
   # it is then possible to run the debugger by "import pdb; pdb.set_trace()"
   sys.path.insert(0, tests_framework_home)
 
-  save = 0
-  # pass save=1 to test loader to skip all tests in save mode
-  # and monkeypatch PortalTestCase.setUp to skip beforeSetUp and afterSetUp.
-  # Also patch unittest.makeSuite, as it's used in test_suite function in 
-  # test cases.
-  if os.environ.get('erp5_save_data_fs'):
+  test_loader = ERP5TypeTestLoader()
+
+  save = int(os.environ.get('erp5_save_data_fs', 0))
+  dummy_test = save and (int(os.environ.get('update_business_templates', 0))
+                         or not int(os.environ.get('erp5_load_data_fs', 0)))
+  if dummy_test:
+    # Skip all tests in save mode and monkeypatch PortalTestCase.setUp
+    # to skip beforeSetUp and afterSetUp. Also patch unittest.makeSuite,
+    # as it's used in test_suite function in test cases.
     from Products.ERP5Type.tests.ERP5TypeTestCase import \
                   dummy_makeSuite, dummy_setUp, dummy_tearDown
-    save = 1
     from Testing.ZopeTestCase.PortalTestCase import PortalTestCase
     unittest.makeSuite = dummy_makeSuite
     PortalTestCase.setUp = dummy_setUp
     PortalTestCase.tearDown = dummy_tearDown
-  
-  suite = ERP5TypeTestLoader(save=save).loadTestsFromNames(test_list)
+    test_loader.testMethodPrefix = 'dummy_test'
+
+  suite = test_loader.loadTestsFromNames(test_list)
 
   # Hack the profiler to run only specified test methods, and wrap results when
   # running in debug mode. We also monkeypatch unittest.TestCase for tests that
   # does not use ERP5TypeTestCase
-  run_only = os.environ.get('run_only', '')
-  if not save:
-    test_method_list = run_only.split(',')
-    
+  if not dummy_test:
+    test_method_list = os.environ.get('run_only', '').split(',')
+
     def wrapped_run(run_orig):
       # wrap the method that run the test to run test method only if its name
       # matches the run_only spec and to provide post mortem debugging facility
@@ -341,11 +341,33 @@
     from unittest import TestCase
     TestCase.__call__ = wrapped_run(TestCase.__call__)
 
-
-
   # change current directory to the test home, to create zLOG.log in this dir.
   os.chdir(tests_home)
-  return TestRunner(verbosity=verbosity).run(suite)
+  result = TestRunner(verbosity=verbosity).run(suite)
+
+  if save:
+    from Products.ERP5Type.tests.utils import getMySQLArguments
+    # The output of mysqldump needs to merge many lines at a time
+    # for performance reasons (merging lines is at most 10 times
+    # faster, so this produce somewhat not nice to read sql
+    command = 'mysqldump %s > %s' % (getMySQLArguments(),
+                                     os.path.join(instance_home, 'dump.sql'))
+    if verbosity:
+      print('Dumping MySQL database with %s... ' % command)
+    os.system(command)
+    if verbosity:
+      print('Dumping static files... ')
+    for static_dir in 'Constraint', 'Document', 'Extensions', 'PropertySheet':
+      static_dir = os.path.join(instance_home, static_dir)
+      try:
+        shutil.rmtree(static_dir + '.bak')
+      except OSError, e:
+        if e.errno != errno.ENOENT:
+          raise
+      shutil.copytree(static_dir, static_dir + '.bak', symlinks=True)
+
+  return result
+
 
 def usage(stream, msg=None):
   if msg:
@@ -379,9 +401,7 @@
   os.environ["erp5_tests_recreate_catalog"] = "0"
   verbosity = 1
   debug = 0
-  load = False
-  save = False
-  
+
   for opt, arg in opts:
     if opt in ("-v", "--verbose"):
       os.environ['VERBOSE'] = "1"
@@ -418,10 +438,8 @@
       os.environ["email_from_address"] = arg
     elif opt == "--save":
       os.environ["erp5_save_data_fs"] = "1"
-      save = True
     elif opt == "--load":
       os.environ["erp5_load_data_fs"] = "1"
-      load = True
     elif opt == "--erp5_catalog_storage":
       os.environ["erp5_catalog_storage"] = arg
     elif opt == "--run_only":
@@ -432,9 +450,6 @@
     elif opt == "--update_business_templates":
       os.environ["update_business_templates"] = "1"
 
-  if load and save:
-    os.environ["erp5_force_data_fs"] = "1"
-
   test_list = args
   if not test_list:
     print "No test to run, exiting immediately."




More information about the Erp5-report mailing list