Software Testing & QA

Testing Web Applications

40 Min.

The test client

def test_home_page_loads(client):
    resp = client.get("/")
    assert resp.status_code == 200
    assert b"PandaDev" in resp.data

Logging in during tests

def login(client, email, password="CorrectHorse9!"):
    return client.post("/auth/login", data={"email": email, "password": password},
                       follow_redirects=True)

CSRF in tests

Most apps disable CSRF in the testing config (WTF_CSRF_ENABLED = False) for convenience. Keep at least one test with it enabled to prove protection works:

def test_post_without_csrf_token_is_rejected(app, client):
    app.config["WTF_CSRF_ENABLED"] = True
    resp = client.post("/collaboration", data={"email": "a@b.com"})
    assert resp.status_code == 400

Test permissions explicitly

Security bugs are usually missing checks. For every protected route, test each kind of user:

import pytest

@pytest.mark.parametrize("role, expected", [
    (None, 404),           # anonymous: the admin area does not reveal itself
    ("user", 404),
    ("sub_admin", 403),    # staff without this permission
    ("admin", 200),
])
def test_staff_page_access(client, make_user, role, expected):
    if role:
        make_user(f"{role}@example.com", role=role)
        login(client, f"{role}@example.com")
    assert client.get("/admin/staff").status_code == expected

Also test ownership: user A must not see or edit user B's data by changing an ID in the URL. That bug class (IDOR) is one of the most common real-world vulnerabilities.

Test the database effects

def test_review_approval_updates_rating(client, admin, project, review):
    client.post(f"/admin/reviews/{review.id}/approve")
    db.session.refresh(project)
    assert project.rating_count == 1

Assert on what changed in the database, not only on the response.

Test input handling

  • Malformed query strings: /projects/filter?category=abc should return 200 or 400, never 500.
  • Over-long input, unicode, HTML and script tags in text fields.
  • Missing required fields.

A smoke test that requests every GET route as each kind of user and asserts no 500s catches a surprising number of bugs cheaply.

Exercise

Write tests for a "delete my comment" route: the owner can delete, another user gets 403 or 404, an anonymous user is redirected to login, and the comment is really gone from the database afterwards.

Ihr Fortschritt wird nur in diesem Browser gespeichert.

Zur Prüfung einreichen (10 Punkte)