3535 generate_message
3636
3737
38- def _test_writer_and_reader (test_case , writer_constructor , reader_constructor , sleep_time = None ,
39- check_remote_frames = True , check_error_frames = True ,
40- check_comments = False , round_timestamps = False ):
41- """Tests a pair of writer and reader by writing all data first and
42- then reading all data and checking if they could be reconstructed
43- correctly. Optionally writes some comments as well.
44-
45- :param unittest.TestCase test_case: the test case the use the assert methods on
46- :param Callable writer_constructor: the constructor of the writer class
47- :param Callable reader_constructor: the constructor of the reader class
48-
49- :param float sleep_time: specifies the time to sleep after writing all messages.
50- gets ignored when set to None
38+ def _test_writer_and_reader (test_case , writer_constructor , reader_constructor ,
39+ check_remote_frames = True , check_error_frames = True , check_comments = False ,
40+ ** kwargs ):
41+ """
5142 :param bool check_remote_frames: if True, also tests remote frames
5243 :param bool check_error_frames: if True, also tests error frames
5344 :param bool check_comments: if True, also inserts comments at some
5445 locations and checks if they are contained anywhere literally
5546 in the resulting file. The locations as selected randomly
5647 but deterministically, which makes the test reproducible.
57- :param bool round_timestamps: if True, rounds timestamps using :meth:`~builtin.round`
58- before comparing the read messages/events
5948 """
6049
61- assert isinstance (test_case , unittest .TestCase ), \
62- "test_case has to be a subclass of unittest.TestCase"
50+ # get all test messages
51+ original_messages = TEST_MESSAGES_BASE
52+ if check_remote_frames :
53+ original_messages += TEST_MESSAGES_REMOTE_FRAMES
54+ if check_error_frames :
55+ original_messages += TEST_MESSAGES_ERROR_FRAMES
6356
6457 if check_comments :
6558 # we check this because of the lack of a common base class
6659 # we filter for not starts with '__' so we do not get all the builtin
6760 # methods when logging to the console
68- test_case .assertIn ('log_event' , [d for d in dir (writer_constructor ) if not d .startswith ('__' )],
61+ attrs = [attr for attr in dir (writer_constructor ) if not attr .startswith ('__' )]
62+ test_case .assertIn ('log_event' , attrs ,
6963 "cannot check comments with this writer: {}" .format (writer_constructor ))
7064
71- # create a temporary file
65+ # get all test comments
66+ original_comments = TEST_COMMENTS if check_comments else ()
67+
68+ # TODO: use https://docs.python.org/3/library/unittest.html#unittest.TestCase.subTest
69+ # once Python 2.7 gets dropped
70+
71+ print ("testing with path-like object and explicit stop() call" )
7272 temp = tempfile .NamedTemporaryFile ('w' , delete = False )
73+ filename = temp .name
7374 temp .close ()
75+ _test_writer_and_reader_execute (test_case , writer_constructor , reader_constructor ,
76+ filename , original_messages , original_comments ,
77+ use_context_manager = False , ** kwargs )
78+
79+ print ("testing with path-like object and context manager" )
80+ temp = tempfile .NamedTemporaryFile ('w' , delete = False )
7481 filename = temp .name
82+ temp .close ()
83+ _test_writer_and_reader_execute (test_case , writer_constructor , reader_constructor ,
84+ filename , original_messages , original_comments ,
85+ use_context_manager = True , ** kwargs )
7586
76- # get all test messages
77- original_messages = TEST_MESSAGES_BASE
78- if check_remote_frames :
79- original_messages += TEST_MESSAGES_REMOTE_FRAMES
80- if check_error_frames :
81- original_messages += TEST_MESSAGES_ERROR_FRAMES
87+ print ("testing with file-like object and explicit stop() call" )
8288
83- # get all test comments
84- original_comments = TEST_COMMENTS
89+ print ("testing with file-like object and context manager" )
8590
86- # create writer
87- writer = writer_constructor (filename )
8891
89- # write
90- if check_comments :
92+ def _test_writer_and_reader_execute (test_case , writer_constructor , reader_constructor ,
93+ file , original_messages , original_comments ,
94+ use_context_manager = False ,
95+ sleep_time = None , round_timestamps = False ):
96+ """Tests a pair of writer and reader by writing all data first and
97+ then reading all data and checking if they could be reconstructed
98+ correctly. Optionally writes some comments as well.
99+
100+ :param unittest.TestCase test_case: the test case the use the assert methods on
101+ :param Callable writer_constructor: the constructor of the writer class
102+ :param Callable reader_constructor: the constructor of the reader class
103+
104+ :param bool use_context_manager:
105+ if False, uses a explicit :meth:`~can.io.generic.BaseIOHandler.stop()`
106+ call on the reader and writer when finished, and else used the reader
107+ and writer as context managers
108+
109+ :param float sleep_time: specifies the time to sleep after writing all messages.
110+ gets ignored when set to None
111+ :param bool round_timestamps: if True, rounds timestamps using :meth:`~builtin.round`
112+ before comparing the read messages/events
113+
114+ """
115+
116+ assert isinstance (test_case , unittest .TestCase ), \
117+ "test_case has to be a subclass of unittest.TestCase"
118+
119+ def _write_all ():
91120 # write messages and insert comments here and there
92121 # Note: we make no assumptions about the length of original_messages and original_comments
93122 for msg , comment in zip_longest (original_messages , original_comments , fillvalue = None ):
@@ -98,21 +127,30 @@ def _test_writer_and_reader(test_case, writer_constructor, reader_constructor, s
98127 if msg is not None :
99128 print ("writing message: " , msg )
100129 writer (msg )
101- else :
102- # ony write messages
103- for msg in original_messages :
104- print ("writing message: " , msg )
105- writer (msg )
106130
107- # sleep and close the writer
108- if sleep_time is not None :
109- sleep (sleep_time )
131+ # sleep and close the writer
132+ if sleep_time is not None :
133+ sleep (sleep_time )
110134
111- writer .stop ()
135+ # create writer
136+ print ("writing all messages/comments" )
137+ if use_context_manager :
138+ with writer_constructor (file ) as writer :
139+ _write_all ()
140+ else :
141+ _write_all ()
142+ writer .stop ()
112143
113144 # read all written messages
114- print ("reading all messages ..." )
115- read_messages = list (reader_constructor (filename ))
145+ print ("reading all messages" )
146+ if use_context_manager :
147+ with reader_constructor (file ) as reader :
148+ read_messages = list (reader )
149+ else :
150+ reader = reader_constructor (file )
151+ read_messages = list (reader )
152+ # redundant, but this checks if stop() can be called multiple times
153+ reader .stop ()
116154
117155 # check if at least the number of messages matches
118156 test_case .assertEqual (len (read_messages ), len (original_messages ),
@@ -121,29 +159,30 @@ def _test_writer_and_reader(test_case, writer_constructor, reader_constructor, s
121159 # check the order and content of the individual messages
122160 for i , (read , original ) in enumerate (zip (read_messages , original_messages )):
123161 try :
162+ # check everything except the timestamp
124163 if read != original :
164+ # check like this to print the whole message
125165 print ("original message: {}" .format (original ))
126166 print ("read message: {}" .format (read ))
127- # check everything except the timestamp
128- test_case .assertEqual (read , original )
167+ test_case .fail ()
129168 # check the timestamp
130169 if round_timestamps :
131170 original .timestamp = round (original .timestamp )
132171 read .timestamp = round (read .timestamp )
133172 test_case .assertAlmostEqual (read .timestamp , original .timestamp , places = 6 )
134173 except Exception as exception :
135174 # attach the index
136- exception .args += ("test failed at index #{}" .format (i ), )
175+ exception .args += ("messages are not equal at index #{}" .format (i ), )
137176 raise exception
138177
139178 # check if the comments are contained in the file
140- if check_comments :
179+ if original_comments :
141180 # read the entire outout file
142- with open (filename , 'r' ) as file :
181+ with open (file , 'r' ) as file :
143182 output_contents = file .read ()
144183 # check each, if they can be found in there literally
145184 for comment in original_comments :
146- test_case .assertTrue (comment in output_contents )
185+ test_case .assertIn (comment , output_contents )
147186
148187
149188class TestCanutilsLog (unittest .TestCase ):
0 commit comments