diff --git a/doc/errors.rst b/doc/errors.rst
new file mode 100644
index 00000000..31c606de
--- /dev/null
+++ b/doc/errors.rst
@@ -0,0 +1,90 @@
+SpiffWorkflow Exceptions
+====================================
+Details about the exceptions and exception hierarchy within SpiffWorkflow
+
+SpiffWorkflowException
+----------
+Base exception for all exceptions raised by SpiffWorkflow
+
+ValidationException
+----------
+
+**Extends**
+SpiffWorkflowException
+
+Thrown during the parsing of a workflow.
+
+**Attributes/Methods**
+
+- **tag**: The type of xml tag being parsed
+- **id**: the id attribute of the xml tag, if available.
+- **name**: the name attribute of the xml tag, if available.
+- **line_number**: the line number where the tag occurs.
+- **file_name**: The name of the file where the error occurred.
+- **message**: a human readable error message.
+
+
+WorkflowException
+--------
+When an error occurs with a Task Specification (maybe should have been called
+a SpecException)
+
+**Extends**
+SpiffWorkflowException
+
+**Attributes/Methods**
+
+- **sender**: The TaskSpec - the specific Task, Gateway, etc... that caused the error to happen.
+- **error**: a human readable error message describing the problem.
+- **get_task_trace**: Provided a specific Task, will work it's way through the workflow / sub-processes
+and call activities to show where an error occurred. Useful if the error happened within a deeply nested structure (where call activities include call activities ....)
+
+WorkflowDataException
+------------------
+When an exception occurs moving data between tasks and Data Objects (including
+data inputs and data outputs.)
+
+**Extends**
+WorkflowException
+
+**Attributes/Methods**
+
+(in addition to the values in a WorkflowException)
+
+ - **task**: The specific task (not the task spec, but the actual executing task)
+ - **data_input**: The spec of the input variable
+ - **data_output**: The spec of the output variable
+
+WorkflowTaskException
+--------
+**Extends**
+WorkflowException
+
+**Attributes/Methods**
+
+(in addition to the values in a WorkflowException)
+
+ - **task**: The specific task (not the task spec, but the actual executing task)
+ - **error_msg**: The detailed human readable message. (conflicts with error above)
+ - **exception**: The original exception this wraps around.
+ - **line_number** The line number that contains the error
+ - **offset** The point in the line that caused the error
+ - **error_line** The content of the line that caused the error.
+
+It will accept the line_number and error_line as arguments - if the
+underlying error provided is a SyntaxError it will try to derive this
+information from the error.
+If this is a name error, it will attempt to calculate a did-you-mean
+error_msg.
+
+Unused / Deprecated errors
+--------------------
+
+** StorageException **
+Deprecated -- Used only by the PrettyXmlSerializer - which is not under active
+support.
+
+** DeadMethodCalled **
+Something related to WeakMethod -- which doesn't look to be utilized anymore.
+
+
diff --git a/graphics/spiffworkflow_logo_ideas.svg b/graphics/spiffworkflow_logo_ideas.svg
index 28e5d8ac..b51b8b52 100644
--- a/graphics/spiffworkflow_logo_ideas.svg
+++ b/graphics/spiffworkflow_logo_ideas.svg
@@ -26,13 +26,13 @@
showgrid="false"
showguides="true"
inkscape:guide-bbox="true"
- inkscape:zoom="0.27433373"
- inkscape:cx="-586.87643"
- inkscape:cy="1882.7433"
+ inkscape:zoom="1.5518659"
+ inkscape:cx="2265.0153"
+ inkscape:cy="3541.2209"
inkscape:window-width="1916"
- inkscape:window-height="1076"
+ inkscape:window-height="916"
inkscape:window-x="0"
- inkscape:window-y="0"
+ inkscape:window-y="162"
inkscape:window-maximized="1"
inkscape:current-layer="layer1">
+
+
+
@@ -839,6 +851,91 @@
x="-580.08496"
y="716.69928">Draw the code
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Draw the code
+
+
+
+
+
diff --git a/tests/SpiffWorkflow/bpmn/ApprovalsTest.py b/tests/SpiffWorkflow/bpmn/ApprovalsTest.py
index 7576a23f..857c81f0 100644
--- a/tests/SpiffWorkflow/bpmn/ApprovalsTest.py
+++ b/tests/SpiffWorkflow/bpmn/ApprovalsTest.py
@@ -2,7 +2,6 @@
import unittest
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
-from SpiffWorkflow.bpmn.specs.events.event_definitions import MessageEventDefinition
from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase
__author__ = 'matth'
@@ -86,8 +85,7 @@ class ApprovalsTest(BpmnWorkflowTestCase):
self.save_restore()
self.do_next_named_step('Parallel_Approvals_SP.Manager_Approval')
self.do_next_exclusive_step('Parallel_Approvals_SP.Step1')
- self.do_next_exclusive_step(
- 'Parallel_Approvals_SP.Supervisor_Approval')
+ self.do_next_exclusive_step('Parallel_Approvals_SP.Supervisor_Approval')
self.do_next_exclusive_step('Approvals.Parallel_SP_Done')
def testSaveRestoreWaiting(self):
@@ -108,93 +106,10 @@ class ApprovalsTest(BpmnWorkflowTestCase):
self.save_restore()
self.do_next_exclusive_step('Parallel_Approvals_SP.Step1')
self.save_restore()
- self.do_next_exclusive_step(
- 'Parallel_Approvals_SP.Supervisor_Approval')
+ self.do_next_exclusive_step('Parallel_Approvals_SP.Supervisor_Approval')
self.save_restore()
self.do_next_exclusive_step('Approvals.Parallel_SP_Done')
- def testReadonlyWaiting(self):
-
- self.do_next_named_step('First_Approval_Wins.Manager_Approval')
-
- readonly = self.get_read_only_workflow()
- self.assertEqual(1, len(readonly.get_ready_user_tasks()))
- self.assertEqual('Approvals.First_Approval_Wins_Done',
- readonly.get_ready_user_tasks()[0].task_spec.name)
- self.assertRaises(AssertionError, readonly.do_engine_steps)
- self.assertRaises(AssertionError, readonly.refresh_waiting_tasks)
- self.assertRaises(AssertionError, readonly.catch, MessageEventDefinition('Cheese'))
- self.assertRaises(
- AssertionError, readonly.get_ready_user_tasks()[0].complete)
-
- self.do_next_exclusive_step('Approvals.First_Approval_Wins_Done')
-
- readonly = self.get_read_only_workflow()
- self.assertEqual(2, len(readonly.get_ready_user_tasks()))
- self.assertEqual(
- ['Approvals.Manager_Approval__P_',
- 'Approvals.Supervisor_Approval__P_'],
- sorted(t.task_spec.name for t in readonly.get_ready_user_tasks()))
- self.assertRaises(
- AssertionError, readonly.get_ready_user_tasks()[0].complete)
-
- self.do_next_named_step('Approvals.Supervisor_Approval__P_')
-
- readonly = self.get_read_only_workflow()
- self.assertEqual(1, len(readonly.get_ready_user_tasks()))
- self.assertEqual('Approvals.Manager_Approval__P_',
- readonly.get_ready_user_tasks()[0].task_spec.name)
- self.assertRaises(
- AssertionError, readonly.get_ready_user_tasks()[0].complete)
- self.do_next_named_step('Approvals.Manager_Approval__P_')
-
- readonly = self.get_read_only_workflow()
- self.assertEqual(1, len(readonly.get_ready_user_tasks()))
- self.assertEqual('Approvals.Parallel_Approvals_Done',
- readonly.get_ready_user_tasks()[0].task_spec.name)
- self.assertRaises(
- AssertionError, readonly.get_ready_user_tasks()[0].complete)
- self.do_next_exclusive_step('Approvals.Parallel_Approvals_Done')
-
- readonly = self.get_read_only_workflow()
- self.assertEqual(2, len(readonly.get_ready_user_tasks()))
- self.assertEqual(
- ['Parallel_Approvals_SP.Manager_Approval',
- 'Parallel_Approvals_SP.Step1'],
- sorted(t.task_spec.name for t in readonly.get_ready_user_tasks()))
- self.assertRaises(
- AssertionError, readonly.get_ready_user_tasks()[0].complete)
- self.do_next_named_step('Parallel_Approvals_SP.Manager_Approval')
-
- readonly = self.get_read_only_workflow()
- self.assertEqual(1, len(readonly.get_ready_user_tasks()))
- self.assertEqual('Parallel_Approvals_SP.Step1',
- readonly.get_ready_user_tasks()[0].task_spec.name)
- self.assertRaises(
- AssertionError, readonly.get_ready_user_tasks()[0].complete)
- self.do_next_exclusive_step('Parallel_Approvals_SP.Step1')
-
- readonly = self.get_read_only_workflow()
- self.assertEqual(1, len(readonly.get_ready_user_tasks()))
- self.assertEqual('Parallel_Approvals_SP.Supervisor_Approval',
- readonly.get_ready_user_tasks()[0].task_spec.name)
- self.assertRaises(
- AssertionError, readonly.get_ready_user_tasks()[0].complete)
- self.do_next_exclusive_step(
- 'Parallel_Approvals_SP.Supervisor_Approval')
-
- readonly = self.get_read_only_workflow()
- self.assertEqual(1, len(readonly.get_ready_user_tasks()))
- self.assertEqual('Approvals.Parallel_SP_Done',
- readonly.get_ready_user_tasks()[0].task_spec.name)
- self.assertRaises(
- AssertionError, readonly.get_ready_user_tasks()[0].complete)
- self.do_next_exclusive_step('Approvals.Parallel_SP_Done')
-
- readonly = self.get_read_only_workflow()
- self.assertEqual(0, len(readonly.get_ready_user_tasks()))
- self.assertEqual(0, len(readonly.get_waiting_tasks()))
-
def suite():
return unittest.TestLoader().loadTestsFromTestCase(ApprovalsTest)
diff --git a/tests/SpiffWorkflow/bpmn/BpmnSerializerTest.py b/tests/SpiffWorkflow/bpmn/BpmnSerializerTest.py
deleted file mode 100644
index a8b6ebd5..00000000
--- a/tests/SpiffWorkflow/bpmn/BpmnSerializerTest.py
+++ /dev/null
@@ -1,118 +0,0 @@
-import os
-import unittest
-
-from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine
-from SpiffWorkflow.bpmn.serializer.BpmnSerializer import BpmnSerializer
-from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
-from .BpmnLoaderForTests import TestBpmnParser
-
-
-class BpmnSerializerTest(unittest.TestCase):
- CORRELATE = BpmnSerializer
-
- def load_workflow_spec(self, filename, process_name):
- f = os.path.join(os.path.dirname(__file__), 'data', filename)
- parser = TestBpmnParser()
- parser.add_bpmn_files_by_glob(f)
- top_level_spec = parser.get_spec(process_name)
- subprocesses = parser.get_subprocess_specs(process_name)
- return top_level_spec, subprocesses
-
- def setUp(self):
- super(BpmnSerializerTest, self).setUp()
- self.serializer = BpmnSerializer()
- self.spec, subprocesses = self.load_workflow_spec('random_fact.bpmn', 'random_fact')
- self.workflow = BpmnWorkflow(self.spec, subprocesses)
-
- def testDeserializeWorkflowSpec(self):
- self.assertIsNotNone(self.spec)
-
- def testSerializeWorkflowSpec(self):
- spec_serialized = self.serializer.serialize_workflow_spec(self.spec)
- result = self.serializer.deserialize_workflow_spec(spec_serialized)
- spec_serialized2 = self.serializer.serialize_workflow_spec(result)
- self.assertEqual(spec_serialized, spec_serialized2)
-
- def testSerializeWorkflow(self):
- json = self.serializer.serialize_workflow(self.workflow)
- print(json)
-
- def testDeserializeWorkflow(self):
- self._compare_with_deserialized_copy(self.workflow)
-
- def testDeserializeCallActivityChildren(self):
- """Tested as a part of deserialize workflow."""
- pass
-
- def testSerializeTask(self):
- json = self.serializer.serialize_workflow(self.workflow)
- print(json)
-
- def testDeserializeTask(self):
- self._compare_with_deserialized_copy(self.workflow)
-
- def testDeserializeActiveWorkflow(self):
- self.workflow.do_engine_steps()
- self._compare_with_deserialized_copy(self.workflow)
-
- def testDeserializeWithData(self):
- self.workflow.data["test"] = "my_test"
- json = self.serializer.serialize_workflow(self.workflow)
- wf2 = self.serializer.deserialize_workflow(json, workflow_spec=self.spec)
- self.assertEqual('my_test', wf2.get_data("test"))
-
- def testDeserializeWithDefaultScriptEngineClass(self):
- json = self.serializer.serialize_workflow(self.workflow)
- wf2 = self.serializer.deserialize_workflow(json, workflow_spec=self.spec)
- self.assertIsNotNone(self.workflow.script_engine)
- self.assertIsNotNone(wf2.script_engine)
- self.assertEqual(self.workflow.script_engine.__class__,
- wf2.script_engine.__class__)
-
- @unittest.skip("Deserialize does not persist the script engine, Fix me.")
- def testDeserializeWithCustomScriptEngine(self):
- class CustomScriptEngine(PythonScriptEngine):
- pass
-
- self.workflow.script_engine = CustomScriptEngine()
- json = self.serializer.serialize_workflow(self.workflow)
- wf2 = self.serializer.deserialize_workflow(json, workflow_spec=self.spec)
- self.assertEqual(self.workflow.script_engine.__class__,
- wf2.script_engine.__class__)
-
- def testDeserializeWithDataOnTask(self):
- self.workflow.do_engine_steps()
- user_task = self.workflow.get_ready_user_tasks()[0]
- user_task.data = {"test":"my_test"}
- self._compare_with_deserialized_copy(self.workflow)
-
- def testLastTaskIsSetAndWorksThroughRestore(self):
- self.workflow.do_engine_steps()
- json = self.serializer.serialize_workflow(self.workflow)
- wf2 = self.serializer.deserialize_workflow(json, workflow_spec=self.spec)
- self.assertIsNotNone(self.workflow.last_task)
- self.assertIsNotNone(wf2.last_task)
- self._compare_workflows(self.workflow, wf2)
-
- def _compare_with_deserialized_copy(self, wf):
- json = self.serializer.serialize_workflow(wf)
- wf2 = self.serializer.deserialize_workflow(json, workflow_spec=self.spec)
- self._compare_workflows(wf, wf2)
-
- def _compare_workflows(self, w1, w2):
- self.assertIsInstance(w1, BpmnWorkflow)
- self.assertIsInstance(w2, BpmnWorkflow)
- self.assertEqual(w1.data, w2.data)
- self.assertEqual(w1.name, w2.name)
- for task in w1.get_ready_user_tasks():
- w2_task = w2.get_task(task.id)
- self.assertIsNotNone(w2_task)
- self.assertEqual(task.data, w2_task.data)
-
-
-def suite():
- return unittest.TestLoader().loadTestsFromTestCase(BpmnSerializerTest)
-
-
-if __name__ == '__main__':
- unittest.TextTestRunner(verbosity=2).run(suite())
diff --git a/tests/SpiffWorkflow/bpmn/BpmnWorkflowSerializerTest.py b/tests/SpiffWorkflow/bpmn/BpmnWorkflowSerializerTest.py
index ac2ae463..e5b77156 100644
--- a/tests/SpiffWorkflow/bpmn/BpmnWorkflowSerializerTest.py
+++ b/tests/SpiffWorkflow/bpmn/BpmnWorkflowSerializerTest.py
@@ -1,13 +1,11 @@
import os
import unittest
import json
-from uuid import uuid4
from SpiffWorkflow.task import TaskState
from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine
from SpiffWorkflow.bpmn.parser.BpmnParser import BpmnParser
from SpiffWorkflow.bpmn.serializer.workflow import BpmnWorkflowSerializer
-from SpiffWorkflow.bpmn.serializer.BpmnSerializer import BpmnSerializer
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
from tests.SpiffWorkflow.bpmn.BpmnLoaderForTests import TestUserTaskConverter
@@ -48,13 +46,6 @@ class BpmnWorkflowSerializerTest(unittest.TestCase):
version = self.serializer.get_version(spec_serialized)
self.assertEqual(version, self.SERIALIZER_VERSION)
- def testSerializeToOldSerializerThenNewSerializer(self):
- old_serializer = BpmnSerializer()
- old_json = old_serializer.serialize_workflow(self.workflow)
- new_workflow = old_serializer.deserialize_workflow(old_json)
- new_json = self.serializer.serialize_json(new_workflow)
- new_workflow_2 = self.serializer.deserialize_json(new_json)
-
def testSerializeWorkflow(self):
serialized = self.serializer.serialize_json(self.workflow)
json.loads(serialized)
diff --git a/tests/SpiffWorkflow/bpmn/BpmnWorkflowTestCase.py b/tests/SpiffWorkflow/bpmn/BpmnWorkflowTestCase.py
index 9b7865bd..8f2f0af5 100644
--- a/tests/SpiffWorkflow/bpmn/BpmnWorkflowTestCase.py
+++ b/tests/SpiffWorkflow/bpmn/BpmnWorkflowTestCase.py
@@ -122,7 +122,7 @@ class BpmnWorkflowTestCase(unittest.TestCase):
before_dump = self.workflow.get_dump()
# Check that we can actully convert this to JSON
json_str = json.dumps(before_state)
- after = self.serializer.workflow_from_dict(json.loads(json_str), read_only=False)
+ after = self.serializer.workflow_from_dict(json.loads(json_str))
# Check that serializing and deserializing results in the same workflow
after_state = self.serializer.workflow_to_dict(after)
after_dump = after.get_dump()
@@ -132,11 +132,7 @@ class BpmnWorkflowTestCase(unittest.TestCase):
self.workflow = after
def restore(self, state):
- self.workflow = self.serializer.workflow_from_dict(state, read_only=False)
-
- def get_read_only_workflow(self):
- state = self._get_workflow_state()
- return self.serializer.workflow_from_dict(state, read_only=True)
+ self.workflow = self.serializer.workflow_from_dict(state)
def _get_workflow_state(self, do_steps=True):
if do_steps:
diff --git a/tests/SpiffWorkflow/bpmn/CallActivityEndEventTest.py b/tests/SpiffWorkflow/bpmn/CallActivityEndEventTest.py
index f3d1522d..1e3d158e 100644
--- a/tests/SpiffWorkflow/bpmn/CallActivityEndEventTest.py
+++ b/tests/SpiffWorkflow/bpmn/CallActivityEndEventTest.py
@@ -3,9 +3,9 @@
import unittest
from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine
-from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
+from SpiffWorkflow.exceptions import WorkflowTaskException
from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase
__author__ = 'kellym'
@@ -60,7 +60,7 @@ class CallActivityTest(BpmnWorkflowTestCase):
def test_call_acitivity_errors_include_task_trace(self):
error_spec = self.subprocesses.get('ErroringBPMN')
error_spec, subprocesses = self.load_workflow_spec('call_activity_*.bpmn', 'ErroringBPMN')
- with self.assertRaises(WorkflowTaskExecException) as context:
+ with self.assertRaises(WorkflowTaskException) as context:
self.workflow = BpmnWorkflow(error_spec, subprocesses)
self.workflow.do_engine_steps()
self.assertEquals(2, len(context.exception.task_trace))
diff --git a/tests/SpiffWorkflow/bpmn/CustomScriptTest.py b/tests/SpiffWorkflow/bpmn/CustomScriptTest.py
index 12f69a2a..8cbca47f 100644
--- a/tests/SpiffWorkflow/bpmn/CustomScriptTest.py
+++ b/tests/SpiffWorkflow/bpmn/CustomScriptTest.py
@@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
import unittest
+from SpiffWorkflow.exceptions import WorkflowTaskException
from SpiffWorkflow.task import TaskState
from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
-from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException
from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase
__author__ = 'McDonald, danfunk'
@@ -46,7 +46,7 @@ class CustomInlineScriptTest(BpmnWorkflowTestCase):
def test_overwrite_function_with_local_variable(self):
ready_task = self.workflow.get_tasks(TaskState.READY)[0]
ready_task.data = {'custom_function': "bill"}
- with self.assertRaises(WorkflowTaskExecException) as e:
+ with self.assertRaises(WorkflowTaskException) as e:
self.workflow.do_engine_steps()
self.assertTrue('' in str(e.exception))
self.assertTrue('custom_function' in str(e.exception))
diff --git a/tests/SpiffWorkflow/bpmn/InvalidWorkflowsTest.py b/tests/SpiffWorkflow/bpmn/InvalidWorkflowsTest.py
index ffb8f024..9987567a 100644
--- a/tests/SpiffWorkflow/bpmn/InvalidWorkflowsTest.py
+++ b/tests/SpiffWorkflow/bpmn/InvalidWorkflowsTest.py
@@ -31,18 +31,11 @@ class InvalidWorkflowsTest(BpmnWorkflowTestCase):
except ValidationException as ex:
self.assertTrue('No start event found' in ('%r' % ex),
'\'No start event found\' should be a substring of error message: \'%r\'' % ex)
- self.assertTrue('No-Start-Event.bpmn20.xml' in ('%r' % ex),
+ self.assertTrue('No-Start-Event.bpmn20.xml' in ex.file_name,
'\'No-Start-Event.bpmn20.xml\' should be a substring of error message: \'%r\'' % ex)
- self.assertTrue('process' in ('%r' % ex),
- '\'process\' should be a substring of error message: \'%r\'' % ex)
- self.assertTrue(
- 'sid-669ddebf-4196-41ee-8b04-bcc90bc5f983' in ('%r' % ex),
- '\'sid-669ddebf-4196-41ee-8b04-bcc90bc5f983\' should be a substring of error message: \'%r\'' % ex)
- self.assertTrue('No Start Event' in ('%r' % ex),
- '\'No Start Event\' should be a substring of error message: \'%r\'' % ex)
def testSubprocessNotFound(self):
-
+
with self.assertRaises(ValidationException) as exc:
self.load_workflow_spec('Invalid-Workflows/Subprocess-Not-Found.bpmn20.xml', 'Subprocess Not Found')
self.assertIn("The process 'Missing subprocess' was not found.", str(exc))
@@ -60,15 +53,12 @@ class InvalidWorkflowsTest(BpmnWorkflowTestCase):
'There is no support implemented for this task type' in (
'%r' % ex),
'\'There is no support implemented for this task type\' should be a substring of error message: \'%r\'' % ex)
- self.assertTrue('Unsupported-Task.bpmn20.xml' in ('%r' % ex),
+ self.assertTrue('Unsupported-Task.bpmn20.xml' in ex.file_name,
'\'Unsupported-Task.bpmn20.xml\' should be a substring of error message: \'%r\'' % ex)
- self.assertTrue('businessRuleTask' in ('%r' % ex),
- '\'businessRuleTask\' should be a substring of error message: \'%r\'' % ex)
- self.assertTrue(
- 'sid-75EEAB28-3B69-4282-B91A-0F3C97931834' in ('%r' % ex),
- '\'sid-75EEAB28-3B69-4282-B91A-0F3C97931834\' should be a substring of error message: \'%r\'' % ex)
- self.assertTrue('Business Rule Task' in ('%r' % ex),
- '\'Business Rule Task\' should be a substring of error message: \'%r\'' % ex)
+ self.assertTrue('businessRuleTask' in ex.tag,
+ '\'businessRuleTask\' should be a substring of the tag: \'%r\'' % ex)
+ self.assertTrue('Business Rule Task' in ex.name,
+ '\'Business Rule Task\' should be the name: \'%s\'' % ex.name)
def suite():
diff --git a/tests/SpiffWorkflow/bpmn/ParserTest.py b/tests/SpiffWorkflow/bpmn/ParserTest.py
index 5703273e..59a32775 100644
--- a/tests/SpiffWorkflow/bpmn/ParserTest.py
+++ b/tests/SpiffWorkflow/bpmn/ParserTest.py
@@ -1,7 +1,8 @@
import unittest
import os
-from SpiffWorkflow.bpmn.parser.BpmnParser import BpmnParser
+from SpiffWorkflow.bpmn.parser.BpmnParser import BpmnParser, BpmnValidator
+from SpiffWorkflow.bpmn.parser.ValidationException import ValidationException
class ParserTest(unittest.TestCase):
@@ -27,3 +28,17 @@ class ParserTest(unittest.TestCase):
self.assertEqual(generate.data_output_associations[0].name, 'obj_1')
self.assertEqual(len(read.data_input_associations), 1)
self.assertEqual(read.data_input_associations[0].name, 'obj_1')
+
+ def testValidatorError(self):
+ parser = BpmnParser(validator=BpmnValidator())
+ bpmn_file = os.path.join(os.path.dirname(__file__), 'data',
+ 'data_object_invalid.bpmn')
+ errored = False
+ try:
+ parser.add_bpmn_file(bpmn_file)
+ except ValidationException as ex:
+ errored = True
+ self.assertEqual(ex.file_name, bpmn_file)
+ self.assertEqual(14, ex.line_number)
+ self.assertIn('DataObjectReference_0cm8dnh', str(ex))
+ assert(errored, "This should have errored out with a validation exception.")
diff --git a/tests/SpiffWorkflow/bpmn/ScriptTest.py b/tests/SpiffWorkflow/bpmn/ScriptTest.py
index efe9f1c8..da0a4a29 100644
--- a/tests/SpiffWorkflow/bpmn/ScriptTest.py
+++ b/tests/SpiffWorkflow/bpmn/ScriptTest.py
@@ -2,7 +2,7 @@
import unittest
-from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException
+from SpiffWorkflow.exceptions import WorkflowTaskException
from SpiffWorkflow.task import TaskState
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase
@@ -39,7 +39,7 @@ class InlineScriptTest(BpmnWorkflowTestCase):
# StartTask doesn't know about testvar, it happened earlier.
# calling an exec that references testvar, in the context of the
# start task should fail.
- with self.assertRaises(WorkflowTaskExecException):
+ with self.assertRaises(WorkflowTaskException):
result = self.workflow.script_engine.evaluate(startTask, 'testvar == True')
diff --git a/tests/SpiffWorkflow/bpmn/ServiceTaskTest.py b/tests/SpiffWorkflow/bpmn/ServiceTaskTest.py
index 29060708..a0112efe 100644
--- a/tests/SpiffWorkflow/bpmn/ServiceTaskTest.py
+++ b/tests/SpiffWorkflow/bpmn/ServiceTaskTest.py
@@ -8,16 +8,15 @@ sys.path.insert(0, os.path.join(dirname, '..', '..', '..'))
from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
-from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException
from tests.SpiffWorkflow.bpmn.BpmnWorkflowTestCase import BpmnWorkflowTestCase
class ServiceTaskTest(BpmnWorkflowTestCase):
def setUp(self):
- spec, subprocesses = self.load_workflow_spec('service_task.bpmn',
+ spec, subprocesses = self.load_workflow_spec('service_task.bpmn',
'service_task_example1')
- self.workflow = BpmnWorkflow(spec, subprocesses)
+ self.workflow = BpmnWorkflow(spec, subprocesses)
def testRunThroughHappy(self):
self.workflow.do_engine_steps()
diff --git a/tests/SpiffWorkflow/bpmn/data/data_object_invalid.bpmn b/tests/SpiffWorkflow/bpmn/data/data_object_invalid.bpmn
new file mode 100644
index 00000000..1d2d2ed8
--- /dev/null
+++ b/tests/SpiffWorkflow/bpmn/data/data_object_invalid.bpmn
@@ -0,0 +1,152 @@
+
+
+
+
+
+ Flow_18858hr
+
+
+
+
+
+
+
+
+
+ Flow_19pyf8s
+
+
+
+ Flow_1r7v9yo
+ Flow_1tnu3ej
+
+
+ DataObjectReference_0pztwm3
+ Property_1uusomz
+
+
+
+ Flow_18858hr
+ Flow_0gbxq9s
+
+ DataObjectReference_17fhr1j
+
+
+
+ Flow_0gbxq9s
+ Flow_1r7v9yo
+
+
+ Flow_1tnu3ej
+ Flow_19pyf8s
+
+
+ DataObjectReference_0cm8dnh
+ Property_1q5wp77
+
+
+ Flow_0yx8lkz
+
+
+ Flow_0yx8lkz
+ Flow_0rk4i35
+
+
+
+ Flow_0rk4i35
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/SpiffWorkflow/bpmn/serializer/dictTest.py b/tests/SpiffWorkflow/bpmn/serializer/dictTest.py
deleted file mode 100644
index 3556bee1..00000000
--- a/tests/SpiffWorkflow/bpmn/serializer/dictTest.py
+++ /dev/null
@@ -1,73 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from builtins import str
-import sys
-import unittest
-import os
-dirname = os.path.dirname(__file__)
-sys.path.insert(0, os.path.join(dirname, '..', '..', '..', '..'))
-
-import uuid
-from SpiffWorkflow.bpmn.serializer.dict import BPMNDictionarySerializer
-from tests.SpiffWorkflow.serializer.baseTest import SerializerTest
-from SpiffWorkflow.workflow import Workflow
-
-
-class BPMNDictionarySerializerTest(SerializerTest):
-
- def setUp(self):
- super(BPMNDictionarySerializerTest, self).setUp()
- self.serializer = BPMNDictionarySerializer()
- self.return_type = dict
-
- def _compare_results(self, item1, item2,
- exclude_dynamic=False,
- exclude_items=None):
- exclude_items = exclude_items if exclude_items is not None else []
- if exclude_dynamic:
- if 'last_state_change' not in exclude_items:
- exclude_items.append('last_state_change')
- if 'last_task' not in exclude_items:
- exclude_items.append('last_task')
- if uuid.UUID not in exclude_items:
- exclude_items.append(uuid.UUID)
- if type(item1) in exclude_items:
- return
-
- if isinstance(item1, dict):
- self.assertIsInstance(item2, dict)
- for key, value in list(item1.items()):
- self.assertIn(key, item2)
- if key in exclude_items:
- continue
- self._compare_results(value, item2[key],
- exclude_dynamic=exclude_dynamic,
- exclude_items=exclude_items)
- for key in item2:
- self.assertIn(key, item1)
-
- elif isinstance(item1, list):
- msg = "item is not a list (is a " + str(type(item2)) + ")"
- self.assertIsInstance(item2, list, msg)
- msg = "list lengths differ: {} vs {}".format(
- len(item1), len(item2))
- self.assertEqual(len(item1), len(item2), msg)
- for i, listitem in enumerate(item1):
- self._compare_results(listitem, item2[i],
- exclude_dynamic=exclude_dynamic,
- exclude_items=exclude_items)
-
- elif isinstance(item1, Workflow):
- raise Exception("Item is a Workflow")
-
- else:
- msg = "{}: types differ: {} vs {}".format(
- str(item2), type(item1), type(item2))
- self.assertEqual(type(item1), type(item2), msg)
- self.assertEqual(item1, item2)
-
-
-def suite():
- return unittest.defaultTestLoader.loadTestsFromTestCase(BPMNDictionarySerializerTest)
-if __name__ == '__main__':
- unittest.TextTestRunner(verbosity=2).run(suite())
diff --git a/tests/SpiffWorkflow/bpmn/serializer/jsonTest.py b/tests/SpiffWorkflow/bpmn/serializer/jsonTest.py
deleted file mode 100644
index 89ee0542..00000000
--- a/tests/SpiffWorkflow/bpmn/serializer/jsonTest.py
+++ /dev/null
@@ -1,38 +0,0 @@
-# -*- coding: utf-8 -*-
-
-import sys
-import unittest
-import os
-dirname = os.path.dirname(__file__)
-sys.path.insert(0, os.path.join(dirname, '..', '..', '..', '..'))
-
-import json
-from SpiffWorkflow.bpmn.serializer.json import BPMNJSONSerializer
-from tests.SpiffWorkflow.serializer.dictTest import DictionarySerializerTest
-
-
-class BPMNJSONSerializerTest(DictionarySerializerTest):
-
- def setUp(self):
- super(BPMNJSONSerializerTest, self).setUp()
- self.serializer = BPMNJSONSerializer()
- self.return_type = str
-
- def _prepare_result(self, item):
- return json.loads(item)
-
- def _compare_results(self, item1, item2, exclude_dynamic=False,
- exclude_items=None):
- if exclude_dynamic:
- exclude_items = ['__uuid__']
- else:
- exclude_items = []
- super(BPMNJSONSerializerTest, self)._compare_results(item1, item2,
- exclude_dynamic=exclude_dynamic,
- exclude_items=exclude_items)
-
-
-def suite():
- return unittest.defaultTestLoader.loadTestsFromTestCase(BPMNJSONSerializerTest)
-if __name__ == '__main__':
- unittest.TextTestRunner(verbosity=2).run(suite())
diff --git a/tests/SpiffWorkflow/camunda/InvalidBusinessRuleTaskParserTest.py b/tests/SpiffWorkflow/camunda/InvalidBusinessRuleTaskParserTest.py
index 3ca9f3d0..757767d6 100644
--- a/tests/SpiffWorkflow/camunda/InvalidBusinessRuleTaskParserTest.py
+++ b/tests/SpiffWorkflow/camunda/InvalidBusinessRuleTaskParserTest.py
@@ -1,7 +1,7 @@
import os
import unittest
-from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException
+from SpiffWorkflow.exceptions import SpiffWorkflowException, WorkflowException
from SpiffWorkflow.task import TaskState
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
@@ -15,17 +15,23 @@ class BusinessRuleTaskParserTest(BaseTestCase):
'invalid/InvalidDecision.bpmn', 'Process_1', 'invalid_decision.dmn')
self.workflow = BpmnWorkflow(self.spec)
+ def testExceptionPrint(self):
+ e1 = Exception("test 1")
+ print (e1)
+ e = SpiffWorkflowException("test")
+ print (e)
+
def testDmnRaisesTaskErrors(self):
self.workflow = BpmnWorkflow(self.spec)
self.workflow.get_tasks(TaskState.READY)[0].set_data(x=3)
try:
self.workflow.do_engine_steps()
self.assertTrue(False, "An error should have been raised.")
- except WorkflowTaskExecException as we:
+ except WorkflowException as we:
self.assertTrue(True, "An error was raised..")
- self.assertEquals("InvalidDecisionTaskId", we.sender.name)
- self.maxDiff = 1000
- self.assertEquals("Error evaluating expression spam= 1", str(we))
+ self.assertEqual("InvalidDecisionTaskId", we.task_spec.name)
+ self.maxDiff = 1000
+ self.assertEquals("Error evaluating expression 'spam= 1'. Rule failed on row 1. Business Rule Task 'Invalid Decision'.", str(we))
def suite():
return unittest.TestLoader().loadTestsFromTestCase(BusinessRuleTaskParserTest)
diff --git a/tests/SpiffWorkflow/camunda/data/DMNMultiInstance.bpmn b/tests/SpiffWorkflow/camunda/data/DMNMultiInstance.bpmn
index ddf2c44e..d00fd87d 100644
--- a/tests/SpiffWorkflow/camunda/data/DMNMultiInstance.bpmn
+++ b/tests/SpiffWorkflow/camunda/data/DMNMultiInstance.bpmn
@@ -1,5 +1,5 @@
-
+
Flow_1b29lxw
@@ -46,59 +46,59 @@ of documentation
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/SpiffWorkflow/camunda/data/dmn/test_integer_decision_multi.dmn b/tests/SpiffWorkflow/camunda/data/dmn/test_integer_decision_multi.dmn
index 7565b4c0..a24c8400 100644
--- a/tests/SpiffWorkflow/camunda/data/dmn/test_integer_decision_multi.dmn
+++ b/tests/SpiffWorkflow/camunda/data/dmn/test_integer_decision_multi.dmn
@@ -1,8 +1,8 @@
-
+
-
+
item.x
diff --git a/tests/SpiffWorkflow/camunda/specs/UserTaskSpecTest.py b/tests/SpiffWorkflow/camunda/specs/UserTaskSpecTest.py
index 33f62191..3de8fa2a 100644
--- a/tests/SpiffWorkflow/camunda/specs/UserTaskSpecTest.py
+++ b/tests/SpiffWorkflow/camunda/specs/UserTaskSpecTest.py
@@ -1,9 +1,7 @@
-import json
import unittest
-from SpiffWorkflow.camunda.specs.UserTask import FormField, UserTask, Form, \
- EnumFormField
-from SpiffWorkflow.specs.base import TaskSpec
+from SpiffWorkflow.camunda.specs.UserTask import FormField, UserTask, Form, EnumFormField
+from SpiffWorkflow.camunda.serializer.task_spec_converters import UserTaskConverter
from SpiffWorkflow.specs.WorkflowSpec import WorkflowSpec
@@ -13,7 +11,6 @@ class UserTaskSpecTest(unittest.TestCase):
def create_instance(self):
if 'testtask' in self.wf_spec.task_specs:
del self.wf_spec.task_specs['testtask']
- task_spec = TaskSpec(self.wf_spec, 'testtask', description='foo')
self.form = Form()
return UserTask(self.wf_spec, 'userTask', self.form)
@@ -33,43 +30,6 @@ class UserTaskSpecTest(unittest.TestCase):
self.assertEqual(self.form, self.user_spec.form)
def testSerialize(self):
- pass
-
- def test_text_field(self):
- form_field = FormField(form_type="text")
- form_field.id = "1234"
- self.form.add_field(form_field)
- self.assertEqual(form_field, self.user_spec.form.fields[0])
-
- def test_enum_field(self):
- enum_field = EnumFormField()
- enum_field.label = "Which kind of fool are you"
- enum_field.add_option('old fool', 'This is old, therefor it is good.')
- enum_field.add_option('new fool',
- 'This is new, therefor it is better.')
- self.form.add_field(enum_field)
- self.assertEqual(enum_field, self.user_spec.form.fields[-1])
-
- def test_properties(self):
- form_field = FormField(form_type="text")
- self.assertFalse(form_field.has_property("wilma"))
- form_field.add_property("wilma", "flintstone")
- self.assertTrue(form_field.has_property("wilma"))
- self.assertEquals("flintstone", form_field.get_property("wilma"))
-
- def test_validations(self):
- form_field = FormField(form_type="text")
- self.assertFalse(form_field.has_validation("barney"))
- form_field.add_validation("barney", "rubble")
- self.assertTrue(form_field.has_validation("barney"))
- self.assertEquals("rubble", form_field.get_validation("barney"))
-
- def testIsEngineTask(self):
- self.assertFalse(self.user_spec.is_engine_task())
-
- def test_convert_to_dict(self):
- form = Form()
-
field1 = FormField(form_type="text")
field1.id = "quest"
field1.label = "What is your quest?"
@@ -89,21 +49,14 @@ class UserTaskSpecTest(unittest.TestCase):
field2.add_property("description", "You know what to do.")
field2.add_validation("maxlength", "25")
- form.key = "formKey"
- form.add_field(field1)
- form.add_field(field2)
+ self.form.key = "formKey"
+ self.form.add_field(field1)
+ self.form.add_field(field2)
- def JsonableHandler(Obj):
- if hasattr(Obj, 'jsonable'):
- return Obj.jsonable()
- else:
- raise 'Object of type %s with value of %s is not JSON serializable' % (
- type(Obj), repr(Obj))
-
- json_form = json.dumps(form, default=JsonableHandler)
- actual = json.loads(json_form)
-
- expected = {
+ converter = UserTaskConverter()
+ dct = converter.to_dict(self.user_spec)
+ self.assertEqual(dct['name'], 'userTask')
+ self.assertEqual(dct['form'], {
"fields": [
{
"default_value": "I seek the grail!",
@@ -137,12 +90,39 @@ class UserTaskSpecTest(unittest.TestCase):
}
],
"key": "formKey",
- }
+ })
- expected_parsed = json.loads(json.dumps(expected))
+ def test_text_field(self):
+ form_field = FormField(form_type="text")
+ form_field.id = "1234"
+ self.form.add_field(form_field)
+ self.assertEqual(form_field, self.user_spec.form.fields[0])
- self.maxDiff = None
- self.assertDictEqual(actual, expected_parsed)
+ def test_enum_field(self):
+ enum_field = EnumFormField()
+ enum_field.label = "Which kind of fool are you"
+ enum_field.add_option('old fool', 'This is old, therefor it is good.')
+ enum_field.add_option('new fool',
+ 'This is new, therefor it is better.')
+ self.form.add_field(enum_field)
+ self.assertEqual(enum_field, self.user_spec.form.fields[-1])
+
+ def test_properties(self):
+ form_field = FormField(form_type="text")
+ self.assertFalse(form_field.has_property("wilma"))
+ form_field.add_property("wilma", "flintstone")
+ self.assertTrue(form_field.has_property("wilma"))
+ self.assertEquals("flintstone", form_field.get_property("wilma"))
+
+ def test_validations(self):
+ form_field = FormField(form_type="text")
+ self.assertFalse(form_field.has_validation("barney"))
+ form_field.add_validation("barney", "rubble")
+ self.assertTrue(form_field.has_validation("barney"))
+ self.assertEquals("rubble", form_field.get_validation("barney"))
+
+ def testIsEngineTask(self):
+ self.assertFalse(self.user_spec.is_engine_task())
def suite():
diff --git a/tests/SpiffWorkflow/spiff/PrescriptPostscriptTest.py b/tests/SpiffWorkflow/spiff/PrescriptPostscriptTest.py
index 52077059..320586a9 100644
--- a/tests/SpiffWorkflow/spiff/PrescriptPostscriptTest.py
+++ b/tests/SpiffWorkflow/spiff/PrescriptPostscriptTest.py
@@ -1,3 +1,4 @@
+from SpiffWorkflow.exceptions import SpiffWorkflowException
from SpiffWorkflow.task import TaskState
from .BaseTestCase import BaseTestCase
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
@@ -18,7 +19,7 @@ class PrescriptPostsciptTest(BaseTestCase):
self.call_activity_test(True)
def testDataObject(self):
-
+
spec, subprocesses = self.load_workflow_spec('prescript_postscript_data_object.bpmn', 'Process_1')
self.workflow = BpmnWorkflow(spec, subprocesses)
# Set a on the workflow and b in the first task.
@@ -45,8 +46,21 @@ class PrescriptPostsciptTest(BaseTestCase):
ready_tasks[0].complete()
self.assertDictEqual({'a': 1, 'b': 2, 'c': 12, 'z': 6}, ready_tasks[0].data)
+ def test_for_error(self, save_restore=False):
+
+ spec, subprocesses = self.load_workflow_spec('prescript_postscript.bpmn', 'Process_1')
+ self.workflow = BpmnWorkflow(spec, subprocesses)
+ if save_restore:
+ self.save_restore()
+ ready_tasks = self.workflow.get_tasks(TaskState.READY)
+ # Calling do-engine steps without setting variables will raise an exception.
+ with self.assertRaises(SpiffWorkflowException) as se:
+ self.workflow.do_engine_steps()
+ ex = se.exception
+ self.assertIn("Error occurred in the Pre-Script", str(ex))
+
def call_activity_test(self, save_restore=False):
-
+
spec, subprocesses = self.load_workflow_spec('prescript_postscript_*.bpmn', 'parent')
self.workflow = BpmnWorkflow(spec, subprocesses)
if save_restore:
diff --git a/tests/SpiffWorkflow/spiff/ServiceTaskTest.py b/tests/SpiffWorkflow/spiff/ServiceTaskTest.py
index 1d3035b3..66b2d86a 100644
--- a/tests/SpiffWorkflow/spiff/ServiceTaskTest.py
+++ b/tests/SpiffWorkflow/spiff/ServiceTaskTest.py
@@ -9,7 +9,6 @@ sys.path.insert(0, os.path.join(dirname, '..', '..', '..'))
from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
-from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException
from .BaseTestCase import BaseTestCase
class ServiceTaskDelegate:
diff --git a/tests/SpiffWorkflow/spiff/ServiceTaskVariableTest.py b/tests/SpiffWorkflow/spiff/ServiceTaskVariableTest.py
index 12237ae6..834f0c6f 100644
--- a/tests/SpiffWorkflow/spiff/ServiceTaskVariableTest.py
+++ b/tests/SpiffWorkflow/spiff/ServiceTaskVariableTest.py
@@ -9,7 +9,6 @@ sys.path.insert(0, os.path.join(dirname, '..', '..', '..'))
from SpiffWorkflow.bpmn.PythonScriptEngine import PythonScriptEngine
from SpiffWorkflow.bpmn.workflow import BpmnWorkflow
-from SpiffWorkflow.bpmn.exceptions import WorkflowTaskExecException
from .BaseTestCase import BaseTestCase
class ServiceTaskDelegate: