how to measure sleep duration: test_duration_w_hours_and_minutes¶
This is part 2 of a program that calculates the difference between a given wake and sleep time.
I want to test the duration
function with timestamps where both hours and minutes are random.
red: make it fail¶
I change the name of
test_duration_w_hours
def test_duration_w_hours_and_minutes(self): sleep_time = random_timestamp() wake_time = random_timestamp()
then add a variable for the difference between the hours
difference_hours = ( int(wake_time.split(':')[0]) - int(sleep_time.split(':')[0]) ) self.assertEqual( sleep_duration.duration( wake_time=wake_time, sleep_time=sleep_time ), difference_hours )
and change the expectation to a timestamp format
self.assertEqual( sleep_duration.duration( wake_time=wake_time, sleep_time=sleep_time ), f'{difference_hours:02}:00' )
which gives me AssertionError
AssertionError: -3 != '-3:00' AssertionError: 0 != '00:00' AssertionError: 8 != '08:00' AssertionError: 16 != '16:00'
the
duration
function returns a number and the test expects a string. I change it to match the expectationdef duration(wake_time=None, sleep_time=None): difference_hours = ( get_hour(wake_time) - get_hour(sleep_time) ) return f'{difference_hours:02}:00'
then make a copy of
difference_hours
in the test, change the name, and change0
to1
on each line to get the difference between the minutes ofwake_time
andsleep_time
def test_duration_w_hours_and_minutes(self): sleep_time = random_timestamp() 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]) )
I also add
difference_minutes
to the expectationself.assertEqual( sleep_duration.duration( wake_time=wake_time, sleep_time=sleep_time ), ( f'{difference_hours:02}:' f'{difference_minutes:02}' ) )
and change the
random_timestamp
function to have random numbers from0
up to and including59
for the minutesdef random_timestamp(): return ( f'{random.randint(0,23):02}:' f'{random.randint(0,59):02}' )
I get random success when
random_timestamp
returns00
for the minutes and AssertionError when it does notAssertionError: '-18:00' != '-18:44' AssertionError: '05:00' != '05:-16' AssertionError: '-2:00' != '-2:-26' AssertionError: '16:00' != '16:-25'
the
duration
function returns00
for the minutes part of the duration, and the test expects the difference between the minutes ofwake_time
andsleep_time
green: make it pass¶
I make a copy of
difference_hours
induration
, change the name, then add it to the return statementdef duration(wake_time=None, sleep_time=None): difference_hours = ( get_hour(wake_time) - get_hour(sleep_time) ) difference_minutes = ( get_hour(wake_time) - get_hour(sleep_time) ) return ( f'{difference_hours:02}:' f'{difference_minutes:02}' )
the terminal shows AssertionError
AssertionError: '20:20' != '20:-6' AssertionError: '06:06' != '06:17' AssertionError: '-16:-16' != '-16:-7' AssertionError: '02:02' != '02:07'
the function returns the same numbers for hours and minutes because
difference_hours
anddifference_minutes
are the same. I make a copy of theget_hour
function, call itget_minutes
and change the index to get the second item from the timestamp splitdef get_minutes(timestamp): return int(timestamp.split(':')[1])
then change the calls in
difference_minutes
difference_minutes = ( get_minutes(wake_time) - get_minutes(sleep_time) )
and the terminal shows passing tests! There is something wrong with this calculation…
refactor: make it better¶
test_duration_calculation¶
The duration
function returns a subtraction of hours and a subtraction of minutes which does not give the right difference between the timestamps
red: make it fail¶
If duration
is given a wake_time
of '03:30'
and a sleep_time
of '02:59'
, it should return '00:31'
as the difference between the timestamps
def test_duration_calculation(self):
self.assertEqual(
sleep_duration.duration(
wake_time='03:30',
sleep_time='02:59'
),
'00:31'
)
def test_duration_w_hours_and_minutes(self):
...
the terminal shows AssertionError when I add test_duration_calculation
AssertionError: '01:-29' != '00:31'
duration
returns '01:-29'
which is not a real duration, the calculation has to change
green: make it pass¶
I add a return statement to the
duration
function where I multiplydifference_hours
by60
then add it todifference_minutes
to get the total difference in minutesreturn ( difference_hours*60 + difference_minutes ) return ( f'{difference_hours:02}:' f'{difference_minutes:02}' )
the terminal shows AssertionError for
test_duration_w_hours_and_minutes
AssertionError: -458 != '-7:-38' AssertionError: -936 != '-15:-36' AssertionError: -31 != '-1:29' AssertionError: 213 != '03:33'
duration
returns the difference as a number and the test still expects a string. I add the unittest.skip decorator to skip it@unittest.skip def test_duration_w_hours_and_minutes(self): ...
and get this AssertionError for
test_duration_calculation
AssertionError: 31 != '00:31
the function returns the right number of minutes for the difference. I need a way to change it to hours and minutes to match the expectations of the tests. I add the unittest.skip decorator to skip it while I test the solution
@unittest.skip def test_duration_calculation(self): ...
If I divide the total number of minutes by
60
, the whole number from the result is the hours and the remainder is the minutes
test_floor_aka_integer_division¶
The //
operator returns a whole number which is how many times the bottom number can be multiplied to get a whole number that is equal to or as close to the top number as possible. It should give me the hours when I divide by 60
I add a failing test for it
def test_floor_aka_integer_division(self): self.assertEqual(120//60, 0) @unittest.skip def test_duration_calculation(self): ...
and the terminal shows AssertionError
AssertionError: 2 != 0
the result of
120
divided by60
is2
with a remainder of0
. I change the expectation to the right value.self.assertEqual(120//60, 2)
and it passes
I add another assertion
self.assertEqual(150//60, 0)
and get AssertionError
AssertionError: 2 != 0
the result of
150
divided by60
is also2
but with a remainder of30
. I change the expectation to the right valueself.assertEqual(150//60, 2)
and the terminal shows passing tests
test_the_modulo_operation¶
The %
operator returns the remainder when a number is divided by another, it should give me the minutes when I divide by 60
I add a failing test for it
def test_the_modulo_operation(self): self.assertEqual(120%60, 2) @unittest.skip def test_duration_calculation(self): ...
and the terminal shows AssertionError
AssertionError: 0 != 2
the remainder when
120
is divided by60
is0
. I change the expectation to the right valueself.assertEqual(120%60, 0)
and the test passes
I add another assertion
self.assertEqual(150%60, 0)
and the terminal shows AssertionError
AssertionError: 30 != 0
the remainder when
150
is divided by60
is30
. I change the expected value in the test to the right valueself.assertEqual(150%60, 30)
and the terminal shows green again
I comment out the unittest.skip decorator for
test_duration_calculation
to get back the AssertionError# @unittest.skip def test_duration_calculation(self):
and change the first return statement in the
duration
function to a variable for the total difference in minutesdifference = ( difference_hours*60 + difference_minutes ) return ( f'{difference_hours:02}:' f'{difference_minutes:02}' )
then add a variable for the hours of the duration using floor (integer) division
difference = ( difference_hours*60 + difference_minutes ) duration_hours = difference // 60
and a variable for the minutes of the duration using the modulo operator
duration_hours = difference // 60 duration_minutes = difference % 60
then change
difference_hours
anddifference_minutes
in the return statementreturn ( f'{duration_hours:02}:' f'{duration_minutes:02}' )
and the test passes
I remove the unittest.skip decorator from
test_duration_calculation
and comment it out for
test_duration_w_hours_and_minutes
# @unittest.skip def test_duration_w_hours_and_minutes(self): ...
which gives me random successes and random AssertionError
AssertionError: '-11:46' != '-10:-14' AssertionError: '-6:04' != '-5:-56' AssertionError: '10:50' != '11:-10' AssertionError: '16:50' != '17:-10'
the calculation in the test is still not right. I change it to match the
duration
functiondifference = ( difference_hours*60 + difference_minutes ) duration_hours = difference // 60 duration_minutes = difference % 60
then change the variables in the expectation
self.assertEqual( sleep_duration.duration( wake_time=wake_time, sleep_time=sleep_time ), ( f'{duration_hours:02}:' f'{duration_minutes:02}' ) )
and the test passes with no more random failures
I take out the unittest.skip decorator from
test_duration_w_hours_and_minutes
and remove
test_duration_calculation
because it is covered bytest_duration_w_hours_and_minutes
which has the right calculationthen add a function in
sleep_duration.py
to changeget_hour
andget_minutes
def read_timestamp(timestamp=None, index=0): return int(timestamp.split(':')[index]) def duration(wake_time=None, sleep_time=None): ...
call it in
duration
def duration(wake_time=None, sleep_time=None): difference_hours = ( read_timestamp(wake_time) - read_timestamp(sleep_time) ) difference_minutes = ( read_timestamp(wake_time, 1) - read_timestamp(sleep_time, 1) ) ...
and remove
get_hour
andget_minutes
. The terminal shows all tests are still passing!
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 random.randint to generate random numbers
from the
24
hours in a dayand the
60
minutes in an hour
then how to pass values them in the timestamp strings that are given to the function
and test_duration_calculation to make sure that the
duration
function returns the right difference betweenwake_time
andsleep_time
and changes it to a timestamp format
by using floor (integer) division to get the hours
and the modulo operation to get the minutes
Would you like to test duration with an earlier wake than sleep time?