Europa
Europa

Reputation: 1292

Python flask unittest using .gitlab-ci.yml

I want to run unittest when I push the code to my Gitlab. I have two python files, Main.py and tests/test_main.py.

To run the test_main.py in Pycharm on Windows 11 I right click on the tests folder and press "Run Python tests in tests".

When I do this the following output is given:

C:\Users\s\AppData\Local\Programs\Python\Python310\python.exe "C:\Program Files\JetBrains\PyCharm Community Edition 2022.1\plugins\python-ce\helpers\pycharm\_jb_unittest_runner.py" --path C:/Users/s/PycharmProjects/todaytest/tests


Testing started at 14:39 ...
Launching unittests with arguments python -m unittest discover -s C:/Users/s/PycharmProjects/todaytest/tests -t C:\Users\s\PycharmProjects\todaytest\tests in C:\Users\s\PycharmProjects\todaytest\tests

All days: http://127.0.0.1:3001/api/v1/resources/today/all
 * Running on all addresses (0.0.0.0)
Today by ID: http://127.0.0.1:3001/api/v1/resources/today?id=2
   WARNING: This is a development server. Do not use it in a production deployment.
Today by month and day: http://127.0.0.1:3001/api/v1/resources/today?month=05&day=10
 * Running on http://127.0.0.1:3000
 * Serving Flask app 'Main' (lazy loading)
 * Running on http://192.168.88.200:3000 (Press CTRL+C to quit)
 * Environment: production
 * Restarting with stat
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
Launching unittests with arguments python -m unittest in C:\Users\sindr\PycharmProjects\todaytest\tests

All days: http://127.0.0.1:3001/api/v1/resources/today/all
 * Debugger is active!
Today by ID: http://127.0.0.1:3001/api/v1/resources/today?id=2
Today by month and day: http://127.0.0.1:3001/api/v1/resources/today?month=05&day=10
 * Debugger PIN: 790-993-637

Now I am going to put the test into my .gitlab-ci.yml:

stages:
  - test
test:
  script:
    - python tests/test_main.py
    - pip install flask

This failes with the following command

Found errors in your .gitlab-ci.yml:
tests job: chosen stage does not exist; available stages are .pre, tests, dockerbuild, .post
You can also test your .gitlab-ci.yml in CI Lint

Here are my Python files..

Main.py

import datetime
import flask
from flask import jsonify, request, app


class Main:
    app = flask.Flask(__name__)  # Creates the Flask application object
    app.config["DEBUG"] = True

    # Readme
    dt = datetime.datetime.today()
    print("All days: http://127.0.0.1:3001/api/v1/resources/today/all")
    print("Today by ID: http://127.0.0.1:3001/api/v1/resources/today?id=2")
    print("Today by month and day: http://127.0.0.1:3001/api/v1/resources/today?month=" + '{:02d}'.format(
        dt.month) + "&day=" + '{:02d}'.format(dt.day))

    def __init__(self):

        # Test data for our catalog in the form of a list of dictionaries.
        # Jokes from here: https://www.rd.com/list/short-jokes/
        self.todays = [
            {'id': 0,
             'month': '05',
             'day': '04',
             'historic_event': '1670 – A royal charter granted the Hudsons Bay Company a monopoly in the fur trade in Ruperts Land (present-day Canada).',
             'joke': 'What’s the best thing about Switzerland? I don’t know, but the flag is a big plus.'},
            {'id': 1,
             'month': '05',
             'day': '05',
             'historic_event': '2010 – Mass protests in Greece erupt in response to austerity measures imposed by the government as a result of the Greek government-debt crisis.',
             'joke': 'I invented a new word! Plagiarism!'},
            {'id': 2,
             'month': '05',
             'day': '06',
             'historic_event': '2002– Founding of SpaceX.',
             'joke': 'Did you hear about the mathematician who’s afraid of negative numbers? He’ll stop at nothing to avoid them.'},
            {'id': 3,
             'month': '05',
             'day': '07',
             'historic_event': '2000 - Vladimir Putin is inaugurated as president of Russia.',
             'joke': 'How did the hacker escape from the police? He ransomware.'},
        ]

        @self.app.route('/', methods=['GET'])
        def __home():
            return self.home()

        @self.app.route('/api/v1/resources/today/all', methods=['GET'])
        def __api_all():
            return self.api_all()

        @self.app.route('/api/v1/resources/today', methods=['GET'])
        def __api_id():
            return self.api_id()

        self.app.run(host="0.0.0.0", port=3000, debug=True)
        #self.app.run(host="localhost", port=3000, debug=True)

    @staticmethod
    def home():
        return '''<h1>Today</h1>
        <p>A prototype API for finding out what happened on this day</p>'''

    def api_all(self):
        return jsonify(self.todays)

    def api_id(self):

        # Create an empty list for our results
        results = []

        # Check if an ID was provided as part of the URL.
        # If ID is provided, assign it to a variable.
        # If no ID is provided, display an error in the browser.
        if 'id' in request.args:
            id = int(request.args['id'])

            # Loop through the data and match results that fit the requested ID.
            # IDs are unique, but other fields might return many results
            for today in self.todays:
                if today['id'] == id:
                    results.append(today)
        else:
            # Month and day search
            if 'month' in request.args and 'day' in request.args:
                month = str(request.args['month'])
                day = str(request.args['day'])

                for today in self.todays:
                    if today['month'] == month and today['day'] == day:
                        results.append(today)

                result_length = len(results)
                if result_length == 0:
                    return "Error: Not yet implemented or not found"
            else:
                return "Error: No id, month or day field provided. Please specify."



        # Use the jsonify function from Flask to convert our list of
        # Python dictionaries to the JSON format.
        return jsonify(results)


Main();

tests/test_main.py

import unittest
import json
from Main import Main


class MainTest(unittest.TestCase):
    def setUp(self):
        self.ctx = Main.app.app_context()
        self.ctx.push()
        self.client = Main.app.test_client()

    def tearDown(self):
        self.ctx.pop()

    # test home #
    def test_home(self):
        """ Test Home will ho to home page of the flask API and check if the home str equals
        the content of the home page """

        home_str = '''<h1>Today</h1>
        <p>A prototype API for finding out what happened on this day</p>'''
        response = self.client.get("/", data={"content": home_str})
        self.assertEqual(response.status_code, 200)
        self.assertEqual(home_str, response.get_data(as_text=True))

    # test all #
    def test_all(self):
        """ Test goes to all API and should then display the entire json object.
         The test checks if the first id equals 0. """

        response = self.client.get("/api/v1/resources/today/all")
        data = json.loads(response.get_data(as_text=True))
        self.assertEqual(data[0]['id'], 0)

    # test id #
    def test_id(self):
        """ Test should pull the json object for id 2. The test check that it gets
         the ID 2. """

        response = self.client.get("/api/v1/resources/today?id=2")
        data = json.loads(response.get_data(as_text=True))
        self.assertEqual(data[0]['id'], 2)

    # test month day #
    def test_month_day(self):
        """ Will send in a month and a day and want to get back if the month
         and day is present in the json response """

        response = self.client.get("/api/v1/resources/today?month=05&day=06")
        data = json.loads(response.get_data(as_text=True))
        self.assertEqual(data[0]['month'], "05")
        self.assertEqual(data[0]['day'], "06")


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

Upvotes: 1

Views: 1101

Answers (1)

goguinhus182
goguinhus182

Reputation: 46

Your stages definition is not right: you have declared it somewhere else as the message states: "tests job: chosen stage does not exist; available stages are .pre, tests, dockerbuild, .post". It means you have defined the stages as:

stages:
  - tests
  - dockerbuild

Please note the stages definition must be unique for the whole pipeline - these are the different steps the pipeline will follow, unless needs section are defined. Then your job must have a stage section assigned to the value of one of these stages - otherwise, it gets automatically assigned to the test stage.

It will lead to something like this:

stages:
  - tests
  - dockerbuild


test:
  stage: tests
  script:
    - python tests/test_main.py
    - pip install flask

Please upload your whole .gitlab-ci.yml file next time.

Upvotes: 2

Related Questions