Skip to content

Commit

Permalink
Performing test on times with data in a fixture
Browse files Browse the repository at this point in the history
Answers UCL Issue UCL-RITS#92
  • Loading branch information
rmapjs1 committed Dec 20, 2020
1 parent 843a2c6 commit 9248123
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 0 deletions.
21 changes: 21 additions & 0 deletions week05-testing/fixture.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
- generic:
time_range_1: ["2010-01-12 10:00:00", "2010-01-12 12:00:00"]
time_range_2: ["2010-01-12 10:30:00", "2010-01-12 10:45:00", 2, 60]
expected:
- ["2010-01-12 10:30:00","2010-01-12 10:37:00"]
- ["2010-01-12 10:38:00", "2010-01-12 10:45:00"]
- no_overlap:
time_range_1: ["2010-01-12 10:00:00", "2010-01-12 11:00:00"]
time_range_2: ["2010-01-12 12:30:00", "2010-01-12 12:45:00", 2, 60]
expected: []
- multiple_overlaps:
time_range_1: ["2010-01-12 10:00:00", "2010-01-12 13:00:00", 3, 900]
time_range_2: ["2010-01-12 10:40:00", "2010-01-12 11:20:00", 2, 120]
expected:
- ["2010-01-12 10:40:00","2010-01-12 10:50:00"]
- ["2010-01-12 11:05:00", "2010-01-12 11:20:00"]
- touching:
time_range_1: ["2010-01-12 10:00:00", "2010-01-12 11:00:00"]
time_range_2: ["2010-01-12 11:00:00", "2010-01-12 12:45:00"]
expected: []

42 changes: 42 additions & 0 deletions week05-testing/test_times_fixtures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""The file to test times.py"""

#import functions from times.py
import pytest
import yaml
from times import compute_overlap_time, time_range

# get fixture data from yaml file
with open("fixture.yaml", 'r') as yamlfile:
fixture = yaml.safe_load(yamlfile)
print(fixture)
# gives a list of dictionaries for each test case

# parametrization of entries
@pytest.mark.parametrize("test_name", fixture)
# fixture is a list of dictionaries [{'generic':...}, {'no_overlap':...}, ...]

def test_parametrized_overlap(test_name):
# test_name will be a dictionary, e.g. for the first case: {'generic': {'time_range_1':..., 'time_range2':..., 'expected':...}}
properties = list(test_name.values())[0]
first_range = time_range(*properties['time_range_1'])
second_range = time_range(*properties['time_range_2'])

expected = [(start, stop) for start, stop in properties['expected']]
result = compute_overlap_time(first_range, second_range)
assert result == expected

#negative test for a date going backwards
#check that the error message matches with the one raised in time_range function of times.py

# first possible solution
def test_negative_time_range():
with pytest.raises(ValueError) as e:
time_range("2010-01-12 10:00:00", "2010-01-12 09:30:00")
# lines after the error is raised are not executed in the pytest.raises context, so the assertion has to be outside the "with"
assert e.match('The end of the time range has to come strictly after its start.')

# an alternative solution for using pytest.raises to check that the error message is as expected
def test_negative_time_range_alternative():
expected_error_message = 'The end of the time range has to come strictly after its start.'
with pytest.raises(ValueError, match=expected_error_message):
time_range("2010-01-12 10:00:00", "2010-01-12 09:30:00")
54 changes: 54 additions & 0 deletions week05-testing/times_fixtures.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
"""Exercise #61 - Code"""

import datetime

#function to convert the time range into strings of start ta and end tb
def time_range(start_time, end_time, number_of_intervals=1, gap_between_intervals_s=0):
start_time_s = datetime.datetime.strptime(start_time, "%Y-%m-%d %H:%M:%S")
end_time_s = datetime.datetime.strptime(end_time, "%Y-%m-%d %H:%M:%S")

if(start_time_s>=end_time_s):
raise ValueError('The end of the time range has to come strictly after its start.')

d = (end_time_s - start_time_s).total_seconds() / number_of_intervals + gap_between_intervals_s * (1 / number_of_intervals - 1)
sec_range = [(start_time_s + datetime.timedelta(seconds=i * d + i * gap_between_intervals_s),
start_time_s + datetime.timedelta(seconds=(i + 1) * d + i * gap_between_intervals_s))
for i in range(number_of_intervals)]
return [(ta.strftime("%Y-%m-%d %H:%M:%S"), tb.strftime("%Y-%m-%d %H:%M:%S")) for ta, tb in sec_range]


#function to compute the overlap time
def compute_overlap_time(range1, range2):
overlap_time = []
for start1, end1 in range1:
for start2, end2 in range2:

# both ranges need to start before the other ends, otherwise there is no overlap!
if start1<= end2 and start2 <= end1:
low = max(start1, start2)
high = min(end1, end2)

# in case they touch exactly (end of one is start of the other) --> no overlap
if high == low:
continue # jumps to the next iteration of the loop

overlap_time.append((low, high))

#note: when there is no overlap, overlap_time = [] stays
return overlap_time


# this only runs if this module is run directly, if it is imported somewhere then __name__ == times instead!!
if __name__ == "__main__":
#converts the time ranges into strings
large = time_range("2010-01-12 10:00:00", "2010-01-12 12:00:00")
short = time_range("2010-01-12 10:30:00", "2010-01-12 10:45:00", 2, 60)
print(f"large: {large}")
#[('2010-01-12 10:00:00', '2010-01-12 12:00:00')]
print(f"short: {short}")
#[('2010-01-12 10:30:00', '2010-01-12 10:37:00'), ('2010-01-12 10:38:00', '2010-01-12 10:45:00')]

# the outputted resulting overlap time
overlap_t = compute_overlap_time(large, short)
print(f"The resulting overlaps are {overlap_t}.")
#[('2010-01-12 10:30:00', '2010-01-12 10:37:00'), ('2010-01-12 10:38:00', '2010-01-12 10:45:00')]

0 comments on commit 9248123

Please sign in to comment.