Appearance
Fresh
Create the project
Back
Getting started with Testcontainers for Python
Learn how to create a Python application and test database interactions using Testcontainers for Python with a real PostgreSQL instance.
Python Testing with Docker
15 minutes
Create the Python project
Copy as Markdown
Open MarkdownAsk Docs AIClaudeOpen in Claude
Table of contents
Initialize the project
Start by creating a Python project with a virtual environment:
console
$ mkdir tc-python-demo
$ cd tc-python-demo
$ python3 -m venv venv
$ source venv/bin/activateThis guide uses psycopg3 to interact with the Postgres database, pytest for testing, and testcontainers-python for running a PostgreSQL database in a container.
Install the dependencies:
console
$ pip install "psycopg[binary]" pytest testcontainers[postgres]
$ pip freeze > requirements.txtThe pip freeze command generates a requirements.txt file so that others can install the same package versions using pip install -r requirements.txt.
Create the database helper
Create a db/connection.py file with a function to get a database connection:
python
import os
import psycopg
def get_connection():
host = os.getenv("DB_HOST", "localhost")
port = os.getenv("DB_PORT", "5432")
username = os.getenv("DB_USERNAME", "postgres")
password = os.getenv("DB_PASSWORD", "postgres")
database = os.getenv("DB_NAME", "postgres")
return psycopg.connect(f"host={host} dbname={database} user={username} password={password} port={port}")Instead of hard-coding the database connection parameters, the function uses environment variables. This makes it possible to run the application in different environments without changing code.
Create the business logic
Create a customers/customers.py file and define the Customer class:
python
class Customer:
def __init__(self, cust_id, name, email):
self.id = cust_id
self.name = name
self.email = email
def __str__(self):
return f"Customer({self.id}, {self.name}, {self.email})"Add a create_table() function to create the customers table:
python
from db.connection import get_connection
def create_table():
with get_connection() as conn:
with conn.cursor() as cur:
cur.execute("""
CREATE TABLE customers (
id serial PRIMARY KEY,
name varchar not null,
email varchar not null unique)
""")
conn.commit()The function obtains a database connection using get_connection() and creates the customers table. The with statement automatically closes the connection when done.
Add the remaining CRUD functions:
python
def create_customer(name, email):
with get_connection() as conn:
with conn.cursor() as cur:
cur.execute(
"INSERT INTO customers (name, email) VALUES (%s, %s)", (name, email))
conn.commit()
def get_all_customers() -> list[Customer]:
with get_connection() as conn:
with conn.cursor() as cur:
cur.execute("SELECT * FROM customers")
return [Customer(cid, name, email) for cid, name, email in cur]
def get_customer_by_email(email) -> Customer:
with get_connection() as conn:
with conn.cursor() as cur:
cur.execute("SELECT id, name, email FROM customers WHERE email = %s", (email,))
(cid, name, email) = cur.fetchone()
return Customer(cid, name, email)
def delete_all_customers():
with get_connection() as conn:
with conn.cursor() as cur:
cur.execute("DELETE FROM customers")
conn.commit()Note
To keep it straightforward for this guide, each function creates a new connection. In a real-world application, use a connection pool to reuse connections.