Merge branch 'feat/Q1.3'
Feat/q1.3 See merge request Klagarge/mse2425-grp09!3
This commit is contained in:
@@ -1,13 +1,16 @@
|
|||||||
stages:
|
default:
|
||||||
- build
|
image: python:3.9
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- lint
|
||||||
|
- build
|
||||||
|
|
||||||
build job:
|
build job:
|
||||||
stage: build
|
stage: build
|
||||||
script:
|
script:
|
||||||
- cd src
|
- cd src
|
||||||
- apt-get update -qy
|
# - apt-get update -qy
|
||||||
- apt-get install -y python3-dev python3-pip python3.12-venv curl
|
# - apt-get install -y python3-dev python3-pip python3.12-venv curl
|
||||||
- python3 -V
|
- python3 -V
|
||||||
# - pip3 install --break-system-packages -r requirements.txt
|
# - pip3 install --break-system-packages -r requirements.txt
|
||||||
- curl -sSL https://pdm-project.org/install-pdm.py | python3 -
|
- curl -sSL https://pdm-project.org/install-pdm.py | python3 -
|
||||||
@@ -22,11 +25,18 @@ build job:
|
|||||||
- export FLASK_APP=app
|
- export FLASK_APP=app
|
||||||
- pdm run pytest tests --cov --cov-report term --cov-report html
|
- pdm run pytest tests --cov --cov-report term --cov-report html
|
||||||
|
|
||||||
|
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- src/htmlcov/
|
- src/htmlcov/
|
||||||
|
|
||||||
|
lint job:
|
||||||
|
stage: lint
|
||||||
|
dependencies: []
|
||||||
|
script:
|
||||||
|
- python3 -m pip install flake8
|
||||||
|
- flake8 src/
|
||||||
|
allow_failure: true # Linter can fail, fixing it is for now outside of the projects scope
|
||||||
|
|
||||||
pages:
|
pages:
|
||||||
stage: build
|
stage: build
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@@ -11,3 +11,7 @@
|
|||||||
## Q1.2
|
## Q1.2
|
||||||
- It's a very bad practice. The secret key will be exposed in the codebase and can be easily accessed by anyone who has access to the codebase. This can lead to security vulnerabilities and compromise the integrity of the application.
|
- It's a very bad practice. The secret key will be exposed in the codebase and can be easily accessed by anyone who has access to the codebase. This can lead to security vulnerabilities and compromise the integrity of the application.
|
||||||
- To fix this, you can use environment variables to store the secret key.
|
- To fix this, you can use environment variables to store the secret key.
|
||||||
|
|
||||||
|
## Q1.3
|
||||||
|
- A linter is a tool to statically analyse code for readability and improving code quality. It is usually executed from a standalone tool.
|
||||||
|
- It is used to check for errors, vulns, code smells or general issues but also to enforce a coding style over the whole project.
|
16
src/app.py
16
src/app.py
@@ -18,12 +18,8 @@
|
|||||||
from flask import request, Flask, url_for, render_template, redirect
|
from flask import request, Flask, url_for, render_template, redirect
|
||||||
import operators
|
import operators
|
||||||
import json
|
import json
|
||||||
from dotenv import load_dotenv
|
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
__author__ = 'Michael Mäder'
|
__author__ = 'Michael Mäder'
|
||||||
__date__ = "2025-03-10"
|
__date__ = "2025-03-10"
|
||||||
__version__ = "0.5"
|
__version__ = "0.5"
|
||||||
@@ -40,7 +36,8 @@ A little web application that offers API calls for arithmetic operations
|
|||||||
# creation of the Flask application
|
# creation of the Flask application
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
app.config['SECRET_KEY'] = os.environ.get('FLASK_SECRET_KEY') # super secure key against CSRF attacks
|
# super secure key against CSRF attacks
|
||||||
|
app.config['SECRET_KEY'] = os.environ.get('FLASK_SECRET_KEY')
|
||||||
|
|
||||||
# global variable containing the name of the login user
|
# global variable containing the name of the login user
|
||||||
global_data = {'username': 'no_user'}
|
global_data = {'username': 'no_user'}
|
||||||
@@ -51,18 +48,19 @@ global_data = {'username': 'no_user'}
|
|||||||
def plus_one():
|
def plus_one():
|
||||||
try:
|
try:
|
||||||
x = int(request.args.get('x', 1))
|
x = int(request.args.get('x', 1))
|
||||||
except:
|
except ValueError:
|
||||||
return json.dumps({"error": "Type error"})
|
return json.dumps({"error": "Type error"})
|
||||||
|
|
||||||
return json.dumps({'x': operators.addition(x, 1)})
|
return json.dumps({'x': operators.addition(x, 1)})
|
||||||
|
|
||||||
|
|
||||||
# addition route, the parameters will be passed with 'x' and 'y'
|
# addition route, the parameters will be passed with 'x' and 'y'
|
||||||
@app.route('/add')
|
@app.route('/add')
|
||||||
def plus_y():
|
def plus_y():
|
||||||
try:
|
try:
|
||||||
x = int(request.args.get('x', 1))
|
x = int(request.args.get('x', 1))
|
||||||
y = int(request.args.get('y', 1))
|
y = int(request.args.get('y', 1))
|
||||||
except:
|
except ValueError:
|
||||||
return json.dumps({"error": "Type error"})
|
return json.dumps({"error": "Type error"})
|
||||||
return json.dumps({'result': operators.addition(x, y)})
|
return json.dumps({'result': operators.addition(x, y)})
|
||||||
|
|
||||||
@@ -73,7 +71,7 @@ def multiply_y():
|
|||||||
try:
|
try:
|
||||||
x = int(request.args.get('x', 1))
|
x = int(request.args.get('x', 1))
|
||||||
y = int(request.args.get('y', 1))
|
y = int(request.args.get('y', 1))
|
||||||
except:
|
except ValueError:
|
||||||
return json.dumps({"error": "Type error"})
|
return json.dumps({"error": "Type error"})
|
||||||
return json.dumps({'result': operators.multiplication(x, y)})
|
return json.dumps({'result': operators.multiplication(x, y)})
|
||||||
|
|
||||||
@@ -84,7 +82,7 @@ def division_y():
|
|||||||
try:
|
try:
|
||||||
x = int(request.args.get('x', 1))
|
x = int(request.args.get('x', 1))
|
||||||
y = int(request.args.get('y', 1))
|
y = int(request.args.get('y', 1))
|
||||||
except:
|
except ValueError:
|
||||||
return json.dumps({"error": "Type error"})
|
return json.dumps({"error": "Type error"})
|
||||||
return json.dumps({'result': operators.division(x, y)})
|
return json.dumps({'result': operators.division(x, y)})
|
||||||
|
|
||||||
|
@@ -23,17 +23,17 @@ __email__ = "michael.maeder@hefr.ch"
|
|||||||
|
|
||||||
# file containing the operations for the calculator
|
# file containing the operations for the calculator
|
||||||
|
|
||||||
# addition: returns x+y
|
# addition: returns x+y
|
||||||
def addition(x, y):
|
def addition(x, y):
|
||||||
return x+y
|
return x+y
|
||||||
|
|
||||||
|
|
||||||
# subtraction: returns x-y
|
# subtraction: returns x-y
|
||||||
def subtraction(x, y):
|
def subtraction(x, y):
|
||||||
return x-y
|
return x-y
|
||||||
|
|
||||||
|
|
||||||
# multiplication: returns x*y
|
# multiplication: returns x*y
|
||||||
def multiplication(x, y):
|
def multiplication(x, y):
|
||||||
return x*y
|
return x*y
|
||||||
|
|
||||||
@@ -42,6 +42,6 @@ def multiplication(x, y):
|
|||||||
# returns None if the divisor is zero
|
# returns None if the divisor is zero
|
||||||
# the result might be of float type
|
# the result might be of float type
|
||||||
def division(x, y):
|
def division(x, y):
|
||||||
if y==0:
|
if y == 0:
|
||||||
return None
|
return None
|
||||||
return x/y
|
return x/y
|
||||||
|
@@ -5,7 +5,7 @@ from app import app
|
|||||||
|
|
||||||
|
|
||||||
# the client here allow to use the app without running in live server
|
# the client here allow to use the app without running in live server
|
||||||
# see https://flask.palletsprojects.com/en/2.0.x/testing/#sending-requests-with-the-test-client
|
# see https://flask.palletsprojects.com/en/2.0.x/testing/#sending-requests-with-the-test-client # noqa: E501
|
||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def client():
|
def client():
|
||||||
app.config['TESTING'] = True
|
app.config['TESTING'] = True
|
||||||
|
@@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
from urllib.parse import urlencode
|
from urllib.parse import urlencode
|
||||||
import json
|
import json
|
||||||
import pytest
|
|
||||||
|
|
||||||
__author__ = 'Michael Mader'
|
__author__ = 'Michael Mader'
|
||||||
__date__ = "2023-03-12"
|
__date__ = "2023-03-12"
|
||||||
@@ -27,12 +26,12 @@ __email__ = "michael.maeder@hefr.ch"
|
|||||||
|
|
||||||
def call(client, path, params):
|
def call(client, path, params):
|
||||||
"""calling function that simulates an API webcall of a specific function/route
|
"""calling function that simulates an API webcall of a specific function/route
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
client: this is the client object used by pytest to 'simulate' the API without running the webserver
|
client: this is the client object used by pytest to 'simulate' the API without running the webserver
|
||||||
path: route of the API to use
|
path: route of the API to use
|
||||||
params: GET parameter that are passed to the function
|
params: GET parameter that are passed to the function
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
json: the result of the client call
|
json: the result of the client call
|
||||||
"""
|
"""
|
||||||
@@ -40,50 +39,59 @@ def call(client, path, params):
|
|||||||
response = client.get(url)
|
response = client.get(url)
|
||||||
return json.loads(response.data.decode('utf-8'))
|
return json.loads(response.data.decode('utf-8'))
|
||||||
|
|
||||||
|
|
||||||
# increment test 1
|
# increment test 1
|
||||||
def test_plus_one1(client):
|
def test_plus_one1(client):
|
||||||
result = call(client, '/inc', {'x': 2})
|
result = call(client, '/inc', {'x': 2})
|
||||||
assert result['x'] == 3
|
assert result['x'] == 3
|
||||||
|
|
||||||
|
|
||||||
# increment test 1
|
# increment test 1
|
||||||
def test_plus_one2(client):
|
def test_plus_one2(client):
|
||||||
result = call(client, '/inc', {'x': -2})
|
result = call(client, '/inc', {'x': -2})
|
||||||
assert result['x'] == -1
|
assert result['x'] == -1
|
||||||
|
|
||||||
|
|
||||||
# adding test with negative value
|
# adding test with negative value
|
||||||
def test_plus_y(client):
|
def test_plus_y(client):
|
||||||
result = call(client, '/add', {'x': -2, 'y': 7})
|
result = call(client, '/add', {'x': -2, 'y': 7})
|
||||||
assert result['result'] == 5
|
assert result['result'] == 5
|
||||||
|
|
||||||
|
|
||||||
# multiplication test
|
# multiplication test
|
||||||
def test_multiply(client):
|
def test_multiply(client):
|
||||||
result = call(client, '/mul', {'x': -2, 'y': 7})
|
result = call(client, '/mul', {'x': -2, 'y': 7})
|
||||||
assert result['result'] == -14
|
assert result['result'] == -14
|
||||||
|
|
||||||
|
|
||||||
# division test
|
# division test
|
||||||
def test_division(client):
|
def test_division(client):
|
||||||
result = call(client, '/div', {'x': 35, 'y': 7})
|
result = call(client, '/div', {'x': 35, 'y': 7})
|
||||||
assert result['result'] == 5
|
assert result['result'] == 5
|
||||||
|
|
||||||
|
|
||||||
# type tests
|
# type tests
|
||||||
def test_type_inc(client):
|
def test_type_inc(client):
|
||||||
result = call(client, '/inc', {'x': 'a'})
|
result = call(client, '/inc', {'x': 'a'})
|
||||||
assert result["error"] == "Type error"
|
assert result["error"] == "Type error"
|
||||||
|
|
||||||
|
|
||||||
def test_type_add(client):
|
def test_type_add(client):
|
||||||
result = call(client, '/add', {'x': 'a', 'y': 1})
|
result = call(client, '/add', {'x': 'a', 'y': 1})
|
||||||
assert result["error"] == "Type error"
|
assert result["error"] == "Type error"
|
||||||
result = call(client, '/add', {'x': 1, 'y': 'a'})
|
result = call(client, '/add', {'x': 1, 'y': 'a'})
|
||||||
assert result["error"] == "Type error"
|
assert result["error"] == "Type error"
|
||||||
|
|
||||||
|
|
||||||
def test_type_mul(client):
|
def test_type_mul(client):
|
||||||
result = call(client, '/mul', {'x': 'a', 'y': 1})
|
result = call(client, '/mul', {'x': 'a', 'y': 1})
|
||||||
assert result["error"] == "Type error"
|
assert result["error"] == "Type error"
|
||||||
result = call(client, '/mul', {'x': 1, 'y': 'a'})
|
result = call(client, '/mul', {'x': 1, 'y': 'a'})
|
||||||
assert result["error"] == "Type error"
|
assert result["error"] == "Type error"
|
||||||
|
|
||||||
|
|
||||||
def test_type_div(client):
|
def test_type_div(client):
|
||||||
result = call(client, '/div', {'x': 'a', 'y': 1})
|
result = call(client, '/div', {'x': 'a', 'y': 1})
|
||||||
assert result["error"] == "Type error"
|
assert result["error"] == "Type error"
|
||||||
result = call(client, '/div', {'x': 1, 'y': 'a'})
|
result = call(client, '/div', {'x': 1, 'y': 'a'})
|
||||||
assert result["error"] == "Type error"
|
assert result["error"] == "Type error"
|
||||||
|
Reference in New Issue
Block a user