Skip to content

Commit f27c5bd

Browse files
committed
Minor changes to Module 3
1 parent 7193ad7 commit f27c5bd

1 file changed

Lines changed: 39 additions & 37 deletions

File tree

03_testing.qmd

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,10 @@ Automatic testing verifies code is still working.
2525

2626
## Testing workflow
2727

28-
```{mermaid}
29-
flowchart TD
30-
A[Prepare inputs]
31-
B[Describe expected output]
32-
C[Obtain actual output]
33-
D[Compare actual and\n expected output]
34-
35-
A --> B --> C --> D
36-
```
28+
1. Prepare inputs
29+
2. Describe expected output
30+
3. Obtain actual output
31+
4. Compare actual and expected output
3732

3833

3934
## Unit testing
@@ -87,28 +82,16 @@ flowchart TD
8782

8883
## Example
8984

90-
1. get a timeseries of water levels
91-
2. find the maxiumum water level each year
92-
3. create a summary report for the subset of data
93-
94-
---
95-
96-
1. get a timeseries of water levels
97-
98-
```python
99-
def test_get_water_level_includes_start_and_end():
100-
wl = get_water_level(time="2019-01-01", location="Aarhus")
101-
102-
assert len(wl) == 25
103-
```
85+
1. find the maximum water level each year
86+
2. create a summary report for the subset of data
10487

10588
---
10689

107-
2. find the maxiumum water level each year
90+
1. find the maximum water level each year
10891

10992
```python
11093
def test_get_max_water_level():
111-
ts = TimeSeries([1.0, .., 3.0], start = "2019-01-01")
94+
ts = TimeSeries([1.0, 2.0, ..., 3.0], start = "2019-01-01")
11295
max_wls = get_max_water_level(ts, freq="Y")
11396

11497
assert len(max_wls) == 1
@@ -117,15 +100,15 @@ def test_get_max_water_level():
117100

118101
---
119102

120-
3. create a summary report for the subset of data
103+
2. create a summary report for the subset of data
121104

122105
```python
123106
def test_summary_report():
124107
max_wls = [1.0, 2.0, 3.0]
125-
report = summary_report(max_wls)
108+
report = summary_report(max_wls, station="Station A")
126109

127-
assert report.title == "Summary report"
128-
assert report.text == "The maximum water level in 2021 was 3.0 m"
110+
assert report.title == "Summary report - Station A"
111+
assert report.text == "The maximum water level during the year was 3.0 m"
129112
```
130113

131114
## Integration testing
@@ -142,6 +125,25 @@ def test_integration():
142125
```
143126

144127

128+
## Regression testing
129+
130+
::: {.incremental}
131+
132+
* Not a distinct test type, but a process
133+
134+
* A regression = when code changes break previously working behavior
135+
136+
* Regression testing = rerunning your existing test suite after each change
137+
138+
* Test suite grows over time:
139+
140+
- Unit/integration tests
141+
142+
- Tests added for fixed bugs
143+
144+
* Goal: ensure new changes don’t reintroduce old bugs or unexpected behavior
145+
:::
146+
145147
## Testing in VS Code
146148

147149
![](images/vs_code_test.png)
@@ -165,7 +167,7 @@ def test_integration():
165167
```python
166168
@pytest.fixture
167169
def water_level():
168-
return TimeSeries([1.0, .., 3.0], start = "2019-01-01")
170+
return TimeSeries([1.0, ..., 3.0], start = "2019-01-01")
169171

170172
def test_get_max_water_level(water_level):
171173
max_wls = get_max_water_level(water_level, freq="Y")
@@ -180,7 +182,7 @@ def test_get_max_water_level(water_level):
180182
::: {.incremental}
181183

182184
* A measure of how much of your code is tested
183-
* A good test suite should cover all the code
185+
* Aim for high coverage, but focus on meaningful tests
184186
* Install `pytest-cov`
185187
* Run tests with coverage report
186188
- `pytest --cov=myproj`
@@ -225,7 +227,7 @@ TOTAL 353 20 94%
225227

226228
:::
227229

228-
## Tests act as specification
230+
## Tests document expected behavior
229231

230232
```python
231233
def test_operable_period_can_be_missing():
@@ -308,7 +310,7 @@ Readability counts.
308310
+ `KeyError`
309311
+ `ValueError`
310312
+ `FileNotFoundError`
311-
* You can also create your own custom exceptions, e.g. `ModelInitialistionError`, `MissingLicenseError`?
313+
* You can also create your own custom exceptions, e.g. `ModelInitError`, `MissingLicenseError`?
312314

313315
:::
314316

@@ -358,9 +360,9 @@ The same can be done with warnings.
358360

359361
## Linting
360362

361-
A way to check your code for common errors and style issues.
363+
A quick way to check your code for common errors and style issues.
362364

363-
[`ruff`](https://docs.astral.sh/ruff/) is a new tool for linting Python code.
365+
[`ruff`](https://docs.astral.sh/ruff/) is a recent tool for linting Python code.
364366

365367
* syntax errors
366368
* unused imports
@@ -409,7 +411,7 @@ Found 3 errors.
409411
* Formatting code for readability and maintainability is essential.
410412
* `ruff` can be used for code formatting (in addition to linting).
411413
* `ruff` is a faster replacement of `black`, a previously commonly used code formatter.
412-
* It enforces its own rules for formatting, which are only minorly configurable.
414+
* It enforces its own rules for formatting, with limited configurability.
413415
* Having a unified style makes code changes easier to understand and collaborate on.
414416

415417
:::
@@ -461,7 +463,7 @@ Visual Studio Code can be configured to run `ruff format` automatically when sav
461463
```python
462464
import numpy as np
463465

464-
def top_neighbors(points, radius="0.1"):
466+
def top_neighbors(points, radius=0.1):
465467
"""Don't use this function, it's only purpose is to be profiled."""
466468
n = len(points)
467469
idx = np.array([int(x) for x in str.split("0 "* n)])

0 commit comments

Comments
 (0)