Test with real names before Jürgen breaks it
Tests with Bob passed; Jürgen crashed it. Here is a copy-paste list of real names and one test that catches encoding bugs.
The fixture
Paste this list into your tests. The names: Bob, Jürgen, Łukasz, Zoë (typed as e plus a combining accent), O'Brien with a straight and a curly apostrophe, an Arabic name, a Chinese name, and an emoji. The \u escapes keep the file pure ASCII.
import pytest
NAMES = [
pytest.param("Bob", id="ascii"),
pytest.param("J\u00fcrgen", id="umlaut"),
pytest.param("\u0141ukasz", id="stroke-L"),
pytest.param("Zoe\u0308", id="combining"),
pytest.param("O'Brien", id="apostrophe"),
pytest.param("O\u2019Brien", id="curly-apostrophe"),
pytest.param("\u0645\u062d\u0645\u062f", id="rtl"),
pytest.param("\u674e\u96f7", id="cjk"),
pytest.param("Sam \U0001F600", id="emoji"),
]The test
One test runs once per name. pytest.param(..., id=...) gives each case a readable label, and tmp_path is a fresh temporary folder for each test. The fix is encoding="utf-8" on both the write and the read. Point the same loop at your own save and load code.
@pytest.mark.parametrize("name", NAMES)
def test_name_roundtrip(name, tmp_path):
f = tmp_path / "user.txt"
f.write_text(name, encoding="utf-8")
got = f.read_text(encoding="utf-8")
assert got == nameCheck it worked
Run it: all 9 pass. Then delete both encoding= arguments and run it again on Windows. Before Python 3.15 the default is the locale encoding, so any character outside your code page raises UnicodeEncodeError. On code pages 1250 and 1252 the emoji, Arabic, Chinese and combining-accent cases fail. Put the arguments back.
python -m pytest -qPro tip: find every open() without encoding
From Python 3.10, -X warn_default_encoding raises an EncodingWarning each time a file is opened with the locale default. Fix each one in the code. Do not treat -X utf8 or PYTHONUTF8=1 as the fix: they change your run, not your users' machines.
python -X warn_default_encoding -m pytestPro tip: names that look equal are not equal
Testing only Jürgen. The ü exists in code page 1252, so it can pass on a machine where Łukasz, an emoji or an Arabic name fails. It fails on other code pages, such as 1251 (Cyrillic) or 932 (Japanese), and under ASCII. You cannot guess which machine your users have, so one list needs several scripts. Keep Bob in the list too: it is the control.
import unicodedata
a = "Zo\u00eb" # one code point
b = "Zoe\u0308" # e + combining accent
print(a == b) # False
nfc = lambda s: unicodedata.normalize("NFC", s)
print(nfc(a) == nfc(b)) # TrueCommon mistake
Testing only Jürgen. The ü exists in code page 1252, so it can pass on a machine where Łukasz, an emoji or an Arabic name fails. The error comes from characters outside the code page, so one list needs several scripts. Keep Bob in the list too: it is the control.
Official docs
- docs.python.org/3/library/functions.html
- docs.python.org/3/using/cmdline.html
- docs.python.org/3/library/os.html
- docs.python.org/3/library/unicodedata.html
- docs.python.org/3/library/pathlib.html
- docs.pytest.org/en/stable/how-to/parametrize.html
- docs.pytest.org/en/stable/example/parametrize.html
- docs.pytest.org/en/stable/reference/reference.html
- docs.pytest.org/en/stable/how-to/tmp_path.html
- www.unicode.org/reports/tr15
- developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize
One fix of twenty: the whole Claude Code survival kit.
Follow @whyshouldaicareA new disaster and its fix every day. Comment the word under a reel to get its guide.