Commit 7d34f032 authored by Arnaud Fontaine's avatar Arnaud Fontaine

ZODB Components: Keep a reference of Test Component module on ERP5TypeTestLoader.

All other Component modules must be kept alive during the REQUEST life (f523edc4).
However, Unit Tests modules should be kept alive until it finished executing and
this may span accross multiple REQUESTS.

Issue found out when migrating testBusinessTemplate to erp5_core_test which was
failing as the module was GC'ed and its top-level variables were reset to None by
the interpreter.
parent de85c464
......@@ -202,15 +202,12 @@ class ERP5TypeTestReLoader(ERP5TypeTestLoader):
otherwise fallback on filesystem
"""
if module is None:
import erp5.component.test
try:
__import__('erp5.component.test.' + name.split('.')[0],
fromlist=['erp5.component.test'],
level=0)
self._importZodbTestComponent(name.split('.')[0])
except ImportError:
pass
else:
import erp5.component.test
module = erp5.component.test
return super(ERP5TypeTestReLoader, self).loadTestsFromName(name,
......
......@@ -278,6 +278,16 @@ class ERP5TypeTestLoader(unittest.TestLoader):
lambda self: self._testMethodPrefix,
lambda self, value: None)
def _importZodbTestComponent(self, name):
import erp5.component.test
module = __import__('erp5.component.test.' + name,
fromlist=['erp5.component.test'],
level=0)
try:
self._test_component_ref_list.append(module)
except AttributeError:
self._test_component_ref_list = [module]
def loadTestsFromName(self, name, module=None):
"""
This method is here for compatibility with old style arguments:
......@@ -308,17 +318,13 @@ class ERP5TypeTestLoader(unittest.TestLoader):
if ComponentTestCase not in ERP5TypeTestCase.__bases__:
ERP5TypeTestCase.__bases__ = ComponentTestCase,
# TestLoader() does not perform any import so import the Module manually
module = __import__('erp5.component.test',
fromlist=['erp5.component.test'],
level=0)
# TODO-arnau: What about loading a test for a specific Component Version?
# `./runUnitTest erp5_base:testBase` executes Unit Test from
# erp5.component.testBase Module. This needs be imported beforehand:
# unittest loadTestsFromName() will then `getattr(module, name)`
name = name.split(':')[1]
__import__('erp5.component.test.%s' % name.split('.')[0],
['erp5.component.test'],
level=0)
import erp5.component.test
module = erp5.component.test
self._importZodbTestComponent(name.split('.')[0])
return super(ERP5TypeTestLoader, self).loadTestsFromName(name, module)
......
......@@ -2829,6 +2829,7 @@ class TestZodbTestComponent(_TestZodbComponent):
def _getValidSourceCode(self, *_):
return '''from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
import os
class Test(ERP5TypeTestCase):
def getTitle(self):
......@@ -2851,6 +2852,12 @@ class Test(ERP5TypeTestCase):
def test_01_sampleTest(self):
self.assertEqual(0, 0)
def afterClear(self):
super(Test, self).afterClear()
# Checked that this module has not been GC'ed until the very end...
self.assertNotEqual(os, None)
'''
def testRunLiveTest(self):
......@@ -2864,6 +2871,27 @@ class Test(ERP5TypeTestCase):
component.validate()
self.tic()
from Products.ERP5Type.tests.runUnitTest import ERP5TypeTestLoader
ERP5TypeTestLoader_loadTestsFromNames = ERP5TypeTestLoader.loadTestsFromNames
def loadTestsFromNames(self, *args, **kwargs):
"""
Monkey patched to simulate a reset right after importing the ZODB Test
Component whose Unit Tests are going to be executed
"""
ret = ERP5TypeTestLoader_loadTestsFromNames(self, *args, **kwargs)
from Products.ERP5.ERP5Site import getSite
getSite().portal_components.reset(force=True)
# Simulate a new REQUEST while the old one has been GC'ed
import erp5.component
erp5.component.ref_manager.clear()
import gc
gc.collect()
return ret
self.assertEqual(component.getValidationState(), 'validated')
self.assertModuleImportable('testRunLiveTest')
self._component_tool.reset(force=True,
......@@ -2872,10 +2900,12 @@ class Test(ERP5TypeTestCase):
# ERP5TypeLiveTestCase.runLiveTest patches ERP5TypeTestCase bases, thus it
# needs to be restored after calling runLiveTest
base_tuple = ERP5TypeTestCase.__bases__
ERP5TypeTestLoader.loadTestsFromNames = loadTestsFromNames
try:
self._component_tool.runLiveTest('testRunLiveTest')
finally:
ERP5TypeTestCase.__bases__ = base_tuple
ERP5TypeTestLoader.loadTestsFromNames = ERP5TypeTestLoader_loadTestsFromNames
# assertRegexpMatches is only available from Python >= 2.7
import re
......@@ -2899,10 +2929,12 @@ class Test(ERP5TypeTestCase):
reset_portal_type_at_transaction_boundary=True)
base_tuple = ERP5TypeTestCase.__bases__
ERP5TypeTestLoader.loadTestsFromNames = loadTestsFromNames
try:
self._component_tool.runLiveTest('testRunLiveTest')
finally:
ERP5TypeTestCase.__bases__ = base_tuple
ERP5TypeTestLoader.loadTestsFromNames = ERP5TypeTestLoader_loadTestsFromNames
# assertRegexpMatches is only available from Python >= 2.7
import re
......
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