how to measure sleep duration: test_duration_w_an_earlier_wake_than_sleep_time¶
This is part 3 of a program that calculates the difference between a given wake and sleep time.
I want to test the duration
function with a wake_time
that is earlier than the sleep_time
red: make it fail¶
I add a failing test to test_sleep_duration.py
with a while statement to make sure wake_time
is always earlier than sleep_time
def test_duration_w_an_earlier_wake_than_sleep_time(self):
sleep_time = random_timestamp()
wake_time = random_timestamp()
while wake_time >= sleep_time:
wake_time = random_timestamp()
self.assertEqual(
sleep_duration.duration(
sleep_time=sleep_time,
wake_time=wake_time
),
''
)
def test_duration_w_hours_and_minutes(self):
...
and get AssertionError
AssertionError: '-1:00' != ''
AssertionError: '-2:12' != ''
AssertionError: '-8:34' != ''
AssertionError: '-10:57' != ''
green: make it pass¶
The
duration
function returns a negative timestamp when given an earlierwake_time
thansleep_time
, which is not a real duration. I want it to return a difference whenwake_time
is later than or the same assleep_time
and raise ValueError with a message whenwake_time
is earlier thansleep_time
. I change the assertEqual to assertRaisesRegex to catch the Exception when it is raised by the functiondef test_duration_w_an_earlier_wake_than_sleep_time(self): sleep_time = random_timestamp() wake_time = random_timestamp() while wake_time >= sleep_time: wake_time = random_timestamp() with self.assertRaisesRegex( ValueError, f'wake_time: "{wake_time}"' ' is earlier than ' f'sleep_time: "{sleep_time}"' ): sleep_duration.duration( sleep_time=sleep_time, wake_time=wake_time )
the terminal shows AssertionError
AssertionError: ValueError not raised
I add a condition to the
duration
function to raise the ValueErrordef duration(wake_time=None, sleep_time=None): if wake_time < sleep_time: raise ValueError( f'wake_time: "{wake_time}"' ' is earlier than ' f'sleep_time: "{sleep_time}"' ) else: difference_hours = ( read_timestamp(wake_time) - read_timestamp(sleep_time) ) difference_minutes = ( read_timestamp(wake_time, 1) - read_timestamp(sleep_time, 1) ) difference = ( difference_hours*60 + difference_minutes ) duration_hours = difference // 60 duration_minutes = difference % 60 return ( f'{duration_hours:02}:' f'{duration_minutes:02}' )
and the terminal shows a random ValueError for
test_duration_w_hours_and_minutes
whenwake_time
is earlier thansleep_time
ValueError: wake_time: "07:33" is earlier than sleep_time: "08:12" ValueError: wake_time: "07:46" is earlier than sleep_time: "14:47" ValueError: wake_time: "23:10" is earlier than sleep_time: "23:27" ValueError: wake_time: "11:32" is earlier than sleep_time: "13:52"
I add the error to the list of Exceptions encountered
# Exceptions Encountered # AssertionError # TypeError # NameError # AttributeError # ValueError
then add a while statement to make sure
wake_time
is not earlier thansleep_time
for the difference calculationdef test_duration_w_hours_and_minutes(self): sleep_time = random_timestamp() wake_time = random_timestamp() while wake_time < sleep_time: wake_time = random_timestamp() difference_hours = ( int(wake_time.split(':')[0]) - int(sleep_time.split(':')[0]) ) difference_minutes = ( int(wake_time.split(':')[1]) - int(sleep_time.split(':')[1]) ) difference = ( difference_hours*60 + difference_minutes ) duration_hours = difference // 60 duration_minutes = difference % 60 self.assertEqual( sleep_duration.duration( sleep_time=sleep_time, wake_time=wake_time ), ( f'{duration_hours:02}:' f'{duration_minutes:02}' ) )
and the terminal shows passing tests with no more random failures, green, green, green, green all the way!
refactor: make it better¶
I copy the assertRaisesRegex statement from
test_duration_w_an_earlier_wake_than_sleep_time
then add it to the while statement to run whenwake_time
is earlier thansleep_time
def test_duration_w_hours_and_minutes(self): sleep_time = random_timestamp() wake_time = random_timestamp() while wake_time < sleep_time: with self.assertRaisesRegex( ValueError, f'wake_time: "{wake_time}"' ' is earlier than ' f'sleep_time: "{sleep_time}"' ): sleep_duration.duration( sleep_time=sleep_time, wake_time=wake_time ) wake_time = random_timestamp() difference_hours = ( int(wake_time.split(':')[0]) - int(sleep_time.split(':')[0]) ) difference_minutes = ( int(wake_time.split(':')[1]) - int(sleep_time.split(':')[1]) ) difference = ( difference_hours*60 + difference_minutes ) duration_hours = difference // 60 duration_minutes = difference % 60 self.assertEqual( sleep_duration.duration( sleep_time=sleep_time, wake_time=wake_time ), ( f'{duration_hours:02}:' f'{duration_minutes:02}' ) )
and comment out the condition in
duration
to make sure the test still works as expecteddef duration(wake_time=None, sleep_time=None): # if wake_time < sleep_time: # raise ValueError( # f'wake_time: "{wake_time}"' # ' is earlier than ' # f'sleep_time: "{sleep_time}"' # ) # else: difference_hours = ( read_timestamp(wake_time) - read_timestamp(sleep_time) ) difference_minutes = ( read_timestamp(wake_time, 1) - read_timestamp(sleep_time, 1) ) difference = ( difference_hours*60 + difference_minutes ) duration_hours = difference // 60 duration_minutes = difference % 60 return ( f'{duration_hours:02}:' f'{duration_minutes:02}' )
which gives me AssertionError for
test_duration_w_an_earlier_wake_than_sleep_time
and a random one whenwake_time
is earlier thansleep_time
intest_duration_w_hours_and_minutes
AssertionError: ValueError not raised
the assertRaisesRegex works as expected. I remove the comments and the terminal shows green again
I remove
test_duration_w_an_earlier_wake_than_sleep_time
because it is now covered bytest_duration_w_hours_and_minutes
then add an
else
block for the rest of the code intest_duration_w_hours_and_minutes
def test_duration_w_hours_and_minutes(self): sleep_time = random_timestamp() wake_time = random_timestamp() while wake_time < sleep_time: with self.assertRaisesRegex( ValueError, f'wake_time: "{wake_time}"' ' is earlier than ' f'sleep_time: "{sleep_time}"' ): sleep_duration.duration( sleep_time=sleep_time, wake_time=wake_time ) wake_time = random_timestamp() else: difference_hours = ( int(wake_time.split(':')[0]) - int(sleep_time.split(':')[0]) ) difference_minutes = ( int(wake_time.split(':')[1]) - int(sleep_time.split(':')[1]) ) difference = ( difference_hours*60 + difference_minutes ) duration_hours = difference // 60 duration_minutes = difference % 60 self.assertEqual( sleep_duration.duration( sleep_time=sleep_time, wake_time=wake_time ), ( f'{duration_hours:02}:' f'{duration_minutes:02}' ) )
still green
I add a static method to calculate the difference between
wake_time
andsleep_time
@staticmethod def get_difference( wake_time=None, sleep_time=None ): difference_hours = ( int(wake_time.split(':')[0]) - int(sleep_time.split(':')[0]) ) difference_minutes = ( int(wake_time.split(':')[1]) - int(sleep_time.split(':')[1]) ) difference = ( difference_hours*60 + difference_minutes ) duration_hours = difference // 60 duration_minutes = difference % 60 return ( f'{duration_hours:02}:' f'{duration_minutes:02}' ) def test_duration_w_hours_and_minutes(self): ...
then call it in
test_duration_w_hours_and_minutes
to change the expectationdef test_duration_w_hours_and_minutes(self): sleep_time = random_timestamp() wake_time = random_timestamp() while wake_time < sleep_time: with self.assertRaisesRegex( ValueError, f'wake_time: "{wake_time}"' ' is earlier than ' f'sleep_time: "{sleep_time}"' ): sleep_duration.duration( sleep_time=sleep_time, wake_time=wake_time ) wake_time = random_timestamp() else: self.assertEqual( sleep_duration.duration( sleep_time=sleep_time, wake_time=wake_time ), self.get_difference( wake_time=wake_time, sleep_time=sleep_time ) )
green again
I also add an
assert
method for the assertRaisesRegex blockdef assertWakeTimeEarlier( self, wake_time=None, sleep_time=None ): with self.assertRaisesRegex( ValueError, f'wake_time: "{wake_time}"' ' is earlier than ' f'sleep_time: "{sleep_time}"' ): sleep_duration.duration( sleep_time=sleep_time, wake_time=wake_time ) @staticmethod def get_difference( ...
and call it in
test_duration_w_hours_and_minutes
def test_duration_w_hours_and_minutes(self): sleep_time = random_timestamp() wake_time = random_timestamp() while wake_time < sleep_time: self.assertWakeTimeEarlier( wake_time=wake_time, sleep_time=sleep_time ) wake_time = random_timestamp() else: self.assertEqual( sleep_duration.duration( sleep_time=sleep_time, wake_time=wake_time ), self.get_difference( wake_time=wake_time, sleep_time=sleep_time ) )
all tests are still passing! Fantastic!
review¶
The challenge is to write a program that calculates the difference between a given wake and sleep time. I ran the following tests to get something that comes close to doing it
test_duration_w_hours_and_minutes where I used a while statement to make sure that when
wake_time
is earlier thansleep_time
theduration
function raises ValueError with a message and returns the right difference between the 2 whenwake_time
is later than or the same assleep_time
Would you like to test duration with timestamps that have dates?