Testing Class Material
This commit is contained in:
commit
05b1f6cdd5
85 changed files with 102796 additions and 0 deletions
1
hands_on/bug_hunt/datastore/README
Normal file
1
hands_on/bug_hunt/datastore/README
Normal file
|
@ -0,0 +1 @@
|
|||
This is the directory used as a datastore by `file_datastore.py`.
|
113
hands_on/bug_hunt/file_datastore.py
Normal file
113
hands_on/bug_hunt/file_datastore.py
Normal file
|
@ -0,0 +1,113 @@
|
|||
import os
|
||||
|
||||
|
||||
class FileDatastore:
|
||||
"""Datastore based on a regular file system.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
base_path: str
|
||||
Filesystem path at which the data store is based.
|
||||
"""
|
||||
|
||||
def __init__(self, base_path):
|
||||
if not os.path.exists(base_path):
|
||||
raise FileNotFoundError(f'Base path {base_path} does not exist')
|
||||
if not os.path.isdir(base_path):
|
||||
raise NotADirectoryError(f'Base path {base_path} exists but is not a directory')
|
||||
|
||||
self.base_path = base_path
|
||||
|
||||
def open(self, path, mode):
|
||||
""" Open a file-like object
|
||||
|
||||
Parameters
|
||||
----------
|
||||
path: str
|
||||
Path relative to the root of the data store.
|
||||
mode: str
|
||||
Specifies the mode in which the file is opened.
|
||||
|
||||
Returns
|
||||
-------
|
||||
IO[Any]
|
||||
An open file-like object.
|
||||
"""
|
||||
path = os.path.join(self.base_path, path)
|
||||
return open(path, mode)
|
||||
|
||||
def read(self, path):
|
||||
""" Read a sequence of bytes from the data store.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
path: str
|
||||
Path relative to the root of the data store.
|
||||
|
||||
Returns
|
||||
-------
|
||||
bytes
|
||||
The sequence of bytes read from `path`.
|
||||
"""
|
||||
with self.open(path, 'rb') as f:
|
||||
data = f.read()
|
||||
return data
|
||||
|
||||
def write(self, path, data) -> None:
|
||||
""" Write a sequence of bytes to the data store.
|
||||
|
||||
`path` contains the path relative to the root of the data store, including the name
|
||||
of the file to be created. If a file already exists at `path`, it is overwritten.
|
||||
|
||||
Intermediate directories that do not exist will be created.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
path: str
|
||||
Path relative to the root of the data store.
|
||||
data: bytes
|
||||
Sequence of bytes to write at `path`.
|
||||
"""
|
||||
path = os.path.join(self.base_path, path)
|
||||
self.makedirs(os.path.dirname(path))
|
||||
with self.open(path, 'wb') as f:
|
||||
f.write(data)
|
||||
|
||||
def exists(self, path):
|
||||
""" Returns True if the file exists.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
path: str
|
||||
Path relative to the root of the data store.
|
||||
|
||||
Returns
|
||||
-------
|
||||
bool
|
||||
True if the file exists, false otherwise
|
||||
"""
|
||||
complete_path = os.path.join(self.base_path, path)
|
||||
return os.path.exists(complete_path)
|
||||
|
||||
def makedirs(self, path):
|
||||
""" Creates the specified directory if needed.
|
||||
|
||||
If the directories already exist, the method does not do anything.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
path: str
|
||||
Path relative to the root of the data store.
|
||||
"""
|
||||
complete_path = os.path.join(self.base_path, path)
|
||||
os.makedirs(complete_path, exist_ok=True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
data = b'A test! 012'
|
||||
datastore = FileDatastore(base_path='./datastore')
|
||||
datastore.write('a/mydata.bin', data)
|
||||
|
||||
# This should pass!
|
||||
# The code works correctly if `base_path` is an absolute path :-(
|
||||
assert os.path.exists('./datastore/a/mydata.bin')
|
65
hands_on/debugger/analyze_sums_and_differences.ipynb
Normal file
65
hands_on/debugger/analyze_sums_and_differences.ipynb
Normal file
|
@ -0,0 +1,65 @@
|
|||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "30f3f04f",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from debugger_example import sum_over_difference"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "3632cacb",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"result = sum_over_difference(7, 5)\n",
|
||||
"print(result)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "02577028",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"result = sum_over_difference(12, 12)\n",
|
||||
"print(result)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "58fc58c0",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.11.3"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
23
hands_on/debugger/debugger_example.py
Executable file
23
hands_on/debugger/debugger_example.py
Executable file
|
@ -0,0 +1,23 @@
|
|||
def add(arg1, arg2):
|
||||
return arg1 + arg2
|
||||
|
||||
|
||||
def sub(arg1, arg2):
|
||||
return arg1 - arg2
|
||||
|
||||
|
||||
def div(arg1, arg2):
|
||||
return arg1 / arg2
|
||||
|
||||
|
||||
def sum_over_difference(arg1, arg2):
|
||||
"""Compute sum of arguments over difference of arguments."""
|
||||
arg_sum = add(arg1, arg2)
|
||||
arg_diff = sub(arg1, arg2)
|
||||
sum_over_diff = div(arg_sum, arg_diff)
|
||||
return sum_over_diff
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
result = sum_over_difference(7, 5)
|
||||
print(result)
|
33
hands_on/factorial/factorial.py
Normal file
33
hands_on/factorial/factorial.py
Normal file
|
@ -0,0 +1,33 @@
|
|||
""" Compute the factorial of a set of numbers stored in a file. """
|
||||
|
||||
def factorial(n):
|
||||
if n == 0:
|
||||
return 1
|
||||
else:
|
||||
return factorial(n-1) * n
|
||||
|
||||
|
||||
def read_data(filename):
|
||||
numbers = []
|
||||
with open(filename, 'r') as f:
|
||||
for line in f:
|
||||
number = int(line)
|
||||
numbers.append(number)
|
||||
return numbers
|
||||
|
||||
|
||||
def compute_factorials_for_list(numbers):
|
||||
factorials = []
|
||||
for number in numbers:
|
||||
result = factorial(number)
|
||||
factorials.append(result)
|
||||
return factorials
|
||||
|
||||
|
||||
def main():
|
||||
numbers = read_data('numbers.txt')
|
||||
factorials = compute_factorials_for_list(numbers)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
100000
hands_on/factorial/numbers.txt
Normal file
100000
hands_on/factorial/numbers.txt
Normal file
File diff suppressed because it is too large
Load diff
13
hands_on/factorial/test_factorial.py
Normal file
13
hands_on/factorial/test_factorial.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
""" Tests for the factorial function. """
|
||||
|
||||
from factorial import factorial
|
||||
|
||||
|
||||
def test_factorial():
|
||||
factorial_cases = [(1, 1),
|
||||
(0, 1),
|
||||
(5, 2*3*4*5),
|
||||
(30, 265252859812191058636308480000000)]
|
||||
|
||||
for n, fact_n in factorial_cases:
|
||||
assert factorial(n) == fact_n
|
8
hands_on/first/first.py
Normal file
8
hands_on/first/first.py
Normal file
|
@ -0,0 +1,8 @@
|
|||
def times_3(x):
|
||||
""" Multiply x by 3.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : The item to multiply by 3.
|
||||
"""
|
||||
return x * 3
|
19
hands_on/first/test_first.py
Normal file
19
hands_on/first/test_first.py
Normal file
|
@ -0,0 +1,19 @@
|
|||
from first import times_3
|
||||
|
||||
|
||||
def test_times_3_integer():
|
||||
value = 7
|
||||
expected = 21
|
||||
|
||||
result = times_3(value)
|
||||
|
||||
assert result == expected
|
||||
|
||||
|
||||
def test_times_3_string():
|
||||
value = 'wow'
|
||||
expected = 'wowwowwow'
|
||||
|
||||
result = times_3(value)
|
||||
|
||||
assert result == expected
|
8
hands_on/first_teacher/first.py
Normal file
8
hands_on/first_teacher/first.py
Normal file
|
@ -0,0 +1,8 @@
|
|||
def times_3(x):
|
||||
""" Multiply x by 3.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
x : The item to multiply by 3.
|
||||
"""
|
||||
return x * 3
|
10
hands_on/local_maxima/local_maxima.py
Normal file
10
hands_on/local_maxima/local_maxima.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
def find_maxima(x):
|
||||
"""Find local maxima of x.
|
||||
|
||||
Input arguments:
|
||||
x -- 1D list of real numbers
|
||||
|
||||
Output:
|
||||
idx -- list of indices of the local maxima in x
|
||||
"""
|
||||
return []
|
10
hands_on/local_maxima_part2/local_maxima.py
Normal file
10
hands_on/local_maxima_part2/local_maxima.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
def find_maxima(x):
|
||||
"""Find local maxima of x.
|
||||
|
||||
Input arguments:
|
||||
x -- 1D list of real numbers
|
||||
|
||||
Output:
|
||||
idx -- list of indices of the local maxima in x
|
||||
"""
|
||||
return []
|
30
hands_on/local_maxima_part2/test_local_maxima.py
Normal file
30
hands_on/local_maxima_part2/test_local_maxima.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
from local_maxima import find_maxima
|
||||
|
||||
|
||||
def test_find_maxima():
|
||||
values = [1, 3, -2, 0, 2, 1]
|
||||
expected = [1, 4]
|
||||
maxima = find_maxima(values)
|
||||
assert maxima == expected
|
||||
|
||||
|
||||
def test_find_maxima_edges():
|
||||
values = [4, 2, 1, 3, 1, 5]
|
||||
expected = [0, 3, 5]
|
||||
maxima = find_maxima(values)
|
||||
assert maxima == expected
|
||||
|
||||
|
||||
def test_find_maxima_empty():
|
||||
values = []
|
||||
expected = []
|
||||
maxima = find_maxima(values)
|
||||
assert maxima == expected
|
||||
|
||||
|
||||
def test_find_maxima_plateau():
|
||||
raise Exception('not yet implemented')
|
||||
|
||||
|
||||
def test_find_maxima_not_a_plateau():
|
||||
raise Exception('not yet implemented')
|
49
hands_on/local_maxima_part3_debug/local_maxima.py
Normal file
49
hands_on/local_maxima_part3_debug/local_maxima.py
Normal file
|
@ -0,0 +1,49 @@
|
|||
def find_maxima(x):
|
||||
"""Find local maxima of x.
|
||||
|
||||
Input arguments:
|
||||
x -- 1D list of real numbers
|
||||
|
||||
Output:
|
||||
idx -- list of indices of the local maxima in x
|
||||
"""
|
||||
|
||||
maxima = []
|
||||
|
||||
len_x = len(x)
|
||||
if len_x == 0:
|
||||
return maxima
|
||||
|
||||
maxima = check_first_element(x, maxima)
|
||||
maxima = check_last_element(x, maxima)
|
||||
|
||||
# Check numbers in between
|
||||
i = 1
|
||||
while i < len_x - 1:
|
||||
if x[i] > x[i - 1]:
|
||||
# We have found a potential maximum or start of a plateau
|
||||
plateau_start = i
|
||||
while i < len_x - 1 and x[i] == x[i + 1]:
|
||||
i += 1
|
||||
plateau_end = i
|
||||
if x[plateau_end] > x[plateau_end + 1]:
|
||||
maxima.append(plateau_start)
|
||||
i += 1
|
||||
return maxima
|
||||
|
||||
|
||||
def check_first_element(x, maxima):
|
||||
if x[0] > x[1]:
|
||||
maxima.append(0)
|
||||
return maxima
|
||||
|
||||
|
||||
def check_last_element(x, maxima):
|
||||
if x[-1] > x[-2]:
|
||||
maxima.append(len(x) - 1)
|
||||
return maxima
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
result = find_maxima([1, 2, 2, 1])
|
||||
print(result)
|
107
hands_on/local_maxima_part3_debug/test_local_maxima.py
Normal file
107
hands_on/local_maxima_part3_debug/test_local_maxima.py
Normal file
|
@ -0,0 +1,107 @@
|
|||
import numpy as np
|
||||
import pytest
|
||||
|
||||
from local_maxima import find_maxima
|
||||
|
||||
|
||||
def test_find_maxima():
|
||||
values = [1, 3, -2, 0, 2, 1]
|
||||
expected = [1, 4]
|
||||
maxima = find_maxima(values)
|
||||
assert maxima == expected
|
||||
|
||||
|
||||
def test_find_maxima_edges():
|
||||
values = [4, 2, 1, 0, 1, 5]
|
||||
expected = [0, 5]
|
||||
maxima = find_maxima(values)
|
||||
assert maxima == expected
|
||||
|
||||
|
||||
def test_find_maxima_empty():
|
||||
values = []
|
||||
expected = []
|
||||
maxima = find_maxima(values)
|
||||
assert maxima == expected
|
||||
|
||||
|
||||
def test_find_maxima_plateau():
|
||||
values = [1, 2, 2, 1]
|
||||
expected = [1]
|
||||
maxima = find_maxima(values)
|
||||
assert maxima == expected
|
||||
|
||||
|
||||
def test_find_maxima_not_a_plateau():
|
||||
values = [1, 2, 2, 3, 1]
|
||||
expected = [3]
|
||||
maxima = find_maxima(values)
|
||||
assert maxima == expected
|
||||
|
||||
|
||||
# the tests below here fail, can you get them to pass?
|
||||
|
||||
|
||||
def test_find_maxima_correct_order():
|
||||
# TASK: get this test to pass
|
||||
values = [2, 1, 5, 1, 9]
|
||||
expected = [0, 2, 4]
|
||||
maxima = find_maxima(values)
|
||||
assert maxima == expected
|
||||
|
||||
|
||||
def test_find_maxima_one_value():
|
||||
# TASK: get this test to pass
|
||||
values = [1]
|
||||
expected = [0]
|
||||
maxima = find_maxima(values)
|
||||
assert maxima == expected
|
||||
|
||||
|
||||
def test_find_maxima_long_plateau():
|
||||
# TASK: Change the implementation for when there is a plateau
|
||||
# for uneven plateau length, return the middle index, e.g. [1, 2, *2*, 2, 1] --> [2]
|
||||
# for even plateau length, return the index left of the middle e.g. [1, 2, *2*, 2, 2, 1] --> [2]
|
||||
values = [1, 2, 2, 2, 2, 2, 1, 8, 0]
|
||||
expected = [3, 7]
|
||||
maxima = find_maxima(values)
|
||||
assert maxima == expected
|
||||
|
||||
|
||||
def test_find_maxima_plateau_at_end():
|
||||
# TASK: make sure plateaus at the end are handled properly (see test above)
|
||||
values = [1, 2, 2]
|
||||
expected = [1]
|
||||
maxima = find_maxima(values)
|
||||
assert maxima == expected
|
||||
|
||||
|
||||
def test_find_maxima_plateau_at_start():
|
||||
# TASK: make sure plateaus at the start are handled properly (see test above)
|
||||
values = [1, 1, 0, 0]
|
||||
expected = [0]
|
||||
maxima = find_maxima(values)
|
||||
assert maxima == expected
|
||||
|
||||
|
||||
def test_find_maxima_all_same_values():
|
||||
# TASK: implement a check for lists where there is no local maximum
|
||||
values = [1, 1]
|
||||
expected = [0]
|
||||
maxima = find_maxima(values)
|
||||
assert maxima == expected
|
||||
|
||||
|
||||
def test_find_maxima_letters():
|
||||
# stings can be evaluated with > and <, who knew!
|
||||
# Find an easy solution so that both "t"s are recognised as local maxima
|
||||
values = ["T", "e", "s", "t", "s", "!"]
|
||||
expected = [0, 3]
|
||||
maxima = find_maxima(values)
|
||||
assert maxima == expected
|
||||
|
||||
|
||||
def test_find_maxima_new_inputs_to_make_current_function_fail():
|
||||
# should you actually be done with all tests, then you can think of other cases where the current function fails
|
||||
# and write tests for them and fix them
|
||||
assert False
|
1
hands_on/logistic_fun/readme.md
Normal file
1
hands_on/logistic_fun/readme.md
Normal file
|
@ -0,0 +1 @@
|
|||
This exercise is in a separate repo!
|
22
hands_on/numpy_equality/test_numpy_equality.py
Normal file
22
hands_on/numpy_equality/test_numpy_equality.py
Normal file
|
@ -0,0 +1,22 @@
|
|||
import numpy as np
|
||||
|
||||
|
||||
def test_equality():
|
||||
x = np.array([1, 1])
|
||||
y = np.array([2, 2])
|
||||
z = np.array([3, 3])
|
||||
assert x + y == z
|
||||
|
||||
|
||||
def test_equality_with_nan():
|
||||
x = np.array([1, np.nan])
|
||||
y = np.array([2, np.nan])
|
||||
z = np.array([3, np.nan])
|
||||
assert x + y == z
|
||||
|
||||
|
||||
def test_allclose_with_nan():
|
||||
x = np.array([1.1, np.nan])
|
||||
y = np.array([2.2, np.nan])
|
||||
z = np.array([3.3, np.nan])
|
||||
assert x + y == z
|
Loading…
Add table
Add a link
Reference in a new issue