Skip to content

Chapter 1 · Introduction to Automated Testing and pytest ​

Chapter goals: understand what "automated testing" actually tests, install pytest, and write and run your first test.

1.1 What Is Automated Testing ​

Manual testing means "a human opens the page, clicks around, and eyeballs the result"; automated testing turns those checks into code so the machine re-runs them automatically on every change. Every test boils down to three steps:

  1. Arrange — construct inputs and dependencies;
  2. Act — invoke the code under test;
  3. Assert — use assert to check whether the result matches expectations.

Why pytest

pytest is the de facto standard testing framework in the Python ecosystem: minimal syntax (plain assert works), a huge plugin ecosystem (400+ plugins), and adoption by mainstream projects such as FastAPI, pandas, and requests. This tutorial targets the current pytest 9.x.

1.2 Installation and Verification ​

bash
python -m venv .venv && source .venv/bin/activate
pip install pytest

Verify the installation:

bash
pytest --version
# pytest 9.x.x

1.3 Your First Test ​

pytest makes only two conventions about test files:

  • The filename must be test_*.py or *_test.py;
  • Test function names must start with test_.

Create test_demo.py:

python
# test_demo.py
def add(a, b):
    return a + b


def test_add_two_positive_numbers():
    assert add(2, 3) == 5


def test_add_negative_numbers():
    assert add(-1, -2) == -3

Run it:

bash
$ pytest -v
================= test session starts =================
collected 2 items

test_demo.py::test_add_two_positive_numbers PASSED
test_demo.py::test_add_negative_numbers PASSED

================== 2 passed in 0.01s ==================

1.4 What pytest Tells You When Tests Fail ​

Deliberately write a failing test:

python
def test_failed_example():
    assert add(2, 2) == 5

pytest's killer feature is assertion rewriting: when something fails, the output doesn't just print a bare AssertionError — it prints every intermediate value in the expression:

text
>       assert add(2, 2) == 5
E       assert 4 == 5
E        +  where 4 = add(2, 2)

The line where 4 = add(2, 2) tells you exactly what the function returned — an experience unittest's self.assertEqual cannot offer.

1.5 What Should a Test Actually Verify? ​

Two common beginner mistakes:

  • ❌ Cramming a dozen unrelated assertions into one test function (when it fails you lose track of which step broke);
  • ❌ Testing the language itself just to chase coverage (assert isinstance([], list) has zero value).

A good unit test tests behavior, not implementation. For add, you care about "adding two numbers yields the correct sum", not whether it uses + or bit tricks internally.

1.6 Chapter Summary ​

  • Automated testing = the Arrange / Act / Assert cycle;
  • pytest discovers tests by naming conventions: test_*.py files plus test_-prefixed functions;
  • Plain assert statements are all you need; assertion rewriting produces detailed failure output;
  • Test behavior, not implementation.

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. Which filename will pytest collect by default?

2. What is the correct way to write assertions in pytest?

3. Test function test_add outputs "F" in the progress dots. What does it mean?

4. Regarding "good unit tests", which statement is correct?

🛠️ Hands-On Exercises ​

  1. Add 3 more edge-case tests for this chapter's add function: zero, floats, and very large integers.
  2. Create a strings.py implementing slugify(text) (replace spaces with -, lowercase everything), and write at least 3 tests for it.
  3. Deliberately break a test, observe the where ... lines in pytest's output, then restore the correct version.

After finishing, run pytest -v and make sure everything passes before moving on to Chapter 2.