Skip to main content

GitLab CI Pipeline: Run Python Unit Tests and Publish Results with GitLab Pages (Python Flask Web Application)

663 words·
GitLab GitLab Pages GitLab CI CI Pipeline Python Unit Test Flask
Table of Contents
GitHub Repository Available

Overview
#

GitLab Setup
#

In this tutorial I’m using the following setup based on Ubuntu 22.04 servers, GitLab is dockerized:

192.168.70.4 # GitLab
192.168.70.5 # GitLab Runner
192.168.70.6 # Deployment Server with Docker platform installed

GitLab Pages
#

  • Make sure GitLab Pages are enabled. To enable GitLab Pages, check out my previous blog post: “GitLab & GitLab Registry - Docker Compose Deployment”

  • Make sure the domain name of the GitLab page can be resolved by the clients:

# Example GitLab page URL
https://root.gitlab-pages.jklug.work/python-test-pages/

# Hosts entry (If no DNS server is used)
192.168.70.4 root.gitlab-pages.jklug.work

Unit Test Overview
#

  • A Python unit test is a way to automatically check if a small, specific part of the code (called a “unit”) works correctly.

  • A unit test runs the code with specific inputs and checks if the outputs or behavior are correct.

  • The Python code must contain unit tests that are using Python’s unittest framework (or another testing library like pytest if configured).


Requirements
#

  • Make sure the add coverage in the requirements.txt file.



GitLab Repository
#

This GitLab repository is available on GitHub:
https://github.com/jueklu/gitlab-ci-python-unit-test-gitlab-pages


File & Folder Structure
#

The file and folder structure of the GitLab repository looks like this:

GitLab-Repository
├── flask-app
│   ├── app.py  # Python Flask Web Application
│   ├── requirements.txt  # Add "coverage" package for the unit test
│   └── test_app.py  # Python unit test
├── .gitlab-ci.yml
└── README.md

CI Pipeline Manifest
#

  • The first stage of the CI pipeline generates the test coverage artifacts

  • The second stage of the CI pipeline publishes the artifacts to GitLab Pages


  • .gitlab-ci.yml
### Stages
stages:
  - test
  - pages


### Unit test
unit-test:
  image: python:3.10
  stage: test
  before_script:
    - cd flask-app
    # Install requirements
    - pip install -r requirements.txt
  script:
    # Run unit tests with coverage enabled
    - python -m coverage run -m unittest
    # Generate an HTML report of the coverage results
    - coverage html
  artifacts:
    paths:
      # Specify the directory to store the coverage report as an artifact
      - flask-app/htmlcov/


### Deploy unit test results to GitLab Pages
pages:
  image: python:3.10
  stage: pages
  dependencies:
    # Use artifacts generated by the 'unit-test' stage
    - unit-test
  script:
    # Move the coverage report to the 'public/' directory for GitLab Pages
    - mv flask-app/htmlcov/ public/
  artifacts:
    paths:
      # Specify the 'public/' directory to be published via GitLab Pages
      - public/

Note: When using GitLab Pages, the job must be named named pages.



Python Code
#

Requirements
#

  • flask-app/requirements.txt
# Flask web framework version 3.1.0
Flask==3.1.0

# Add coverage package for the unit test
coverage

Flask Application
#

  • flask-app/app.py
# Import the Flask class from the Flask library
from flask import Flask

 # Create an instance of the Flask application
app = Flask(__name__)


# Define a route for the root URL ("/")
@app.route("/")
def main():   # Define a function that will execute when the root URL is accessed
    return "Hi there"  # Return a simple string response to the client.


# Start the Flask app on all available network interfaces (0.0.0.0) and port 8080
if __name__ == "__main__":
    # Start the Flask app only when running the script directly
    app.run(host='0.0.0.0', port=8080)

Unit Test
#

  • flask-app/test_app.py
import unittest
from flask import Flask
from app import app  # Import the Flask app from your application

class TestFlaskApp(unittest.TestCase):
    def setUp(self):
        # Set up a test client for the Flask app
        self.app = app.test_client()
        self.app.testing = True

    def test_main_route(self):
        # Send a GET request to the root URL
        response = self.app.get('/')
        # Check if the status code is 200
        self.assertEqual(response.status_code, 200)
        # Check if the response data is correct
        self.assertEqual(response.data.decode('utf-8'), "Hi there")

if __name__ == "__main__":
    unittest.main()



Verify GitLab Pages Unit Test
#

Open GitLab Page
#

  • Go to: (Project) “Deploy” > “Pages”

  • Uncheck “Use unique domain” and click “Save changes”

  • Click the link in the “Access pages” section:
    https://root.gitlab-pages.jklug.work/python-test-pages/


Verify Unit Test
#

  • Verify the unit test:



Links #

jueklu/gitlab-ci-python-flask-web-application

GitLab CI Pipeline the containerizes and deploys a Python Flask web application.

Python
0
0