Commit 96c6ea1c authored by Jérome Perrin's avatar Jérome Perrin

Backport and small fixes for unittest

See merge request !2051
parents 143be498 24638029
......@@ -315,6 +315,7 @@ class Test(ERP5TypeTestCase):
except ImportError:
import traceback
traceback.print_exc(file=global_stream)
traceback.print_exc() # also print on stderr
global_stream.seek(0)
return global_stream.read()
finally:
......
......@@ -291,12 +291,18 @@ def runLiveTest(test_list, verbosity=1, stream=None, request_server_url=None, **
output = stream
if stream is None:
output = StringIO()
def print_and_write(data):
sys.stderr.write(data)
sys.stderr.flush()
return output.write(data)
print_and_write("**Running Live Test:\n")
ZopeTestCase._print = print_and_write
class StderrIOWrapper:
def __init__(self, wrapped):
self._wrapped_io = wrapped
def write(self, data):
sys.stderr.write(data)
return self._wrapped_io.write(data)
def __getattr__(self, attr):
return getattr(self._wrapped_io, attr)
output = StderrIOWrapper(output)
output.write("**Running Live Test:\n")
ZopeTestCase._print = output.write
with warnings.catch_warnings():
warnings.simplefilter(kw['warnings'])
......@@ -306,6 +312,6 @@ def runLiveTest(test_list, verbosity=1, stream=None, request_server_url=None, **
from AccessControl.SecurityManagement import getSecurityManager, setSecurityManager
sm = getSecurityManager()
try:
result = TestRunner(stream=output, verbosity=verbosity).run(suite)
TestRunner(stream=output, verbosity=verbosity).run(suite)
finally:
setSecurityManager(sm)
......@@ -17,6 +17,7 @@ import string
import sys
import time
import traceback
import warnings
from six.moves import configparser
from contextlib import contextmanager
from io import BytesIO
......@@ -273,6 +274,10 @@ class ERP5TypeTestCaseMixin(ProcessingNodeTestCase, PortalTestCase, functional.F
def newPassword(self):
""" Generate a password """
forced_password = os.environ.get('insecure_erp5_test_password')
if forced_password:
warnings.warn("Using password set from environment variable")
return forced_password
return ''.join(random.SystemRandom().sample(string.ascii_letters + string.digits, 20))
def login(self, user_name=None, quiet=0):
......
......@@ -11,6 +11,8 @@ class SetupSiteError(Exception):
def patch():
import six
import contextlib
import sys
import traceback
from unittest import TestCase, TextTestResult, TextTestRunner
......@@ -21,6 +23,20 @@ def patch():
TestCase.assertRaisesRegex = getattr(TestCase, 'assertRaisesRegexp')
TestCase.assertRegex = getattr(TestCase, 'assertRegexpMatches')
TestCase.assertCountEqual = TestCase.assertItemsEqual
@contextlib.contextmanager
def subTest(self, msg='', **params):
yield
TestCase.subTest = subTest
if sys.version_info < (3, 11):
def enterContext(self, cm):
cls = type(cm)
enter = cls.__enter__
exit = cls.__exit__
result = enter(cm)
self.addCleanup(exit, cm, None, None, None)
return result
TestCase.enterContext = enterContext
TextTestResult_addError = six.get_unbound_function(TextTestResult.addError)
def addError(self, test, err):
......
......@@ -150,6 +150,7 @@ Options:
timer service.
This option only makes sense with --activity_node=
or when not specifying a test to run.
--insecure_password=PWD Use `PWD` instead of generating random passwords for users.
--zserver=ADDRESS[,...] Make ZServer listen on given IPv4 address.
Addresses can be given in the following syntaxs:
- HOST:PORT
......@@ -798,7 +799,8 @@ def main(argument_list=None):
"sys_path=",
"instance_home=",
"log_directory=",
"with_wendelin_core"
"with_wendelin_core",
"insecure_password=",
])
except getopt.GetoptError as msg:
usage(sys.stderr, msg)
......@@ -919,6 +921,8 @@ def main(argument_list=None):
_log_directory = os.path.abspath(arg)
elif opt == "--with_wendelin_core":
os.environ["with_wendelin_core"] = "1"
elif opt == "--insecure_password":
os.environ["insecure_erp5_test_password"] = arg
setupWarnings()
......
......@@ -3255,17 +3255,9 @@ class Test(ERP5TypeTestCase):
self.assertNotEqual(os, None)
'''
def testRunLiveTest(self):
"""
Create a new ZODB Test Component and try to run it as a live tests and
check the expected output
def _runLiveTest(self, test_name):
"""Runs a live test from portal_components
"""
# First try with a test which run successfully
source_code = self._getValidSourceCode()
component = self._newComponent('testRunLiveTest', source_code)
component.validate()
self.tic()
from Products.ERP5Type.tests.runUnitTest import ERP5TypeTestLoader
ERP5TypeTestLoader_loadTestsFromNames = ERP5TypeTestLoader.loadTestsFromNames
def loadTestsFromNames(self, *args, **kwargs):
......@@ -3287,6 +3279,35 @@ class Test(ERP5TypeTestCase):
return ret
# ERP5TypeLiveTestCase.runLiveTest patches ERP5TypeTestCase bases, thus it
# needs to be restored after calling runLiveTest
base_tuple = ERP5TypeTestCase.__bases__
ERP5TypeTestLoader.loadTestsFromNames = loadTestsFromNames
from six.moves import cStringIO as StringIO
stderr = StringIO()
_real_stderr = sys.stderr
sys.stderr = stderr
try:
self._component_tool.runLiveTest(test_name)
finally:
ERP5TypeTestCase.__bases__ = base_tuple
ERP5TypeTestLoader.loadTestsFromNames = ERP5TypeTestLoader_loadTestsFromNames
sys.stderr = _real_stderr
test_output = self._component_tool.readTestOutput()
self.assertEqual(stderr.getvalue(), test_output)
return test_output
def testRunLiveTest(self):
"""
Create a new ZODB Test Component and try to run it as a live tests and
check the expected output
"""
# First try with a test which run successfully
source_code = self._getValidSourceCode()
component = self._newComponent('testRunLiveTest', source_code)
component.validate()
self.tic()
self.assertEqual(component.getValidationState(), 'validated')
self.assertModuleImportable('testRunLiveTest')
self._component_tool.reset(force=True,
......@@ -3295,19 +3316,7 @@ class Test(ERP5TypeTestCase):
# set a request key, that should not be set from the test request
self.portal.REQUEST.set('foo', 'something from main request')
def runLiveTest(test_name):
# 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(test_name)
finally:
ERP5TypeTestCase.__bases__ = base_tuple
ERP5TypeTestLoader.loadTestsFromNames = ERP5TypeTestLoader_loadTestsFromNames
return self._component_tool.readTestOutput()
output = runLiveTest('testRunLiveTest')
output = self._runLiveTest('testRunLiveTest')
expected_msg_re = re.compile('Ran 1 test.*OK', re.DOTALL)
self.assertRegex(output, expected_msg_re)
......@@ -3325,7 +3334,7 @@ class Test(ERP5TypeTestCase):
self._component_tool.reset(force=True,
reset_portal_type_at_transaction_boundary=True)
output = runLiveTest('testRunLiveTest')
output = self._runLiveTest('testRunLiveTest')
expected_msg_re = re.compile(r'Ran 2 tests.*FAILED \(failures=1\)', re.DOTALL)
self.assertRegex(output, expected_msg_re)
......@@ -3350,7 +3359,7 @@ class Test(ERP5TypeTestCase):
self._component_tool.reset(force=True,
reset_portal_type_at_transaction_boundary=True)
output = runLiveTest('testRunLiveTest')
output = self._runLiveTest('testRunLiveTest')
expected_msg_re = re.compile('Ran 3 test.*OK', re.DOTALL)
self.assertRegex(output, expected_msg_re)
......@@ -3364,44 +3373,11 @@ break_at_import()
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._component_tool.reset(force=True,
reset_portal_type_at_transaction_boundary=True)
def runLiveTest(test_name):
# 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(test_name)
finally:
ERP5TypeTestCase.__bases__ = base_tuple
ERP5TypeTestLoader.loadTestsFromNames = ERP5TypeTestLoader_loadTestsFromNames
return self._component_tool.readTestOutput()
output = runLiveTest('testRunLiveTestImportError')
output = self._runLiveTest('testRunLiveTestImportError')
relative_url = 'portal_components/test.erp5.testRunLiveTestImportError'
if six.PY2:
module_file = '<' + relative_url + '>'
......@@ -3417,7 +3393,7 @@ break_at_import()
%(error_message)s
''' % dict(module_file=module_file, error_message=error_message), output)
output = runLiveTest('testDoesNotExist_import_error_because_module_does_not_exist')
output = self._runLiveTest('testDoesNotExist_import_error_because_module_does_not_exist')
if six.PY2:
expected_output = "ImportError: No module named testDoesNotExist_import_error_because_module_does_not_exist"
else:
......
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