Testing and CI/CD
Lesson Plan: Testing and CI/CD in Python with pytest, GitHub Actions, and Docker
Objective:
By the end of this lesson, students will be able to:
- Write unit tests in Python using
pytest. - Set up Continuous Integration (CI) using GitHub Actions.
- Containerize a Python application using Docker.
- Implement Continuous Deployment (CD) using Docker and GitHub Actions.
Lesson Outline
1. Introduction (15 minutes)
- What is Testing?
- Importance of testing in software development.
- Types of tests: unit, integration, end-to-end.
- What is CI/CD?
- Continuous Integration (CI): Automatically testing code changes.
- Continuous Deployment (CD): Automatically deploying code changes.
- Tools Overview:
pytest: A testing framework for Python.- GitHub Actions: A CI/CD tool integrated with GitHub.
- Docker: A tool to containerize applications.
2. Writing Tests with pytest (30 minutes)
- Installation:
1
pip install pytest - Writing a Simple Test:
- Create a Python file
calculator.py:1 2 3 4 5
def add(a, b): return a + b def subtract(a, b): return a - b
- Create a test file
test_calculator.py:1 2 3 4 5 6 7 8 9
from calculator import add, subtract def test_add(): assert add(2, 3) == 5 assert add(-1, 1) == 0 def test_subtract(): assert subtract(5, 3) == 2 assert subtract(10, 7) == 3
- Create a Python file
- Running Tests:
1
pytest
- Explanation:
assert: Checks if the condition is true; if not, the test fails.pytestautomatically discovers and runs tests in files namedtest_*.py.
3. Setting Up CI with GitHub Actions (30 minutes)
- What is GitHub Actions?
- A CI/CD tool that allows you to automate workflows.
- Creating a Workflow:
- Create a
.github/workflows/ci.ymlfile:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
name: CI on: push: branches: - main pull_request: branches: - main jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Set up Python uses: actions/setup-python@v2 with: python-version: '3.9' - name: Install dependencies run: | python -m pip install --upgrade pip pip install pytest - name: Run tests run: pytest
- Create a
- Explanation:
on: Specifies when the workflow should run (e.g., on push or pull request).jobs: Defines the jobs to run (e.g.,test).steps: The steps to execute in the job (e.g., install Python, run tests).
4. Containerizing the Application with Docker (30 minutes)
- What is Docker?
- A tool to package applications into containers.
- Creating a Dockerfile:
- Create a
Dockerfile:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
# Use an official Python runtime as a parent image FROM python:3.9-slim # Set the working directory in the container WORKDIR /app # Copy the current directory contents into the container COPY . . # Install any needed packages specified in requirements.txt RUN pip install --no-cache-dir -r requirements.txt # Run tests RUN pytest # Make port 80 available to the world outside this container EXPOSE 80 # Run the application CMD ["python", "app.py"]
- Create a
- Building and Running the Docker Image:
1 2
docker build -t my-python-app . docker run -p 4000:80 my-python-app
- Explanation:
FROM: Specifies the base image.WORKDIR: Sets the working directory.COPY: Copies files from the host to the container.RUN: Executes commands (e.g., install dependencies, run tests).EXPOSE: Exposes a port.CMD: Specifies the command to run the application.
5. Implementing CD with GitHub Actions and Docker (30 minutes)
- Extending the Workflow:
- Update
.github/workflows/ci.ymlto include CD:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
name: CI/CD on: push: branches: - main pull_request: branches: - main jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Set up Python uses: actions/setup-python@v2 with: python-version: '3.9' - name: Install dependencies run: | python -m pip install --upgrade pip pip install pytest - name: Run tests run: pytest deploy: needs: test runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Build Docker image run: docker build -t my-python-app . - name: Log in to Docker Hub run: echo "$" | docker login -u "$" --password-stdin - name: Push Docker image run: docker push my-python-app
- Update
- Explanation:
deploy: A new job that builds and pushes the Docker image.needs: test: Ensures thedeployjob runs only if thetestjob succeeds.secrets.DOCKER_USERNAMEandsecrets.DOCKER_PASSWORD: GitHub secrets for Docker Hub credentials.
6. Recap and Q&A (15 minutes)
- Recap the key concepts: testing, CI/CD, Docker.
- Answer any questions from students.
Flashcards for Retention
Q: What is
pytestused for?
A: A testing framework for Python to write and run tests.Q: How do you run tests using
pytest?
A: Runpytestin the terminal.Q: What is Continuous Integration (CI)?
A: Automatically testing code changes.Q: What is Continuous Deployment (CD)?
A: Automatically deploying code changes.Q: What is GitHub Actions?
A: A CI/CD tool integrated with GitHub.Q: What is Docker?
A: A tool to containerize applications.Q: What does the
FROMcommand in a Dockerfile do?
A: Specifies the base image.Q: What does the
WORKDIRcommand in a Dockerfile do?
A: Sets the working directory in the container.Q: What does the
COPYcommand in a Dockerfile do?
A: Copies files from the host to the container.Q: What does the
RUNcommand in a Dockerfile do?
A: Executes commands (e.g., install dependencies, run tests).Q: What does the
EXPOSEcommand in a Dockerfile do?
A: Exposes a port to the outside world.Q: What does the
CMDcommand in a Dockerfile do?
A: Specifies the command to run the application.Q: How do you build a Docker image?
A: Rundocker build -t <image-name> .Q: How do you run a Docker container?
A: Rundocker run -p <host-port>:<container-port> <image-name>Q: What is the purpose of the
onkey in a GitHub Actions workflow?
A: Specifies when the workflow should run (e.g., on push or pull request).Q: What is the purpose of the
jobskey in a GitHub Actions workflow?
A: Defines the jobs to run (e.g.,test,deploy).Q: What is the purpose of the
stepskey in a GitHub Actions workflow?
A: The steps to execute in the job (e.g., install Python, run tests).Q: How do you log in to Docker Hub in a GitHub Actions workflow?
A: Useecho "$" | docker login -u "$" --password-stdinQ: How do you push a Docker image to Docker Hub in a GitHub Actions workflow?
A: Usedocker push <image-name>Q: What is the purpose of the
needskey in a GitHub Actions workflow?
A: Ensures a job runs only if another job succeeds.
Conclusion
This lesson plan provides a comprehensive guide to testing and CI/CD in Python using pytest, GitHub Actions, and Docker. The practical examples, code block comments, and flashcards will help reinforce the concepts and ensure retention.
Additional resources
Github Actions for Continuous Integration (CI) by Wes Doyle
CS50W - Lecture 7 - Testing and CI/CD
Slides for CS50W(for the above video)
