Commit 72aa9dd4 authored by Łukasz Nowak's avatar Łukasz Nowak

[erp5_test_result]: Periodical Test Suite

By extending TestSuite class with Periodicity mixin it is possible to
enable and configure periodicity.

TestSuite.isRestartAllowed used by
ERP5ProjectUnitTestDistributor.createTestResult in order to create new
Test Result for configured periodicity if finished one already exists.

 - [x] remove method isRestartAllowed
 - [x] use method getAlarmDate
 - [x] in ERP5ProjectUnitTestDistributor.py, I would use "alarm_date = test_suite.getAlarmDate()" and then "if alarm_date and alarm_date <= now: ..."
 - [x] set next alarm date

/reviewed-on !479
parent 9b03eebc
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ActionInformation" module="Products.CMFCore.ActionInformation"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>action</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_view</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_view</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>periodicity</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>View</string>
</tuple>
</value>
</item>
<item>
<key> <string>priority</string> </key>
<value> <float>2.0</float> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Periodicity</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
<value> <int>1</int> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/Periodicity_view</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="Expression" module="Products.CMFCore.Expression"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>python: here.isEnabled()</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -3,8 +3,9 @@ from DateTime import DateTime ...@@ -3,8 +3,9 @@ from DateTime import DateTime
from zLOG import LOG,INFO,ERROR from zLOG import LOG,INFO,ERROR
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions from Products.ERP5Type import Permissions
from Products.ERP5.mixin.periodicity import PeriodicityMixin
class TestSuite(XMLObject): class TestSuite(XMLObject, PeriodicityMixin):
security = ClassSecurityInfo() security = ClassSecurityInfo()
security.declareObjectProtected(Permissions.AccessContentsInformation) security.declareObjectProtected(Permissions.AccessContentsInformation)
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
</portal_type> </portal_type>
<portal_type id="Test Suite"> <portal_type id="Test Suite">
<item>Arrow</item> <item>Arrow</item>
<item>Periodicity</item>
<item>Reference</item> <item>Reference</item>
<item>ScalabilityTestSuite</item> <item>ScalabilityTestSuite</item>
<item>SortIndex</item> <item>SortIndex</item>
......
...@@ -84,6 +84,8 @@ ...@@ -84,6 +84,8 @@
<value> <value>
<list> <list>
<string>my_cluster_configuration</string> <string>my_cluster_configuration</string>
<string>my_enabled</string>
<string>my_alarm_date</string>
</list> </list>
</value> </value>
</item> </item>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>date_only</string>
<string>description</string>
<string>editable</string>
<string>enabled</string>
<string>timezone_style</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_alarm_date</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>date_only</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>timezone_style</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>date_only</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>The time, when test will be allowed to be repeated for the same revision.</string> </value>
</item>
<item>
<key> <string>editable</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_date_time_field</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>timezone_style</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Next Test Repeat After</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="TALESMethod" module="Products.Formulator.TALESField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>here/isEnabled</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_enabled</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_checkbox</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Periodicity Enabled</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -1066,3 +1066,72 @@ class TestTaskDistribution(ERP5TypeTestCase): ...@@ -1066,3 +1066,72 @@ class TestTaskDistribution(ERP5TypeTestCase):
def test_19_testMultiDistributor(self): def test_19_testMultiDistributor(self):
pass pass
def test_20_TestSuite_Periodicity(self):
revision = 'a=a,b=b,c=c'
self.addCleanup(self.unpinDateTime)
test_suite = self.test_suite_module.newContent(
portal_type='Test Suite',
title='Periodicity Enabled Test Suite',
int_index=1,
# periodicity enabled
enabled=True,
# periodicity configuration
periodicity_day_frequency=1,
periodicity_hour=(13,),
periodicity_minute=(0,),
)
test_suite.validate()
self.tic()
self.pinDateTime(DateTime('2017/05/01 00:00:00 UTC'))
self.assertEqual(None, test_suite.getAlarmDate())
first_test_result, got_revision = self._createTestResult(revision=revision, test_title='Periodicity Enabled Test Suite')
self.assertTrue(first_test_result.startswith('test_result_module/'))
self.assertEqual(revision, got_revision)
self.assertEqual(DateTime('2017/05/01 13:00:00 UTC'), test_suite.getAlarmDate())
# Finish the current test run
self.portal.restrictedTraverse(first_test_result).stop()
self.tic()
self.pinDateTime(DateTime('2017/05/01 14:00:00 UTC'))
second_test_result, got_revision = self._createTestResult(revision=revision, test_title='Periodicity Enabled Test Suite')
self.assertTrue(second_test_result.startswith('test_result_module/'))
self.assertNotEqual(first_test_result, second_test_result)
self.assertEqual(revision, got_revision)
self.assertEqual(DateTime('2017/05/02 13:00:00 UTC'), test_suite.getAlarmDate())
# Finish the current test run
self.portal.restrictedTraverse(second_test_result).stop()
self.tic()
self.pinDateTime(DateTime('2017/05/02 14:00:00 UTC'))
third_test_result, got_revision = self._createTestResult(revision=revision, test_title='Periodicity Enabled Test Suite')
self.assertTrue(third_test_result.startswith('test_result_module/'))
self.assertNotEqual(third_test_result, second_test_result)
self.assertEqual(DateTime('2017/05/03 13:00:00 UTC'), test_suite.getAlarmDate())
self.tic()
def test_21_TestSuite_Periodicity_disabled(self):
self.addCleanup(self.unpinDateTime)
test_suite = self.test_suite_module.newContent(
portal_type='Test Suite',
title='Periodicity Disabled Test Suite',
int_index=1,
# periodicity disabled
enabled=False,
# periodicity configuration
periodicity_day_frequency=1,
periodicity_hour=(13,),
periodicity_minute=(0,),
)
test_suite.validate()
today = DateTime('2017/05/01')
self.tic()
self.pinDateTime(today)
self.assertEqual(None, test_suite.getAlarmDate())
self._createTestResult(test_title='Periodicity Disabled Test Suite')
self.assertEqual(None, test_suite.getAlarmDate())
self.tic()
self._createTestResult(test_title='Periodicity Disabled Test Suite')
self.assertEqual(None, test_suite.getAlarmDate())
\ No newline at end of file
...@@ -31,4 +31,5 @@ Test Result | view_node_list ...@@ -31,4 +31,5 @@ Test Result | view_node_list
Test Result | view_performance_graph Test Result | view_performance_graph
Test Suite Module | view Test Suite Module | view
Test Suite Repository | view Test Suite Repository | view
Test Suite | periodicity
Test Suite | view Test Suite | view
\ No newline at end of file
...@@ -26,6 +26,7 @@ Test Result | Task ...@@ -26,6 +26,7 @@ Test Result | Task
Test Suite Repository | TestSuiteRepository Test Suite Repository | TestSuiteRepository
Test Suite Repository | TestSuiteRepositoryConstraint Test Suite Repository | TestSuiteRepositoryConstraint
Test Suite | Arrow Test Suite | Arrow
Test Suite | Periodicity
Test Suite | Reference Test Suite | Reference
Test Suite | ScalabilityTestSuite Test Suite | ScalabilityTestSuite
Test Suite | SortIndex Test Suite | SortIndex
......
...@@ -397,6 +397,16 @@ class ERP5ProjectUnitTestDistributor(XMLObject): ...@@ -397,6 +397,16 @@ class ERP5ProjectUnitTestDistributor(XMLObject):
test_node.setPingDate() test_node.setPingDate()
test_suite = self._getTestSuiteFromTitle(test_title) test_suite = self._getTestSuiteFromTitle(test_title)
if test_suite is not None: if test_suite is not None:
if not allow_restart and test_suite.isEnabled():
# in case if allow_restart is not enforced by client and test_node
# periodicity is enabled control the restartability based on test_suite
# periodicity
current_date = DateTime()
alarm_date = test_suite.getAlarmDate()
if alarm_date is None or alarm_date <= current_date:
allow_restart = True
test_suite.setAlarmDate(
test_suite.getNextPeriodicalDate(current_date, alarm_date))
test_suite.setPingDate() test_suite.setPingDate()
return portal.portal_task_distribution.createTestResult(name, return portal.portal_task_distribution.createTestResult(name,
revision, test_name_list, allow_restart, revision, test_name_list, allow_restart,
......
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