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):