__init__.py 13.2 KB
Newer Older
1 2
from glob import glob
import os, subprocess, re
3
# test_suite is provided by 'run_test_suite'
4
from test_suite import ERP5TypeTestSuite, SavedTestSuite
Sebastien Robin's avatar
Sebastien Robin committed
5
import sys
6

7 8
HERE = os.path.dirname(__file__)

9
class _ERP5(ERP5TypeTestSuite):
10
  _saved_test_id = "erp5_web_renderjs_ui_test:testFunctionalRJSInterfaceValidator"
11 12
  realtime_output = False
  enabled_product_list = ('CMFActivity', 'CMFCategory', 'ERP5', 'ERP5Catalog',
13
                          'ERP5eGovSecurity', 'ERP5Form',
14
                          'ERP5OOo', 'ERP5Security', 'ERP5SyncML', 'ERP5Type',
15
                          'ERP5Wizard', 'Formulator', 'ERP5Workflow',
16
                          'HBTreeFolder2', 'MailTemplates',
17
                          'PortalTransforms', 'TimerService', 'ZLDAPConnection', 
18
                          'ZLDAPMethods', 'ZMySQLDA', 'ZSQLCatalog', 'Zelenium')
19 20 21 22 23 24 25 26 27 28 29 30 31 32

  def enableProducts(self):
    product_set = set(self.enabled_product_list)
    try:
      dir_set = set(os.walk('Products').next()[1])
      for product in dir_set - product_set:
        os.unlink(os.path.join('Products', product))
      product_set -= dir_set
    except StopIteration:
      os.mkdir('Products')
    for product in product_set:
      os.symlink(os.path.join('..', 'products', product),
                 os.path.join('Products', product))

33 34
  def _getAllTestList(self):
    test_list = []
35
    path = "%s/../" % HERE
36 37
    component_re = re.compile(".*/([^/]+)/TestTemplateItem/portal_components"
                              "/test\.[^.]+\.([^.]+).py$")
38
    for test_path in (
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
        # glob('%s/product/Formulator/tests/test*.py' % path) +
        # glob('%s/product/ERP5Form/tests/test*.py' % path) +
        # ['%s/product/ERP5OOo/tests/testDeferredStyle.py' % path] +
        # ['%s/product/ERP5/tests/testXHTML.py' % path] +
        # ['%s/product/ERP5/tests/testERP5Core.py' % path] +
        # ['%s/product/ERP5/tests/testQueryModule.py' % path] +
        # ['%s/product/ERP5/tests/testBankReconciliation.py' % path] +
        # ['%s/product/ERP5Security/tests/testERP5Security.py' % path] +
        # ['%s/product/ERP5Type/tests/testFunctionalCore.py' % path] +
        # ['%s/product/ERP5Type/tests/testFunctionalKM.py' % path] +
        # ['%s/product/ERP5Type/tests/testFunctionalAnonymousSelection.py' % path] +
        # glob('%s/bt5/erp5_web/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        # glob('%s/bt5/erp5_web_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        glob('%s/bt5/erp5_hal_json_style/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        glob('%s/bt5/erp5_web_renderjs_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        # glob('%s/bt5/erp5_web_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        # glob('%s/bt5/erp5_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        # glob('%s/bt5/erp5_token_login/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        glob('%s/bt5/erp5_trade_renderjs_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        glob('%s/bt5/erp5_pdm_renderjs_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        glob('%s/bt5/erp5_crm_renderjs_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        glob('%s/bt5/erp5_item_renderjs_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        glob('%s/bt5/erp5_deferred_renderjs_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        glob('%s/bt5/erp5_accounting_renderjs_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        # glob('%s/bt5/erp5_accounting_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        glob('%s/bt5/erp5_bank_reconciliation_renderjs_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        glob('%s/bt5/erp5_document_scanner_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        glob('%s/bt5/erp5_gadget_interface_validator_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        # glob('%s/bt5/erp5_web_monitoring_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        glob('%s/bt5/erp5_travel_expense_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        glob('%s/bt5/erp5_officejs_support_request_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        glob('%s/bt5/erp5_officejs_afs_directory_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        glob('%s/bt5/erp5_configurator_standard/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        # glob('%s/bt5/erp5_test_result/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        glob('%s/bt5/erp5_officejs_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        glob('%s/bt5/erp5_web_manifest_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        glob('%s/bt5/erp5_km_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        glob('%s/bt5/erp5_monaco_editor_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        glob('%s/bt5/erp5_web_project_ui_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        glob('%s/bt5/erp5_corporate_identity_test/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        # glob('%s/bt5/erp5_oauth*/TestTemplateItem/portal_components/test.*.test*.py' % path) +
        []
      ):
82 83 84 85 86 87
      component_re_match = component_re.match(test_path)
      if component_re_match is not None:
        test_case = "%s:%s" % (component_re_match.group(1),
                               component_re_match.group(2))
      else:
        test_case = test_path.split(os.sep)[-1][:-3] # remove .py
88 89 90 91
      product = test_path.split(os.sep)[-3]
      # don't test 3rd party products
      if product in ('PortalTransforms', 'MailTemplates', 'Zelenium'):
        continue
92 93 94 95
      # ERP5TioSafe is disabled for now because it requires external programs
      # such as php and it has not been updated for Zope >= 2.12
      if product == 'ERP5TioSafe':
        continue
96 97 98
      test_list.append(test_case)
    return test_list

99
  def update(self):
100 101 102 103 104 105 106
    self.checkout('products', 'bt5')
    self.enableProducts()


class PERF(_ERP5):

  def getTestList(self):
107
    return [x for x in self._getAllTestList() if x.find('Performance')>0]
108

109 110 111
class CloudPERF(_ERP5):

  def getTestList(self):
112
    return ['_testPystone', '_testSQLBench']
113

114 115 116 117 118
class ERP5(_ERP5):
  mysql_db_count = 3

  def getTestList(self):
    test_list = []
119 120 121 122
    for full_test_case in self._getAllTestList():
      test_case = (':' in full_test_case and full_test_case.split(':')[1]
                   or full_test_case)

123
      # skip some tests
124
      if test_case.find('Performance') > 0 \
125 126
         or test_case in ('testERP5LdapCatalog', # XXX (Ivan), until LDAP server is available this test will alway fail
                          # tests reading selenium tables from erp5.com
127
                          # not maintained
128
                          'testERP5eGov',
129 130 131 132
                          'testAccounting_l10n_fr_m9',
                          # Not a test
                          'testERP5SyncMLMixin'
         ):
133
        continue
134
      test_list.append(full_test_case)
135 136
    return test_list

137 138 139 140
  def run(self, full_test):
    test = ':' in full_test and full_test.split(':')[1] or full_test
    if test in ('testConflictResolution', 'testInvalidationBug'):
      status_dict = self.runUnitTest('--save', full_test)
141
      if not status_dict['status_code']:
142
        status_dict = self.runUnitTest('--load', '--activity_node=2', full_test)
143
      return status_dict
144
    elif test.startswith('testFunctional'):
145
      return self._updateFunctionalTestResponse(self.runUnitTest(full_test))
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
    elif test == 'testUpgradeInstanceWithOldDataFs':
      old_data_path = None
      for path in sys.path:
        if path.endswith('/erp5-bin'):
          old_data_path = os.path.join(path, 'test_data', test)
          if not os.path.isdir(old_data_path):
            return dict(
              status_code=-1,
              test_count=1,
              failure_count=1,
              stderr='%s does not exist or is not a directory' % old_data_path)

          break
      else:
        return dict(
          status_code=-1,
          test_count=1,
          failure_count=1,
          stderr='erp5-bin repository not found in %s' % '\n'.join(sys.path))

      instance_home = (self.instance and 'unit_test.%u' % self.instance
                       or 'unit_test')

      import shutil
170 171 172
      shutil.rmtree(instance_home, ignore_errors=True)

      os.makedirs(os.path.join(instance_home, 'var'))
173 174 175 176 177
      shutil.copyfile(os.path.join(old_data_path, 'Data.fs'),
                      os.path.join(instance_home, 'var', 'Data.fs'))
      shutil.copyfile(os.path.join(old_data_path, 'dump.sql'),
                      os.path.join(instance_home, 'dump.sql'))

178
      return self.runUnitTest('--load', '--portal_id=erp5', full_test)
179

180
    return super(ERP5, self).run(full_test)
181

182
  def _updateFunctionalTestResponse(self, status_dict):
183 184 185 186
    """ Convert the Unit Test output into more accurate information
        related to funcional test run.
    """
    # Parse relevant information to update response information
187 188 189
    try:
      summary, html_test_result = status_dict['stderr'].split("-"*79)[1:3]
    except ValueError:
190
      # In case of error when parse the file, preserve the original
191 192
      # informations. This prevents we have unfinished tests.
      return status_dict
193 194 195 196 197 198
    status_dict['html_test_result'] = html_test_result
    search = self.FTEST_PASS_FAIL_RE.search(summary)
    if search:
      group_dict = search.groupdict()
      status_dict['failure_count'] = int(group_dict['failures'])
      status_dict['test_count'] = int(group_dict['total'])
199
      status_dict['skip_count'] = int(group_dict['expected_failure'])
200 201
    return status_dict

202 203

class ERP5_simulation(_ERP5):
204 205

  def getTestList(self):
206 207 208 209 210 211 212 213 214 215 216 217
    p = subprocess.Popen(('grep', '-lr', '--include=test*.py',
                          '-e', '@newSimulationExpectedFailure',
                          '-e', 'erp5_report_new_simulation_failures',
                          'Products/ERP5/tests'),
                         stdout=subprocess.PIPE)
    return sorted(os.path.basename(x)[:-3]
                  for x in p.communicate()[0].splitlines())

  def runUnitTest(self, *args, **kw):
    return super(ERP5_simulation, self).runUnitTest(
      erp5_report_new_simulation_failures='1', *args, **kw)

218
class ERP5_scalability(_ERP5):
219

220 221 222 223 224
  def getTestList(self):
    return ['createPerson', 'createSaleOrder', 'createWebPage']

  def getTestPath(self):
    return 'erp5/util/benchmark/examples/'
225

226 227 228 229 230 231 232 233 234 235 236 237
  def getUsersFilePath(self):
    return 'erp5/util/benchmark/examples/scalabilityUsers'

  def getUserNumber(self, test_number):
    return [45, 135, 170, 220, 250][test_number]

  # Test duration in seconds
  def getTestDuration(self, test_number):
    return 60*10

  def getTestRepetition(self, test_number):
    return 3
Xiaowu Zhang's avatar
Xiaowu Zhang committed
238 239 240 241 242 243

class ERP5_XHTML_Only(_ERP5):

  def _getAllTestList(self):
    path = sys.path[0]
    return ['%s/product/ERP5/tests/testXHTML.py' % path]
244 245 246 247 248 249

class FunctionalTests(ERP5):

  def _getAllTestList(self):
    return [x for x in super(FunctionalTests, self)._getAllTestList()
      if x.startswith('testFunctional') or ':testFunctional' in x]
250 251 252 253 254 255 256 257


class ERP5BusinessTemplateCodingStyleTestSuite(_ERP5):
  """Run coding style test on all business templates.
  """
  def getTestList(self):
    test_list = []
    for business_template_path in (
258 259 260 261 262 263 264 265 266 267 268
        glob('%s/../product/ERP5/bootstrap/erp5_*' % HERE) +
        glob('%s/../bt5/erp5_adm*' % HERE) +
        glob('%s/../bt5/erp5_*hal*' % HERE) +
        glob('%s/../bt5/erp5_*renderjs*' % HERE) +
        glob('%s/../bt5/erp5_*officejs*' % HERE) +
        glob('%s/../bt5/erp5_web*' % HERE) +
        glob('%s/../bt5/erp5_configu*' % HERE) +
        glob('%s/../bt5/erp5_upgrader*' % HERE) +
        glob('%s/../bt5/erp5_corporate_identity*' % HERE) +
        []
      ):
269 270 271 272 273 274 275 276 277 278
      # we skip coding style check for business templates having this marker
      # property. Since the property is not exported (on purpose), modified business templates
      # will be candidate for coding style test again.
      if os.path.isdir(business_template_path) and \
              not os.path.exists(os.path.join(business_template_path, 'bt/skip_coding_style_test')):
        test_list.append(os.path.basename(business_template_path))
    return test_list

  def run(self, full_test):
    return self.runUnitTest('CodingStyleTest', TESTED_BUSINESS_TEMPLATE=full_test)
279

280 281 282 283 284 285 286 287
  def getLogDirectoryPath(self, *args, **kw):
    log_directory = os.path.join(
        self.log_directory,
        '{}-{}'.format(args[-1] , kw['TESTED_BUSINESS_TEMPLATE']))
    os.mkdir(log_directory)
    return log_directory


288 289 290 291 292 293 294 295 296
class RJS_Only(_ERP5):
  def getTestList(self):
    rjs_officejs_bt_list = ["erp5_officejs_",
                            "renderjs_ui_test",
                            "erp5_monaco_editor_ui_test",
                            "erp5_travel_expense_ui_test",
                            "erp5_gadget_interface_validator_ui_test",
                            "erp5_hal_json_style"]
    return [test for test in self._getAllTestList() if any(test.find(bt)>-1 for bt in rjs_officejs_bt_list)]