Python

Python Automation #5: Reporting Results — Email, Slack, and Discord Notifications
6 min read

Python Automation #5: Reporting Results — Email, Slack, and Discord Notifications

The last piece of automation is reporting. Send Slack and Discord notifications with a single httpx POST, email Excel attachments with smtplib, and keep tokens out of your code with a .env file.

Python Automation #4: Web Scraping Part 2 — Dynamic Pages with Playwright
5 min read

Python Automation #4: Web Scraping Part 2 — Dynamic Pages with Playwright

Handle JavaScript-rendered pages that return empty HTML to requests by driving a real browser with Playwright. From install and a first script to wait_for_selector, login automation, infinite scroll, and saving to CSV — all in one pass.

Python Automation #3: Web Scraping Part 1 — Static Pages with httpx and BeautifulSoup
6 min read

Python Automation #3: Web Scraping Part 1 — Static Pages with httpx and BeautifulSoup

Let code read the price, notice, and stock pages you check by hand every day. We fetch HTML with httpx, pick out just the data we need with BeautifulSoup CSS selectors, and save it to CSV — static page scraping from start to finish.

Python Automation #2: Excel Automation — Ending Repetitive Reports with openpyxl
6 min read

Python Automation #2: Excel Automation — Ending Repetitive Reports with openpyxl

Read Excel files with openpyxl, merge per-branch reports from a folder into a single sheet, and finish with header styling and number formats. We also cover the formula and data_only pitfalls, merged cells, and large-file performance.

Python Automation #1: Ending Repetitive Work — First Scripts and File Organizing
6 min read

Python Automation #1: Ending Repetitive Work — First Scripts and File Organizing

Learn the basic shape of an automation script by building a downloads-folder organizer in Python. We sort and move files with pathlib, add a dry-run safety net, and wire up argparse arguments — one full cycle from start to finish.

Python Testing #7: Running Tests in CI — People Forget, Machines Don't
5 min read

Python Testing #7: Running Tests in CI — People Forget, Machines Don't

Build a CI workflow that runs pytest automatically with GitHub Actions. Covers uv caching, a Python version matrix, coverage comments on PRs, pre-commit, and separating slow tests to wrap up the series.

Python Testing #6: Test Design — Good Tests and How to Read Coverage
6 min read

Python Testing #6: Test Design — Good Tests and How to Read Coverage

Test design fundamentals from the AAA pattern and behavior-driven tests to test double terminology, dealing with flaky tests, and reading pytest-cov coverage numbers the right way.

Python Testing #5: Testing the Outside World — Files, HTTP, Databases, and Web Frameworks
6 min read

Python Testing #5: Testing the Outside World — Files, HTTP, Databases, and Web Frameworks

A test that mocks everything guarantees nothing about real behavior. A strategy for testing the outside world: write real files with tmp_path, block only the network boundary with respx, and reset databases with transaction rollbacks.

Python Testing #4 mock and monkeypatch: Controlling What You Can't Control
7 min read

Python Testing #4 mock and monkeypatch: Controlling What You Can't Control

How to pin down dependencies that change on every run — time, randomness, external APIs — with monkeypatch and unittest.mock, including the patch-path trap and where over-mocking begins.

Python Testing #3 parametrize and Markers: Multiply Cases, Run Selectively
5 min read

Python Testing #3 parametrize and Markers: Multiply Cases, Run Selectively

How to collapse input-only test variations into one case table with @pytest.mark.parametrize, and run only the tests you want using skip, skipif, xfail, custom markers, and the -m and -k options.

Python Testing #2 Fixtures: Injecting Setup and Teardown
6 min read

Python Testing #2 Fixtures: Injecting Setup and Teardown

How to inject test setup code with @pytest.fixture — yield teardown, scope trade-offs, sharing via conftest.py, and built-in fixtures like tmp_path.

Python Testing #1 Getting Started with pytest: Why One assert Is All You Need
7 min read

Python Testing #1 Getting Started with pytest: Why One assert Is All You Need

How to install pytest and write your first test with a single assert — plus how it differs from unittest, how to read failure output, and the test discovery rules.