Lab Week 10

Overview

Week 10 deepens the work you started in Week 9. You will write a more substantial set of tests for your A3 package, publish a release to TestPyPI, draft your A1 poster, and sit a short group fit interview with your partner.

By the end of today you should have the following.

  1. At least four meaningful tests, including one that uses a fixture or pytest.parametrize.
  2. A successful TestPyPI release of your package.
  3. A clean install of that release in a fresh virtual environment.
  4. A first-pass A2 poster outline (paper sketch is fine).
  5. The short fit interview completed for both partners (3 to 5 minutes per group).

Duration, approximately 115 minutes.

What you need.

  • The package you started in Week 9 (your A3 package).
  • Both partners present.
  • A TestPyPI account (you will create this in Part 3 if you have not already).
Pair work, in plain language

Both partners commit code today. Both partners will sit the individual fit interview at the end of this lab, so neither of you can outsource a function entirely to the other. Aim for genuine pair work, not divided silos.

Part 1. Plan today’s tests (10 minutes)

  1. Open the Chapter 4.2 testing summary. Skim the three small geospatial test patterns.

  2. With your partner, list four tests you will add today.

    • One happy-path test that calls a function with realistic input and checks the output type or shape.
    • One CRS or coordinate test (relevant for every brief except pavescore).
    • One edge-case test (empty input, missing column, file not found).
    • One fixture or parametrize test (you choose).

    Write these four down on paper before you start coding. This is the design step that almost everyone skips.

Part 2. Add the tests (35 minutes)

  1. Add or extend your test file from Week 9.
import pytest
import geopandas as gpd
from shapely.geometry import Point

from your_package_name import function_one, function_two
  1. CRS test. Confirm the function preserves or sets the expected CRS. For most A3 briefs this should be EPSG:2193 (NZTM) for spatial maths or EPSG:4326 (WGS 84) for input from raw lat/lon.
def test_output_has_correct_crs():
    result = function_one(...)
    assert result.crs.to_string() == "EPSG:2193"
  1. Fixture test (option A). A reusable test sample shared across tests.
@pytest.fixture
def small_sample():
    return gpd.GeoDataFrame(
        {"id": [1, 2]},
        geometry=[Point(174.76, -36.85), Point(174.78, -36.86)],
        crs="EPSG:4326",
    )


def test_function_with_fixture(small_sample):
    result = function_two(small_sample)
    assert len(result) == len(small_sample)

Or, parametrize test (option B). The same test run on several inputs.

@pytest.mark.parametrize("crs", ["EPSG:2193", "EPSG:4326"])
def test_function_handles_either_crs(crs, small_sample):
    sample = small_sample.to_crs(crs)
    result = function_two(sample)
    assert result is not None
  1. Run the tests.
uv run pytest -v
  1. (Optional) Look at coverage to see what is still untested.
uv add --dev pytest-cov
uv run pytest --cov=your_package_name

Commit and push when all four tests pass.

Part 3. Publish to TestPyPI (30 minutes)

This step rehearses what you will do for production PyPI in Week 12. Practise it now while there is no time pressure.

  1. Create a TestPyPI account at https://test.pypi.org/account/register/. Verify your email and (recommended) enable two-factor authentication.

  2. Generate an API token. Go to Account Settings, then API Tokens. Set the scope to “Entire account” for now. Copy the token (it starts with pypi-). Save it somewhere safe because you cannot view it again.

  3. Bump the version in pyproject.toml. TestPyPI does not allow re-uploading the same version.

[project]
version = "0.1.1"   # was 0.1.0
  1. Build and publish.
uv build
uv publish --publish-url https://test.pypi.org/legacy/

uv will prompt for credentials. Use __token__ as the username and paste the token as the password. Or set the token via environment variable.

export UV_PUBLISH_TOKEN=pypi-AgEI...
uv publish --publish-url https://test.pypi.org/legacy/
  1. Verify the install in a clean environment. Do not skip this step. It catches missing files and broken metadata that pass locally.
uv venv /tmp/test-install
source /tmp/test-install/bin/activate

uv pip install \
    --index-url https://test.pypi.org/simple/ \
    --extra-index-url https://pypi.org/simple/ \
    your-package-name

python -c "from your_package_name import function_one; print(function_one(...))"

deactivate

The --extra-index-url is needed because some dependencies (like pandas and geopandas) only live on real PyPI, not TestPyPI.

Part 4. Poster outline (20 minutes)

The poster showcase is on Monday 25 May (B301-G10). Today you sketch the layout. The aim is to have something on paper, not a polished file.

  1. Take an A4 sheet and divide it into seven boxes (a poster has roughly this many regions).

  2. Label each box and write one or two lines of content for each.

  3. Title and authors. The package name and both your names.

  4. The problem. Two sentences, no jargon. Why does this package exist?

  5. The solution. One sentence stating what the package does.

  6. Code example. A six-line snippet showing the simplest use of one function.

  7. A figure. A draft of the map, chart, or table from your demo notebook.

  8. Design choices. Three bullets explaining one CRS choice, one data choice, and one scope decision.

  9. Links. TestPyPI URL, GitHub URL, contact email. (Replace with PyPI URLs after Week 12.)

  10. Show your sketch to the demonstrator before leaving.

Tip

A2 posters are read from two metres away. Aim for titles at 50 pt or larger, body text at 20 pt or larger, and a single dominant figure. White space matters. Most weak posters have too much text.

Take a look at the poster

Part 5. Short fit interview (10 minutes)

This is the actual fit interview, not a rehearsal. Each person sits 3 to 5 minutes, with a demonstrator floating between groups to listen in. The aim is a quick check that both partners understand the code their name is on.

  1. Cluster into groups of four (your pair plus another pair). Sit so both pairs can see each other’s screens.

  2. One person sits, the other three listen. The interviewer asks the following three questions in sequence (the other pair’s pair member is the interviewer; demonstrators may also conduct interviews directly).

  • “Pick one function you (personally) wrote and walk us through it. What does it return?”
  • “Why did you choose this CRS, this default, or this optional dependency? What did you reject and why?”
  • “What would happen if I passed an empty GeoDataFrame (or a missing key) to this function?”
  1. The interviewee may look at the code, look at the docstring, or say “I do not know, but I would check…” All of those are fine. What we are listening for is whether you can describe and defend the work, not whether you have memorised it.

  2. Rotate so all four people in the group get a turn (about 5 minutes each, including a brief reset between people).

What is and is not OK

Fine: hesitating, looking at the docstring, saying “my partner did the first draft and I rewrote this part”. Not fine: “my partner wrote that bit, I am not sure how it works”. The interview catches uneven contribution early so we can address it before Week 12, not after.

Tip

If you finish the rotation early, swap to the other pair’s package and try interviewing each other on it. Hearing the same questions about a different package is the best preparation for explaining your own.

Part 6. Wrap up (5 minutes)

Before leaving, confirm the following with your partner.

  • Tests pass and have been pushed to GitHub.
  • The TestPyPI page exists and the package installs in a clean environment.
  • The poster outline is on paper and the demonstrator has seen it.
  • Both partners have completed the fit interview.

Further reading

  • Chapter 4.2, Testing and code quality
  • Chapter 4.3, A real geospatial package: akl-ped-counts
  • akl-ped-counts CONTRIBUTING.md for the build and publish steps, https://github.com/dataandcrowd/akl-ped-counts/blob/main/CONTRIBUTING.md
  • uv publish guide, https://docs.astral.sh/uv/guides/publish/
  • TestPyPI, https://test.pypi.org/