Skip to content

Commit 988598f

Browse files
committed
Add screenshots for debugging in VS Code
1 parent 0f6dd9a commit 988598f

12 files changed

Lines changed: 130 additions & 99 deletions

episodes/12-virtual-environments.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ using `venv` and manage packages using `pip`.
203203

204204
:::::::::::::::::::::::::::::::::::::::::: prereq
205205

206-
## Making Sure You Can Invoke Python
206+
### Making Sure You Can Invoke Python
207207

208208
You can test your Python installation from the command line with:
209209

@@ -496,11 +496,9 @@ python3 -m pip install --editable .
496496

497497
::::::::::::::::::::::::::::::::::::::::: spoiler
498498

499-
### This command fails for me
500-
501-
If your `pip` installation is older than version 21.3, then this command will probably fail for you.
502-
This is because these older versions of `pip` do not support `pyproject.toml` as the package metadata.
503-
Given these versions of `pip` are now over 4 years old, we strongly recommend that you update `pip` if you can:
499+
If the above command fails for you - your `pip` installation is older than version 21.3.
500+
Such older versions of `pip` do not support `pyproject.toml` as the package metadata.
501+
Given these versions of `pip` are now over 4 years old, we strongly recommend that you update `pip` if you can with:
504502

505503
```bash
506504
python3 -m pip install --upgrade pip

episodes/14-collaboration-using-git.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,9 +271,9 @@ In the above command,
271271
when you run `git clone remote_url` command to replicate a remote repository locally);
272272
`main` is the name of our main (and currently only) development branch.
273273

274-
::::::::::::::::::::::::::::::::::::::::: callout
274+
::::::::::::::::::::::::::::::::::::::::: caution
275275

276-
## GitHub Authentication/Authorisation Error
276+
### GitHub Authentication/Authorisation Error
277277

278278
If, at this point (i.e. the first time you try to write to a remote repository on GitHub),
279279
you get a warning/error that HTTPS access is deprecated, or a personal access token is required,
@@ -291,7 +291,7 @@ $ git remote set-url origin git@github.com:<YOUR_GITHUB_USERNAME>/python-interme
291291

292292
::::::::::::::::::::::::::::::::::::::::: callout
293293

294-
## Git Remotes
294+
### Git Remotes
295295

296296
Note that systems like Git allow us to synchronise work between
297297
any two or more copies of the same repository -

episodes/24-diagnosing-issues-improving-robustness.md

Lines changed: 123 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -185,36 +185,54 @@ Debuggers allow us to peer at the internal workings of a program,
185185
such as variables and other state,
186186
as it performs its functions.
187187

188-
### Running Tests in IDE
188+
Firstly, to make it easier to track what's going on, we can set up our IDE to run and debug our tests instead of running them from the command line.
189189

190-
Firstly, to make it easier to track what's going on, we can set up our IDE to run and debug our tests
191-
instead of running them from the command line.
190+
### Configuring the Test Framework
192191

193192
::: group-tab
194193

195194
### PyCharm
196195

197-
If you have not done so already,
198-
you will first need to enable the Pytest framework in PyCharm.
196+
If you have not done so already, you will first need to enable the Pytest framework in PyCharm.
199197
You can do this by:
200198

201-
1. Select either `PyCharm` > `Preferences` (Mac) or `File` > `Settings` (Linux, Windows).
202-
2. Then, in the preferences window that appears,
203-
select `Tools` -> `Python integrated tools` > from the left.
199+
1. Select either `PyCharm` > `Preferences` (Mac) or `File -> Settings` (Linux, Windows).
200+
2. Then, in the preferences window that appears, select `Tools -> Python integrated tools` from the left.
204201
3. Under `Testing`, for `Default test runner` select `pytest`.
205202
4. Select `OK`.
206203

207204
![](fig/pycharm-test-framework.png){alt='Setting up test framework in PyCharm' .image-with-shadow width="1000px"}
208205

209-
We can now run `pytest` over our tests in PyCharm,
210-
similarly to how we ran our `inflammation-analysis.py` script before.
211-
Right-click the `test_models.py` file
212-
under the `tests` directory in the file navigation window on the left,
213-
and select `Run 'pytest in test_model...'`.
206+
207+
### VS Code
208+
209+
If you have not done so already, you will first need to confugure the Pytest framework in VS Code.
210+
Open the Test Explorer view (click on the test beaker icon on the VS Code Activity Bar on the left hand side).
211+
212+
You should see a `Configure Python Tests` button if a test framework is not enabled.
213+
Clicking on it prompts you to select a test framework and a folder containing your tests.
214+
215+
![](fig/vscode-test-framework.png){alt='Setting up test framework in VS Code' .image-with-shadow width="1000px"}
216+
217+
![](fig/vscode-configure-pytest.png){alt='Setting up test framework in VS Code' .image-with-shadow width="1000px"}
218+
219+
Tests can be configured anytime by using the `Python: Configure Tests` command from the Command Palette
220+
or by setting `python.testing.pytestEnabled` in the Settings editor or `settings.json` file (described in the VS Code Settings in the [episode on IDEs](/13-ides.md)).
221+
Each testing framework also has further specific configuration settings as described in the [Test configuration settings of the VS Code documentation for Python](https://code.visualstudio.com/docs/python/testing#_test-configuration-settings).
222+
223+
:::
224+
225+
### Running the Tests
226+
227+
We can now run `pytest` over our tests in the IDE, similarly to how we ran our `inflammation-analysis.py` script before.
228+
229+
::: group-tab
230+
231+
### PyCharm
232+
233+
Right-click the `test_models.py` file under the `tests` directory in the file navigation window on the left, and select `Run 'pytest in test_model...'`.
214234
You'll see the results of the tests appear in PyCharm in a bottom panel.
215-
If you scroll down in that panel you should see
216-
the failed `test_patient_normalise()` test result
217-
looking something like the following:
235+
If you scroll down in that panel you should see the failed `test_patient_normalise()` test result looking something like the following:
218236

219237
![](fig/pytest-pycharm-run-tests.png){alt='Running pytest in PyCharm' .image-with-shadow width="1000px"}
220238

@@ -239,45 +257,41 @@ so select any others you see and click the `-` button at the top to remove them.
239257
This will avoid any confusion when running our tests separately.
240258
Click `OK` when done.
241259

260+
Note that, whenever a Python program prints text to the terminal or to a file, it first stores this text in an **output buffer**.
261+
When the buffer becomes full or is **flushed**, the contents of the buffer are written to the terminal / file in one go and the buffer is cleared.
262+
This is usually done to increase performance by effectively converting multiple output operations into just one.
263+
Printing text to the terminal is a relatively slow operation, so in some cases this can make quite a big difference to the total execution time of a program.
264+
265+
However, using buffered output can make debugging more difficult, as we can no longer be quite sure when a log message will be displayed.
266+
In order to make debugging simpler, PyCharm automatically adds the environment variable `PYTHONUNBUFFERED` we see in the screenshot above, which disables output buffering.
267+
268+
Now, if you select the green arrow next to a test function in our `test_models.py` script in PyCharm, and select `Run 'pytest in test_model...'`, we can run just that test:
269+
270+
![](fig/pytest-pycharm-run-single-test.png){alt='Running a single test in PyCharm' .image-with-shadow width="800px"}
271+
272+
Click on the "run" button next to `test_patient_normalise`, and you will be able to see that PyCharm runs just that test function, and we see the same `AssertionError` that we saw before.
273+
242274
### VS Code
243275

244-
:::
276+
In VS Code - one you have configured the test framework to use - you can run tests either from the Project Explorer or Test Explorer in the VS Code Activity Bar.
245277

246-
::::::::::::::::::::::::::::::::::::::::: callout
278+
From the Project Explorer, right-click on the test folder and select "Run Tests".
247279

248-
## Buffered Output
280+
![](fig/vscode-run-tests-project-explorer.png){alt='Running pytest in VS Code from the Project Explorer' .image-with-shadow width="1000px"}
249281

250-
Whenever a Python program prints text to the terminal or to a file,
251-
it first stores this text in an **output buffer**.
252-
When the buffer becomes full or is **flushed**,
253-
the contents of the buffer are written to
254-
the terminal / file in one go and the buffer is cleared.
255-
This is usually done to increase performance
256-
by effectively converting multiple output operations into just one.
257-
Printing text to the terminal is a relatively slow operation,
258-
so in some cases this can make quite a big difference
259-
to the total execution time of a program.
282+
Alternatively, from the Test Explorer view in VS Code (click on the test beaker icon on the VS Code Activity Bar on the left hand side) - locate `python-intermediate-inflammation` and hover over it.
283+
You will see a few "run" buttons next to it - click either the play button (`Run Test`) or the play button with the little check (`Run Test with Coverage`).
260284

261-
However, using buffered output can make debugging more difficult,
262-
as we can no longer be quite sure when a log message will be displayed.
263-
In order to make debugging simpler,
264-
PyCharm automatically adds the environment variable `PYTHONUNBUFFERED`
265-
we see in the screenshot above,
266-
which disables output buffering.
285+
![](fig/vscode-run-tests-test-explorer.png){alt='Running pytest in VS Code from the Test Explorer' .image-with-shadow width="1000px"}
267286

287+
In either case, you should get the test results on the test results pane at the bottom of the window and you should see the same `AssertionError` that we saw before from the command line.
268288

269-
::::::::::::::::::::::::::::::::::::::::::::::::::
289+
Once we have run all our tests - you can run an individual (single) test from the test result pane or from the Test Explorer view (e.g. just the failing test) without rerunning all.
270290

271-
Now, if you select the green arrow next to a test function
272-
in our `test_models.py` script in PyCharm,
273-
and select `Run 'pytest in test_model...'`,
274-
we can run just that test:
291+
![](fig/vscode-run-individual-test.png){alt='Running individual test Test Explorer in VS Code' .image-with-shadow width="1000px"}
275292

276-
![](fig/pytest-pycharm-run-single-test.png){alt='Running a single test in PyCharm' .image-with-shadow width="800px"}
293+
:::
277294

278-
Click on the "run" button next to `test_patient_normalise`,
279-
and you will be able to see that PyCharm runs just that test function,
280-
and we see the same `AssertionError` that we saw before.
281295

282296
### Running the Debugger
283297

@@ -286,39 +300,27 @@ what is happening inside the `patient_normalise` function.
286300
To do this we will add a *breakpoint* in the code.
287301
A breakpoint will pause execution at that point allowing us to explore the state of the program.
288302

289-
To set a breakpoint, navigate to the `models.py` file
290-
and move your mouse to the `return` statement of the `patient_normalise` function.
291-
Click to just to the right of the line number for that line
292-
and a small red dot will appear,
293-
indicating that you have placed a breakpoint on that line.
303+
To set a breakpoint, navigate to the `models.py` file and move your mouse to the `return` statement of the `patient_normalise` function.
304+
Click to just to the right of the line number for that line and a small red dot will appear, indicating that you have placed a breakpoint on that line.
305+
306+
::: group-tab
307+
308+
### PyCharm
294309

295310
![](fig/pytest-pycharm-set-breakpoint.png){alt='Setting a breakpoint in PyCharm' .image-with-shadow width="600px"}
296311

297-
Now if you select the green arrow next to the `test_patient_normalise` function
298-
and instead select `Debug 'pytest in test_model...'`,
299-
you will notice that execution will be paused
300-
at the `return` statement of `patient_normalise`.
301-
In the debug panel that appears below,
302-
we can now investigate the exact state of the program
303-
prior to it executing this line of code.
312+
Now if you select the green arrow next to the `test_patient_normalise` function and instead select `Debug 'pytest in test_model...'`,
313+
you will notice that execution will be paused at the `return` statement of `patient_normalise`.
314+
In the debug panel that appears below, we can now investigate the exact state of the program prior to it executing this line of code.
304315

305-
In the debug panel below,
306-
in the `Debugger` tab you will be able to see
307-
two sections that looks something like the following:
316+
In the debug panel below, in the `Debugger` tab you will be able to see two sections that looks something like the following:
308317

309318
![](fig/pytest-pycharm-debug.png){alt='Debugging in PyCharm' .image-with-shadow width="1000px"}
310319

311-
- The `Frames` section on the left,
312-
which shows the **call stack**
313-
(the chain of functions that have been executed to lead to this point).
314-
We can traverse this chain of functions if we wish,
315-
to observe the state of each function.
316-
- The `Variables` section on the right,
317-
which displays the local and global variables currently in memory.
318-
You will be able to see the `data` array
319-
that is input to the `patient_normalise` function,
320-
as well as the `max` local array
321-
that was created to hold the maximum inflammation values for each patient.
320+
- The `Frames` section on the left, which shows the **call stack** (the chain of functions that have been executed to lead to this point).
321+
We can traverse this chain of functions if we wish, to observe the state of each function.
322+
- The `Variables` section on the right, which displays the local and global variables currently in memory.
323+
You will be able to see the `data` array that is input to the `patient_normalise` function, as well as the `max` local array that was created to hold the maximum inflammation values for each patient.
322324

323325
We also have the ability run any Python code we wish at this point
324326
to explore the state of the program even further!
@@ -332,9 +334,22 @@ in the return line of the function.
332334

333335
![](fig/pytest-pycharm-console.png){alt='Debugging in PyCharm' .image-with-shadow width="1000px"}
334336

335-
Now, looking at the `max` variable,
336-
we can see that something looks wrong,
337-
as the maximum values for each patient do not correspond to the `data` array.
337+
### VS Code
338+
339+
![](fig/vscode-set-breakpoint.png){alt='Setting a breakpoint in VS Code' .image-with-shadow width="600px"}
340+
341+
Now if you select the `test_patient_normalise` function in the Test Explorer and instead select `Debug Test` option,
342+
you will notice that execution will be paused at the `return` statement of `patient_normalise`.
343+
In the debug panel that appears below, we can now investigate the exact state of the program prior to it executing this line of code.
344+
345+
![](fig/vscode-debug-window.png){alt='Debugging in VS Code - Variable values' .image-with-shadow width="1000px"}
346+
347+
The `Variables` section on the left displays the local and global variables currently in memory.
348+
You will be able to see the `data` array that is input to the `patient_normalise` function, as well as the `max` local array that was created to hold the maximum inflammation values for each patient.
349+
350+
:::
351+
352+
Now, looking at the `max` variable, we can see that something looks wrong, as the maximum values for each patient do not correspond to the `data` array.
338353
Recall that the input `data` array we are using for the function is
339354

340355
```python
@@ -343,26 +358,38 @@ Recall that the input `data` array we are using for the function is
343358
[7, 8, 9]]
344359
```
345360

346-
So the maximum inflammation for each patient should be `[3, 6, 9]`,
347-
whereas the debugger shows `[7, 8, 9]`.
348-
You can see that the latter corresponds exactly to the last column of `data`,
349-
and we can immediately conclude that
350-
we took the maximum along the wrong axis of `data`.
351-
Now we have our answer,
352-
stop the debugging process by selecting
353-
the red square at the top right of the main PyCharm window.
354-
355-
So to fix the `patient_normalise` function in `models.py`,
356-
change `axis=0` in the first line of the function to `axis=1`.
357-
With this fix in place,
358-
running all the tests again should result in all tests passing.
359-
Navigate back to `test_models.py` in PyCharm,
360-
right click `test_models.py`
361-
and select `Run 'pytest in test_model...'`.
362-
You should be rewarded with:
361+
So the maximum inflammation for each patient should be `[3, 6, 9]`, whereas the debugger shows `[7, 8, 9]`.
362+
You can see that the latter corresponds exactly to the last column of `data`, and we can immediately conclude that we took the maximum along the wrong axis of `data`.
363+
Now we have our answer, stop the debugging process.
364+
365+
::: group-tab
366+
367+
### PyCharm
368+
369+
In PyCharm you can stop debugging by selecting the red square at the top right of the main PyCharm window.
370+
371+
### VS Code
372+
373+
In VS Code you can stop debugging by selecting `Run -> Stop Debugging` from the top menu.
374+
375+
:::
376+
377+
So to fix the `patient_normalise` function in `models.py`, change `axis=0` in the first line of the function to `axis=1`.
378+
With this fix in place, running all the tests again should result in all tests passing.
379+
380+
::: group-tab
381+
382+
### PyCharm
363383

364384
![](fig/pytest-pycharm-all-tests-pass.png){alt='All tests in PyCharm are successful' .image-with-shadow width="1000px"}
365385

386+
387+
### VS Code
388+
389+
![](fig/vscode-all-tests-pass.png){alt='All tests in VS Code are successful' .image-with-shadow width="1000px"}
390+
391+
:::
392+
366393
::::::::::::::::::::::::::::::::::::::::: callout
367394

368395
## NumPy Axis
@@ -786,6 +813,12 @@ since this wouldn't work in the test case that uses a string.
786813

787814
If you do the challenge, again, be sure to commit your changes and push them to GitHub.
788815

816+
```bash
817+
$ git add inflammation/models.py tests/test_models.py
818+
$ git commit -m "Add test cases"
819+
$ git push origin test-suite
820+
```
821+
789822
You should not take it too far by trying to code preconditions for every conceivable eventuality.
790823
You should aim to strike a balance between
791824
making sure you secure your function against incorrect use,
1000 KB
Loading
406 KB
Loading
882 KB
Loading
1.23 MB
Loading
1.25 MB
Loading
1.14 MB
Loading
76.1 KB
Loading

0 commit comments

Comments
 (0)