From 63181626e4f60f4fba3a65e67865809ce8dffacf Mon Sep 17 00:00:00 2001 From: EliuX Date: Thu, 12 Mar 2020 19:08:52 -0500 Subject: [PATCH] Fixes #17 Add tests and coverage support --- .gitignore | 5 ++ README.md | 73 +++++++++++++++++-- cli.py | 8 +- requirements/dev.txt | 11 +++ setup.cfg | 8 ++ setup.py | 7 ++ tests/__init__.py | 0 tests/conftest.py | 15 ++++ tests/projects/__init__.py | 0 tests/projects/projects_namespace_test.py | 11 +++ tests/smoke_test.py | 4 + .../projects/projects_namespace.py | 1 - 12 files changed, 132 insertions(+), 11 deletions(-) create mode 100644 requirements/dev.txt create mode 100644 setup.cfg create mode 100644 setup.py create mode 100644 tests/__init__.py create mode 100644 tests/conftest.py create mode 100644 tests/projects/__init__.py create mode 100644 tests/projects/projects_namespace_test.py create mode 100644 tests/smoke_test.py diff --git a/.gitignore b/.gitignore index 6049a511..23ff50ef 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,11 @@ __pycache__/ *.py[cod] *$py.class +*.egg-info/ +htmlcov/ +.tox/ +.coverage +.coverage.* # scrapy .scrapy diff --git a/README.md b/README.md index ebf26867..1e149522 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ # time-tracker-api +The API of the TSheets killer app. + ## Getting started -Follow the following instructions to get the project ready to use ASAP: +Follow the following instructions to get the project ready to use ASAP. ### Requirements Be sure you have installed in your system @@ -10,7 +12,7 @@ Be sure you have installed in your system automatically [pip](https://pip.pypa.io/en/stable/) as well. - A virtual environment, namely [venv](https://docs.python.org/3/library/venv.html). -## Setup +### Setup - Create and activate the environment, @@ -26,13 +28,16 @@ automatically [pip](https://pip.pypa.io/en/stable/) as well. virtualenv .venv source .venv/bin/activate ``` + - Install the requirements: ``` - python3 -m pip install -r requirements/prod.txt + python3 -m pip install -r requirements/.txt ``` + + The `stage` can be `dev` or `prod`. Remember to do it with Python 3. -## How to use it +### How to use it - Set the env var `FLASK_APP` to `time_tracker_api` and start the app: In Windows @@ -50,7 +55,47 @@ automatically [pip](https://pip.pypa.io/en/stable/) as well. a link to the swagger.json with the definition of the api. -## CLI +## Development + +### Test +We are using Pytest](https://docs.pytest.org/en/latest/index.html) for tests. The tests are located in the package +`tests` and use the [conventions for python test discovery](https://docs.pytest.org/en/latest/goodpractices.html#test-discovery). + +To run the tests just execute: + +``` +python3 -m pytest -v +``` + +The option `-v` shows which tests failed or succeeded. Have into account that you can also debug each test +(test_* files) with the help of an IDE like PyCharm. + +#### Coverage +To check the coverage of the tests execute + +```bash + coverage run -m pytest -v +``` + +To get a report table + +```bash + coverage report +``` + +To get a full report in html +```bash + coverage html +``` +Then check in the [htmlcov/index.html](./htmlcov/index.html) to see it + +If you want that previously collected coverage data is erased, you can execute: + +``` +coverage erase +``` + +### CLI There are available commands, aware of the API, that can be very helpful to you. You can check them out by running @@ -64,4 +109,20 @@ as well as its correspondent options. ``` python cli.py gen_swagger_json -f ~/Downloads/swagger.json -``` \ No newline at end of file +``` + +## Built with +- [Python version 3](https://www.python.org/download/releases/3.0/) as backend programming language. Strong typing for +the win. +- [Flask](http://flask.pocoo.org/) as the micro framework of choice. +- [Flask RestPlus](https://flask-restplus.readthedocs.io/en/stable/) for building Restful APIs with Swagger. +- [Pytest](https://docs.pytest.org/en/latest/index.html) for tests +- [Coverage](https://coverage.readthedocs.io/en/coverage-4.5.4/) for coverage +- [Swagger](https://swagger.io/) for documentation and standardization, taking into account the +[API import restrictions and known issues](https://docs.microsoft.com/en-us/azure/api-management/api-management-api-import-restrictions) +in Azure. + + +## License + +Copyright 2020 ioet Inc. All Rights Reserved. \ No newline at end of file diff --git a/cli.py b/cli.py index de84e87c..953e0e06 100644 --- a/cli.py +++ b/cli.py @@ -1,9 +1,5 @@ #!/usr/bin/env python3 -print("****************") -print("TimeTracker CLI") -print("****************") - import os from flask import json @@ -63,4 +59,8 @@ def save_data(data: str, filename: str) -> None: if __name__ == "__main__": + print("****************") + print("TimeTracker CLI") + print("****************") + cli_manager.run() diff --git a/requirements/dev.txt b/requirements/dev.txt new file mode 100644 index 00000000..e7f629d0 --- /dev/null +++ b/requirements/dev.txt @@ -0,0 +1,11 @@ +# requirements/dev.txt + +-r prod.txt + +# For development + +# Tests +pytest==4.1.1 + +# Coverage +coverage==4.5.1 \ No newline at end of file diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 00000000..f7333a82 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,8 @@ +[tool:pytest] +testpaths = tests +addopts = -p no:warnings + +[coverage:run] +branch = True +source = + time_tracker_api diff --git a/setup.py b/setup.py new file mode 100644 index 00000000..999aad6e --- /dev/null +++ b/setup.py @@ -0,0 +1,7 @@ +from setuptools import setup, find_packages + +setup( + name="time-tracker-api", + packages=find_packages(), + include_package_data=True, +) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000..dab7eecd --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,15 @@ + +import pytest + +from time_tracker_api import create_app + +@pytest.fixture(scope='session') +def app(): + """An instance of the app for tests""" + return create_app() + +@pytest.fixture +def client(app): + """A test client for the app.""" + with app.test_client() as c: + return c \ No newline at end of file diff --git a/tests/projects/__init__.py b/tests/projects/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/projects/projects_namespace_test.py b/tests/projects/projects_namespace_test.py new file mode 100644 index 00000000..2cc9a3fd --- /dev/null +++ b/tests/projects/projects_namespace_test.py @@ -0,0 +1,11 @@ +from flask import json + + +def test_list_should_return_nothing(client): + """Should return an empty array""" + response = client.get("/projects", follow_redirects=True) + + assert 200 == response.status_code + + json_data = json.loads(response.data) + assert [] == json_data \ No newline at end of file diff --git a/tests/smoke_test.py b/tests/smoke_test.py new file mode 100644 index 00000000..3e0551d6 --- /dev/null +++ b/tests/smoke_test.py @@ -0,0 +1,4 @@ + +def test_app_exists(app): + """Does app exists""" + assert app is not None diff --git a/time_tracker_api/projects/projects_namespace.py b/time_tracker_api/projects/projects_namespace.py index 4cdfae81..914ceaab 100644 --- a/time_tracker_api/projects/projects_namespace.py +++ b/time_tracker_api/projects/projects_namespace.py @@ -77,7 +77,6 @@ def get(self, uid): return project_dao.get(uid) @ns.doc('update_project_status') - @ns.param('uid', 'The project identifier') @ns.expect(project) @ns.response(204, 'State of the project successfully updated') def post(self, uid):