Reputation: 2782
Before this question is immediately marked as a duplicate let me say that I have already tried every solution which were the two questions most relevant to my situation. I would appreciate it if someone could at least look at my particular issue before closing this question if necessary.
I have a finite state machine object called e which is a MCFiniteSM
object. At the core of e is a dictionary called state_dict which stores "process" ids ('1', '2', etc) and an associated dictionary which stores more information about each "process". I am running unittests to add processes, changes their states based on given parameters, etc. However, in between function calls in the unittest file the finite state machine seems to be cleared. I have looked at the two questions listed above in order to avoid this and persist changes but no matter what I try the changes to the finite state machine are not persisted. Here is the uniitest file.
from finite_state_machine import MCFiniteSM
from unittest import TestLoader, TestCase, main as unimain
from datetime import datetime
import time, calendar
class MyUnitTest(TestCase):
@classmethod
def setUpClass(cls):
cls.e = MCFiniteSM()
cls.timestamp = datetime.strftime(datetime.fromtimestamp(calendar.timegm(time.gmtime())), '%Y/%m/%d %H:%M:%S')
class TestFSM(MyUnitTest):
@classmethod
def setUpClass(cls):
super(TestFSM, cls).setUpClass()
#e = MCFiniteSM()
#timestamp = datetime.strftime(datetime.fromtimestamp(calendar.timegm(time.gmtime())), '%Y/%m/%d %H:%M:%S')
def test_add_convert_processes(self):
self.e.add_process('1', 'S', self.timestamp, 100, 'start message for process 1')
self.e.add_process('2', 'S', self.timestamp, 200, 'start message for process 2')
self.e.add_process('3', 'S', self.timestamp, 300, 'start message for process 3')
self.e.add_process('4', 'S', self.timestamp, 400, 'start message for process 4')
self.e.add_process('5', 'S', self.timestamp, 500, 'start message for process 5')
self.e.add_process('6', 'S', self.timestamp, 600, 'start message for process 6')
self.assertEqual(self.e.state_dict['1'], {'id':'1', 'message_type': 'S', 'timestamp':self.timestamp, 'state': 'i', 'threshold':100, 'message': 'start message for process 1'})
self.assertEqual(self.e.state_dict['2'], {'id':'2', 'message_type': 'S', 'timestamp':self.timestamp, 'state': 'i', 'threshold':200, 'message': 'start message for process 2'})
self.assertEqual(self.e.state_dict['3'], {'id':'3', 'message_type': 'S', 'timestamp':self.timestamp, 'state': 'i', 'threshold':300, 'message': 'start message for process 3'})
self.assertEqual(self.e.state_dict['4'], {'id':'4', 'message_type': 'S', 'timestamp':self.timestamp, 'state': 'i', 'threshold':400, 'message': 'start message for process 4'})
self.assertEqual(self.e.state_dict['5'], {'id':'5', 'message_type': 'S', 'timestamp':self.timestamp, 'state': 'i', 'threshold':500, 'message': 'start message for process 5'})
self.assertEqual(self.e.state_dict['6'], {'id':'6', 'message_type': 'S', 'timestamp':self.timestamp, 'state': 'i', 'threshold':600, 'message': 'start message for process 6'})
self.e.convert_state('1', 'S')
self.e.convert_state('2', 'S')
self.e.convert_state('3', 'S')
self.e.convert_state('4', 'S')
self.e.convert_state('5', 'S')
self.e.convert_state('6', 'S')
self.assertEqual(self.e.state_dict['2']['state'], 'a')
self.assertEqual(self.e.state_dict['3']['state'], 'a')
self.assertEqual(self.e.state_dict['4']['state'], 'a')
self.e.add_process('2', 'E', self.timestamp, None, 'end message for process 2')
self.e.add_process('3', 'E', self.timestamp, None, 'end message for process 3')
self.e.add_process('4', 'E', self.timestamp, None, 'end message for process 4')
self.assertEqual(self.e.state_dict['2']['state'], 'i')
self.assertEqual(self.e.state_dict['3']['state'], 'i')
self.assertEqual(self.e.state_dict['4']['state'], 'i')
def test_active_start_conversion(self):
print self.e
print 'trying...'
import sys
from StringIO import StringIO
orig = sys.stdout
try:
output = StringIO()
sys.stdout = output
self.e.convert_state('1', 'S')
out = output.getvalue().strip()
test = "Process ID:", '1', "\n" \
"Process Message Type:", 'S', "\n" \
"Process timestamp:", self.timestamp, "\n" \
"Process Threshold:", 100, "\n" \
"Process Message:", 'start message for process 1', "\n" \
"Log Message:", "PROCESS WITH ID 1 SENT MULTIPLE START MESSAGES", "\n"
self.assertEqual(out, test)
finally:
sys.stdout = orig
if __name__ == '__main__':
unimain()
'e'
is the variable I want to keep modified between function calls. When I get down to TestFSM.test_active_start_conversion
the size of e prints out 0, when it should be 6. The TestFSM.test_add_convert_processes
method runs successfully.
The actual error is a key error. Here is the stack trace:
Error
Traceback (most recent call last):
File "/home/Desktop/fsm_unit_tests.py", line 68, in test_active_start_conversion
self.e.convert_state('1', 'S')
File "/home/Desktop/finite_state_machine.py", line 26, in convert_state
cb_id = self.state_dict[id]['id']
KeyError: '1'
The line where the error is thrown is the self.e.convert_state('1', 'S')
where I am telling the fsm to change the state of the process with ID '1'. It believes that there is no process with ID 1 and upon printing the size of the fsm it believes the finite state machine is empty. This must be due to the fact that e is not continually maintained but I do not see why.
I have tried converting self.e
to self.__class__.e
(same with timestamp) as well as just keeping e and timestamp global and calling TestFSM.e
and TestFSM.timestamp
to persist changes. Both these solutions were listed in the other questions, both of them still produced a Key Error. I tried setting up setUpClass()
, but that still produced a key error.
How can I persist e and timestamp?
Upvotes: 1
Views: 1164
Reputation: 599610
Test methods are executed in alphabetical order. So test_active_start_conversion
is executed before test_add_convert_processes
.
However, really your tests should be independent - you should be doing the set up in the actual setUp
method, not in a test method.
Upvotes: 5