Skip to content

Commit

Permalink
Fixed tests. (#223)
Browse files Browse the repository at this point in the history
* Fixed tests.

* Improved wording of exercise

* Update input_output.ipynb

Co-authored-by: Despina Adamopoulou <16343312+despadam@users.noreply.github.com>

* Fixed test for print_odd exercise

* Fixed error message

* Fixed another misleading error message

* Fixed TOC.

* updating TOC and titles for exercise sections

---------

Co-authored-by: Despina Adamopoulou <16343312+despadam@users.noreply.github.com>
Co-authored-by: Despina Adamopoulou <despoina.adamopoulou@empa.ch>
  • Loading branch information
3 people authored May 3, 2024
1 parent 5442f1a commit dfe2bba
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 66 deletions.
107 changes: 56 additions & 51 deletions input_output.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,30 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"## Table of contents\n",
"\n",
"- [String input](#String-input)\n",
"- [File I/O](#File-I/O)\n",
"- [Writing to a file](#Writing-to-a-file)\n",
"- [Context managers](#Context-managers)\n",
"- [Binary I/O](#Binary-I/O)\n",
" - [Bytes and strings](#Bytes-and-strings)\n",
" - [Converting bytes to text](#Converting-bytes-to-text)\n",
"- [Reading/Writing CSV files](#Reading/Writing-CSV-files)\n",
"- [Exercises](#Exercises)\n",
"# Table of Contents\n",
" - [References](#References)\n",
" - [Introduction](#Introduction)\n",
" - [String input and output ](#String-input-and-output)\n",
" - [String output](#String-output)\n",
" - [String input](#String-input)\n",
" - [Warm-up exercises](#Warm-up-exercises)\n",
" - [File I/O](#File-I/O)\n",
" - [Paths](#Paths)\n",
" - [Exercises on Paths](#Exercises-on-Paths)\n",
" - [Reading from a file](#Reading-from-a-file)\n",
" - [Writing to a file](#Writing-to-a-file)\n",
" - [Exercises on file reading and writing](#Exercises-on-file-reading-and-writing)\n",
" - [Context managers](#Context-managers)\n",
" - [Binary I/O](#Binary-I/O)\n",
" - [Bytes and strings](#Bytes-and-strings)\n",
" - [Converting bytes to text ](#Converting-bytes-to-text)\n",
" - [Reading/Writing CSV files](#Reading/Writing-CSV-files)\n",
" - [Exercises](#Exercises)\n",
" - [Exercise 1: CSV to dictionary 🌶️🌶️](#Exercise-1:-CSV-to-dictionary-🌶️🌶️)\n",
" - [Exercise 2: Counting words 🌶️](#Exercise-2:-Counting-words-🌶️)\n",
" - [Exercise 3: Letter statistics 🌶️🌶️](#Exercise-3:-Letter-statistics-🌶️🌶️)\n",
" - [Exercise 4: Translating words 🌶️🌶️](#Exercise-4:-Translating-words-🌶️🌶️)\n",
" - [Exercise 5: Binary format 🌶️🌶️🌶️](#Exercise-5:-Binary-format-🌶️🌶️🌶️)\n"
" - [Exercise 5: Binary format 🌶️🌶️🌶️](#Exercise-5:-Binary-format-🌶️🌶️🌶️)"
]
},
{
Expand Down Expand Up @@ -120,7 +129,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### Exercises"
"### Warm-up exercises"
]
},
{
Expand Down Expand Up @@ -356,7 +365,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### Exercises"
"### Exercises on Paths"
]
},
{
Expand Down Expand Up @@ -505,37 +514,6 @@
"This is the most *pythonic* way to read a file line-by-line instead of reading the full contents at once."
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"### Exercises"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"1. Modify the function `solution_read_file` to return the content of the file passed as the `input_file` argument. Return the content as a **list of strings**, one string per line.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%ipytest\n",
"\n",
"from pathlib import Path\n",
"\n",
"def solution_read_file(input_file: Path) -> \"list[str]\": \n",
" \"\"\"Write your solution here\"\"\"\n",
" pass"
]
},
{
"attachments": {},
"cell_type": "markdown",
Expand Down Expand Up @@ -605,7 +583,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"### Exercises"
"### Exercises on file reading and writing"
]
},
{
Expand All @@ -622,7 +600,30 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"1. Modify the function `solution_write_file` to write the sentence \"python tutorial 2023\" (**without quotes**) to the file `output_file`, which is available as a `Path` object as argument to the function."
"1. Modify the function `solution_read_file` to return the content of the file passed as the `input_file` argument. Return the content as a **list of strings**, one string per line.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"%%ipytest\n",
"\n",
"from pathlib import Path\n",
"\n",
"def solution_read_file(input_file: Path) -> \"list[str]\": \n",
" \"\"\"Write your solution here\"\"\"\n",
" pass"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"2. Modify the function `solution_write_file` to write the sentence \"python tutorial 2023\" (**without quotes**) to the file `output_file`, which is available as a `Path` object as argument to the function."
]
},
{
Expand All @@ -647,7 +648,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"1. Modify the function `solution_read_write_file` to read the lines from the file `input_file` and write them in the form `line, length`, to the file `output_file`. Here `line` is the line of text in `input_file` **without the line ending**, `length` is **number of characters** in that line.\n",
"3. Modify the function `solution_read_write_file` to read the lines from the file `input_file` and write them in the form `line, length`, to the file `output_file`. Here `line` is the line of text in `input_file` **without the line ending**, `length` is **number of characters** in that line.\n",
"If `input_file` contains these lines:\n",
" ```\n",
" first\n",
Expand Down Expand Up @@ -1104,7 +1105,7 @@
"tags": []
},
"source": [
"Write a function to read all the lines from [`lines.txt`](./tutorial/tests/data/lines.txt) and count the number of words in the file. The solution should be a single number.\n",
"Write a function to read all the lines from `input_file` and count the number of words in the file. The solution should be a single number.\n",
"\n",
"For example, for the file\n",
"```\n",
Expand All @@ -1118,7 +1119,11 @@
"\n",
"<div class=\"alert alert-block alert-info\">\n",
" <h4><b>Hint</b></h4>\n",
" The file is available as the parameter <code>input_file</code> of <code>solution_exercise2</code> function\n",
" <ul>\n",
" <li>The file is available as the parameter <code>input_file</code> of <code>solution_exercise2</code> function</li>\n",
" <li>A word consists of printable characters without line ends and spaces</li>\n",
" </ul>\n",
" \n",
"</div>\n",
"\n",
"\n"
Expand Down Expand Up @@ -1338,7 +1343,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.4"
"version": "3.10.14"
},
"vscode": {
"interpreter": {
Expand Down
5 changes: 5 additions & 0 deletions tutorial/tests/data/lines2.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
this file has
more words in each
line
but it is shorter I think
I hope you have fun solving this exercise
45 changes: 30 additions & 15 deletions tutorial/tests/test_input_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,24 @@ def get_data(name: str, data_dir: str = "data") -> pl.Path:
return (pl.Path.cwd() / f"tutorial/tests/{data_dir}/{name}").resolve()


def reference_print_odd(num: int) -> None:
for i in range(num):
def reference_print_odd(n: int) -> None:
for i in range(n):
if i % 2 != 0:
print(i)


@pytest.mark.parametrize("num", [1, 2, 3, 4, 5])
def test_print_odd(function_to_test, num: int):
@pytest.mark.parametrize("n", [1, 2, 3, 4, 5])
def test_print_odd(function_to_test, n: int):
with StringIO() as solution_stdout, StringIO() as reference_stdout:
with contextlib.redirect_stdout(solution_stdout):
function_to_test(num)
function_to_test(n)
solution_text = solution_stdout.getvalue()

with contextlib.redirect_stdout(reference_stdout):
reference_print_odd(num)
reference_print_odd(n)
reference_text = reference_stdout.getvalue()

assert reference_stdout.getvalue() == solution_stdout.getvalue()
assert solution_text == reference_text


def reference_find_all_files(f: pl.Path) -> List[pl.Path]:
Expand Down Expand Up @@ -73,16 +75,26 @@ def test_write_file(function_to_test, tmp_path: pl.Path):
function_to_test(tmp_user)
reference_write_file(tmp_test)

if not tmp_user.exists():
pytest.fail("Cannot read from inexistent file.")
assert (
tmp_user.exists()
), """The file was not created. Make sure to create the file in the function. Hint: use `open(output_file, "w")`"""

assert tmp_user.read_text() == tmp_test.read_text()
assert (
tmp_user.read_text() == tmp_test.read_text()
), "The file content is not correct."


def reference_read_write_file(input_file: pl.Path, output_file: pl.Path) -> None:
# We open the input and output file at the same time
with input_file.open("r") as read_file, output_file.open("w") as write_file:
# Here we iterate over each line of the input file
for line in read_file.readlines():
write_file.write("{}, {}\n".format(line.strip("\n\r"), len(line)))
# We remove line breaks and write the line to the output file
clean_line = line.strip("\n\r")
# We crete the output line
output_line = f"{clean_line}, {len(clean_line)}\n"
# Finally we write the line and its length to the output file
write_file.write(output_line)


def test_read_write_file(function_to_test, tmp_path: pl.Path):
Expand All @@ -92,6 +104,7 @@ def test_read_write_file(function_to_test, tmp_path: pl.Path):

function_to_test(input_file, output_file)
reference_read_write_file(input_file, test_output_file)
assert output_file.exists(), "The output file was not created."

assert output_file.read_text() == test_output_file.read_text()

Expand All @@ -105,8 +118,9 @@ def reference_exercise1(file: pl.Path) -> Dict[str, List[str]]:
}


def test_exercise1(function_to_test):
f = get_data("example.csv")
@pytest.mark.parametrize("file", ["example.csv"])
def test_exercise1(function_to_test, file: str):
f = get_data(file)
assert function_to_test(f) == reference_exercise1(f)


Expand All @@ -121,8 +135,9 @@ def reference_exercise2(file: pl.Path) -> int:
)


def test_exercise2(function_to_test):
f = get_data("lines.txt")
@pytest.mark.parametrize("file", ["lines.txt", "lines2.txt"])
def test_exercise2(function_to_test, file: str):
f = get_data(file)
assert function_to_test(f) == reference_exercise2(f)


Expand Down

0 comments on commit dfe2bba

Please sign in to comment.