diff --git a/Makefile b/Makefile index 180691381..61cee6b53 100644 --- a/Makefile +++ b/Makefile @@ -36,8 +36,16 @@ uninstall: .PHONY : tests tests: - cd tests/$(NAME) - PYTHONPATH=../.. python -m unittest discover -v . "*Test.py" + python -m unittest discover -vs tests/SpiffWorkflow -p \*Test.py -t . + +.PHONY : tests-par +tests-par: + @if ! command -v unittest-parallel >/dev/null 2>&1; then \ + echo "unittest-parallel not found. Please install it with:"; \ + echo " pip install unittest-parallel"; \ + exit 1; \ + fi + unittest-parallel --module-fixtures -vs tests/SpiffWorkflow -p \*Test.py -t . .PHONY : tests-cov tests-cov: diff --git a/tests/SpiffWorkflow/bpmn/data/event-gateway.bpmn b/tests/SpiffWorkflow/bpmn/data/event-gateway.bpmn new file mode 100644 index 000000000..afa986ba5 --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/data/event-gateway.bpmn @@ -0,0 +1,107 @@ + + + + + Flow_0w4b5t2 + + + + Flow_0w4b5t2 + Flow_0gge7fn + Flow_0px7ksu + Flow_1rfbrlf + + + Flow_0gge7fn + Flow_1g4g85l + + + + + Flow_0px7ksu + Flow_18v90rx + + + + + Flow_1rfbrlf + Flow_0mppjk9 + + timedelta(seconds=1) + + + + + Flow_0mppjk9 + + + + Flow_1g4g85l + + + + Flow_18v90rx + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SpiffWorkflow/bpmn/data/multiple-start-parallel.bpmn b/tests/SpiffWorkflow/bpmn/data/multiple-start-parallel.bpmn new file mode 100644 index 000000000..453dde30c --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/data/multiple-start-parallel.bpmn @@ -0,0 +1,43 @@ + + + + + Flow_1tr2mqr + + + + + Flow_1tr2mqr + Flow_1qjctmo + + + + Flow_1qjctmo + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SpiffWorkflow/bpmn/data/multiple-start.bpmn b/tests/SpiffWorkflow/bpmn/data/multiple-start.bpmn new file mode 100644 index 000000000..e9deb9b0f --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/data/multiple-start.bpmn @@ -0,0 +1,43 @@ + + + + + Flow_1tr2mqr + + + + + Flow_1tr2mqr + Flow_1qjctmo + + + + Flow_1qjctmo + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SpiffWorkflow/bpmn/data/multiple-throw-start.bpmn b/tests/SpiffWorkflow/bpmn/data/multiple-throw-start.bpmn new file mode 100644 index 000000000..a70bb6337 --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/data/multiple-throw-start.bpmn @@ -0,0 +1,88 @@ + + + + + + + + + + + Flow_04uk4n8 + + + + + Flow_08al33k + + + Flow_04uk4n8 + Flow_08al33k + + + + + + + Flow_1wgdi4h + + + + + Flow_1wxjn4e + + + Flow_1wgdi4h + Flow_1wxjn4e + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SpiffWorkflow/bpmn/data/multiple-throw.bpmn b/tests/SpiffWorkflow/bpmn/data/multiple-throw.bpmn new file mode 100644 index 000000000..721f54a80 --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/data/multiple-throw.bpmn @@ -0,0 +1,87 @@ + + + + + + + + + + + Flow_1tr2mqr + + + + Flow_1wohnl8 + Flow_1tr2mqr + + + + + Flow_1wohnl8 + + + + + + Flow_1wgdi4h + + + + + Flow_1wxjn4e + + + Flow_1wgdi4h + Flow_1wxjn4e + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/SpiffWorkflow/bpmn/events/EventBasedGatewayTest.py b/tests/SpiffWorkflow/bpmn/events/EventBasedGatewayTest.py new file mode 100644 index 000000000..692f41943 --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/events/EventBasedGatewayTest.py @@ -0,0 +1,46 @@ +from datetime import timedelta + +from SpiffWorkflow.bpmn.workflow import BpmnWorkflow +from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine +from SpiffWorkflow.bpmn.specs.events.event_definitions import MessageEventDefinition +from SpiffWorkflow.task import TaskState + +from ..BpmnWorkflowTestCase import BpmnWorkflowTestCase + +class EventBsedGatewayTest(BpmnWorkflowTestCase): + + def setUp(self): + self.spec, self.subprocesses = self.load_workflow_spec('event-gateway.bpmn', 'Process_0pvx19v') + self.script_engine = PythonScriptEngine(default_globals={"timedelta": timedelta}) + self.workflow = BpmnWorkflow(self.spec, script_engine=self.script_engine) + + def testEventBasedGateway(self): + self.actual_test() + + def testEventBasedGatewaySaveRestore(self): + self.actual_test(True) + + def actual_test(self, save_restore=False): + + self.workflow.do_engine_steps() + waiting_tasks = self.workflow.get_waiting_tasks() + if save_restore: + self.save_restore() + self.workflow.script_engine = self.script_engine + self.assertEqual(len(waiting_tasks), 1) + self.workflow.catch(MessageEventDefinition('message_1')) + self.workflow.refresh_waiting_tasks() + self.workflow.do_engine_steps() + self.assertEqual(self.workflow.is_completed(), True) + self.assertEqual(self.workflow.get_tasks_from_spec_name('message_1_event')[0].state, TaskState.COMPLETED) + self.assertEqual(self.workflow.get_tasks_from_spec_name('message_2_event')[0].state, TaskState.CANCELLED) + self.assertEqual(self.workflow.get_tasks_from_spec_name('timer_event')[0].state, TaskState.CANCELLED) + + def testMultipleStart(self): + spec, subprocess = self.load_workflow_spec('multiple-start-parallel.bpmn', 'main') + workflow = BpmnWorkflow(spec) + workflow.do_engine_steps() + workflow.catch(MessageEventDefinition('message_1')) + workflow.catch(MessageEventDefinition('message_2')) + workflow.refresh_waiting_tasks() + workflow.do_engine_steps() diff --git a/tests/SpiffWorkflow/bpmn/events/MultipleCatchEventTest.py b/tests/SpiffWorkflow/bpmn/events/MultipleCatchEventTest.py new file mode 100644 index 000000000..791b7bd54 --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/events/MultipleCatchEventTest.py @@ -0,0 +1,81 @@ +from SpiffWorkflow.bpmn.workflow import BpmnWorkflow +from SpiffWorkflow.bpmn.specs.events.event_definitions import MessageEventDefinition + +from ..BpmnWorkflowTestCase import BpmnWorkflowTestCase + + +class MultipleStartEventTest(BpmnWorkflowTestCase): + + def setUp(self): + self.spec, self.subprocesses = self.load_workflow_spec('multiple-start.bpmn', 'main') + self.workflow = BpmnWorkflow(self.spec) + + def testMultipleStartEvent(self): + self.actual_test() + + def testMultipleStartEventSaveRestore(self): + self.actual_test(True) + + def actual_test(self, save_restore=False): + + self.workflow.do_engine_steps() + waiting_tasks = self.workflow.get_waiting_tasks() + + if save_restore: + self.save_restore() + + # The start event should be waiting + self.assertEqual(len(waiting_tasks), 1) + self.assertEqual(waiting_tasks[0].task_spec.name, 'StartEvent_1') + + self.workflow.catch(MessageEventDefinition('message_1')) + self.workflow.refresh_waiting_tasks() + self.workflow.do_engine_steps() + + # Now the first task should be ready + ready_tasks = self.workflow.get_ready_user_tasks() + self.assertEqual(len(ready_tasks), 1) + self.assertEqual(ready_tasks[0].task_spec.name, 'any_task') + + +class ParallelStartEventTest(BpmnWorkflowTestCase): + + def setUp(self): + self.spec, self.subprocesses = self.load_workflow_spec('multiple-start-parallel.bpmn', 'main') + self.workflow = BpmnWorkflow(self.spec) + + def testParallelStartEvent(self): + self.actual_test() + + def testParallelStartEventSaveRestore(self): + self.actual_test(True) + + def actual_test(self, save_restore=False): + + self.workflow.do_engine_steps() + waiting_tasks = self.workflow.get_waiting_tasks() + + if save_restore: + self.save_restore() + + # The start event should be waiting + self.assertEqual(len(waiting_tasks), 1) + self.assertEqual(waiting_tasks[0].task_spec.name, 'StartEvent_1') + + self.workflow.catch(MessageEventDefinition('message_1')) + self.workflow.refresh_waiting_tasks() + self.workflow.do_engine_steps() + + # It should still be waiting because it has to receive both messages + waiting_tasks = self.workflow.get_waiting_tasks() + self.assertEqual(len(waiting_tasks), 1) + self.assertEqual(waiting_tasks[0].task_spec.name, 'StartEvent_1') + + self.workflow.catch(MessageEventDefinition('message_2')) + self.workflow.refresh_waiting_tasks() + self.workflow.do_engine_steps() + + # Now the first task should be ready + ready_tasks = self.workflow.get_ready_user_tasks() + self.assertEqual(len(ready_tasks), 1) + self.assertEqual(ready_tasks[0].task_spec.name, 'any_task') \ No newline at end of file diff --git a/tests/SpiffWorkflow/bpmn/events/MultipleThrowEventTest.py b/tests/SpiffWorkflow/bpmn/events/MultipleThrowEventTest.py new file mode 100644 index 000000000..087951eb3 --- /dev/null +++ b/tests/SpiffWorkflow/bpmn/events/MultipleThrowEventTest.py @@ -0,0 +1,47 @@ +from SpiffWorkflow.bpmn.workflow import BpmnWorkflow + +from ..BpmnWorkflowTestCase import BpmnWorkflowTestCase + + +class MultipleThrowEventIntermediateCatchTest(BpmnWorkflowTestCase): + + def setUp(self): + self.spec, subprocesses = self.load_collaboration('multiple-throw.bpmn','top') + self.workflow = BpmnWorkflow(self.spec, subprocesses) + + def testMultipleThrowEventIntermediateCatch(self): + self.actual_test() + + def testMultipleThrowEventIntermediateCatchSaveRestore(self): + self.actual_test(True) + + def actual_test(self, save_restore=False): + if save_restore: + self.save_restore() + self.workflow.do_engine_steps() + self.assertEqual(len(self.workflow.get_waiting_tasks()), 0) + self.assertEqual(self.workflow.is_completed(), True) + + +class MultipleThrowEventStartsEventTest(BpmnWorkflowTestCase): + + def setUp(self): + specs = self.get_all_specs('multiple-throw-start.bpmn') + self.spec = specs.pop('initiate') + self.workflow = BpmnWorkflow(self.spec, specs) + + def testMultipleThrowEventStartEvent(self): + self.actual_test() + + def testMultipleThrowEventStartEventSaveRestore(self): + self.actual_test(True) + + def actual_test(self, save_restore=False): + if save_restore: + self.save_restore() + self.workflow.do_engine_steps() + ready_tasks = self.workflow.get_ready_user_tasks() + self.assertEqual(len(ready_tasks), 1) + ready_tasks[0].complete() + self.workflow.do_engine_steps() + self.assertEqual(self.workflow.is_completed(), True) \ No newline at end of file diff --git a/tests/SpiffWorkflow/dmn/HitPolicyTest.py b/tests/SpiffWorkflow/dmn/HitPolicyTest.py index a7503732a..061ba660e 100644 --- a/tests/SpiffWorkflow/dmn/HitPolicyTest.py +++ b/tests/SpiffWorkflow/dmn/HitPolicyTest.py @@ -3,6 +3,8 @@ import unittest from SpiffWorkflow.dmn.engine.DMNEngine import DMNEngine from SpiffWorkflow.dmn.parser.BpmnDmnParser import BpmnDmnParser +from SpiffWorkflow.dmn.serializer.task_spec_converters import \ + BusinessRuleTaskConverter from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase from tests.SpiffWorkflow.dmn.DecisionRunner import DecisionRunner from tests.SpiffWorkflow.dmn.python_engine.PythonDecisionRunner import \ @@ -27,7 +29,18 @@ class HitPolicyTest(BpmnWorkflowTestCase): self.assertEqual('COLLECT', decision_table.hit_policy) res = runner.result({'type': 'stooge'}) self.assertEqual(4, len(res['name'])) + res = runner.result({'type': 'farmer'}) + self.assertEqual(1, len(res['name'])) + self.assertEqual('Elmer Fudd', res['name'][0]) + def testSerializeHitPolicy(self): + file_name = os.path.join(os.path.dirname(__file__), 'data', 'collect_hit.dmn') + runner = PythonDecisionRunner(file_name) + decision_table = runner.decision_table + self.assertEqual("COLLECT", decision_table.hit_policy) + dict = BusinessRuleTaskConverter().decision_table_to_dict(decision_table) + new_table = BusinessRuleTaskConverter().decision_table_from_dict(dict) + self.assertEqual("COLLECT", new_table.hit_policy) def suite(): return unittest.TestLoader().loadTestsFromTestCase(HitPolicyTest) diff --git a/tests/SpiffWorkflow/specs/ExecuteTest.py b/tests/SpiffWorkflow/specs/ExecuteTest.py index fc16db931..05653e185 100644 --- a/tests/SpiffWorkflow/specs/ExecuteTest.py +++ b/tests/SpiffWorkflow/specs/ExecuteTest.py @@ -3,9 +3,7 @@ import os -import sys import unittest -sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..')) from tests.SpiffWorkflow.util import run_workflow from .TaskSpecTest import TaskSpecTest @@ -25,7 +23,8 @@ class ExecuteTest(TaskSpecTest): args=self.cmd_args) def setUp(self): - self.cmd_args = ["python", "ExecuteProcessMock.py"] + script_path = os.path.join(os.path.dirname(__file__), '..', 'ExecuteProcessMock.py') + self.cmd_args = ["python", script_path] TaskSpecTest.setUp(self) def testConstructor(self):