From 70afa5e5e0b9dfa7e08d3032fa26b565d4927fe4 Mon Sep 17 00:00:00 2001 From: Dingedi <64697405+dingedi@users.noreply.github.com> Date: Sat, 2 Apr 2022 21:02:17 +0200 Subject: [PATCH 01/19] Run test for pull requests --- .github/workflows/run-tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 626bf21..9ba9c0e 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -2,6 +2,8 @@ name: Run tests # Run test at each push to main, if changes to package or tests files on: workflow_dispatch: + pull_request: + branches: [ main ] push: branches: [ main ] paths: From 9638b67f700d7f9cc1e13b70358256fd99395763 Mon Sep 17 00:00:00 2001 From: Dingedi <64697405+dingedi@users.noreply.github.com> Date: Sat, 2 Apr 2022 21:14:27 +0200 Subject: [PATCH 02/19] Remove python 3.6 Flask-Limiter 2.2 require >= python 3.7 --- .github/workflows/run-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 9ba9c0e..f645f32 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -18,7 +18,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.6, 3.7, 3.8, 3.9] + python-version: [3.7, 3.8, 3.9] steps: - uses: actions/checkout@v2 From 00a60392891f2989212ac74d9804fc2e66a5085d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Thuret?= Date: Sat, 2 Apr 2022 22:26:37 +0200 Subject: [PATCH 03/19] Refactor & add the first test ! --- app/main.py | 11 ++++++++--- tests/test_api.py | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 3 deletions(-) create mode 100644 tests/test_api.py diff --git a/app/main.py b/app/main.py index 62d4d6e..1545a77 100644 --- a/app/main.py +++ b/app/main.py @@ -6,7 +6,7 @@ from app.app import create_app from app.default_values import DEFAULT_ARGUMENTS as DEFARGS -def main(): +def get_args(): parser = argparse.ArgumentParser( description="LibreTranslate - Free and Open Source Translation API" ) @@ -106,13 +106,18 @@ def main(): "--suggestions", default=DEFARGS['SUGGESTIONS'], action="store_true", help="Allow user suggestions" ) parser.add_argument( - "--disable-files-translation", default=DEFARGS['DISABLE_FILES_TRANSLATION'], action="store_true", help="Disable files translation" + "--disable-files-translation", default=DEFARGS['DISABLE_FILES_TRANSLATION'], action="store_true", + help="Disable files translation" ) parser.add_argument( "--disable-web-ui", default=DEFARGS['DISABLE_WEB_UI'], action="store_true", help="Disable web ui" ) - args = parser.parse_args() + return parser.parse_args() + + +def main(): + args = get_args() app = create_app(args) if sys.argv[0] == '--wsgi': diff --git a/tests/test_api.py b/tests/test_api.py new file mode 100644 index 0000000..5663e19 --- /dev/null +++ b/tests/test_api.py @@ -0,0 +1,25 @@ +import pytest +import sys +import json +from app.app import create_app +from app.main import get_args + +@pytest.fixture() +def app(): + sys.argv=[''] + app = create_app(get_args()) + + yield app + + +@pytest.fixture() +def client(app): + return app.test_client() + +def test_api_get_languages(client): + response = client.get("/languages") + response_json = json.loads(response.data) + + assert "code" in response_json[0] and "name" in response_json[0] + assert len(response_json) >= 1 + assert response.status_code == 200 From 0874dc062eab600af47e5e901121d2b52011eea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Thuret?= Date: Sun, 3 Apr 2022 11:07:37 +0200 Subject: [PATCH 04/19] reorganization of tests (1 route per file), add some basic tests --- tests/test_api/__init__.py | 0 tests/test_api/conftest.py | 18 +++++++++++++ tests/test_api/test_api_detect_language.py | 26 +++++++++++++++++++ tests/test_api/test_api_frontend_settings.py | 4 +++ .../test_api_get_languages.py} | 21 +++++---------- tests/test_api/test_api_spec.py | 10 +++++++ 6 files changed, 64 insertions(+), 15 deletions(-) create mode 100644 tests/test_api/__init__.py create mode 100644 tests/test_api/conftest.py create mode 100644 tests/test_api/test_api_detect_language.py create mode 100644 tests/test_api/test_api_frontend_settings.py rename tests/{test_api.py => test_api/test_api_get_languages.py} (53%) create mode 100644 tests/test_api/test_api_spec.py diff --git a/tests/test_api/__init__.py b/tests/test_api/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_api/conftest.py b/tests/test_api/conftest.py new file mode 100644 index 0000000..3fc54aa --- /dev/null +++ b/tests/test_api/conftest.py @@ -0,0 +1,18 @@ +import sys +import pytest + +from app.app import create_app +from app.main import get_args + + +@pytest.fixture() +def app(): + sys.argv = [''] + app = create_app(get_args()) + + yield app + + +@pytest.fixture() +def client(app): + return app.test_client() diff --git a/tests/test_api/test_api_detect_language.py b/tests/test_api/test_api_detect_language.py new file mode 100644 index 0000000..d85600c --- /dev/null +++ b/tests/test_api/test_api_detect_language.py @@ -0,0 +1,26 @@ +import json + + +def test_api_detect_language(client): + response = client.post("/detect", data={ + "q": "Hello" + }) + response_json = json.loads(response.data) + + assert "confidence" in response_json[0] and "language" in response_json[0] + assert len(response_json) >= 1 + assert response.status_code == 200 + + +def test_api_detect_language_must_fail_without_parameters(client): + response = client.post("/detect") + response_json = json.loads(response.data) + + assert "error" in response_json + assert response.status_code == 400 + + +def test_api_detect_language_must_fail_bad_request_type(client): + response = client.get("/detect") + + assert response.status_code == 405 diff --git a/tests/test_api/test_api_frontend_settings.py b/tests/test_api/test_api_frontend_settings.py new file mode 100644 index 0000000..8c3070a --- /dev/null +++ b/tests/test_api/test_api_frontend_settings.py @@ -0,0 +1,4 @@ +def test_api_get_frontend_settings(client): + response = client.get("/frontend/settings") + + assert response.status_code == 200 diff --git a/tests/test_api.py b/tests/test_api/test_api_get_languages.py similarity index 53% rename from tests/test_api.py rename to tests/test_api/test_api_get_languages.py index 5663e19..75404f1 100644 --- a/tests/test_api.py +++ b/tests/test_api/test_api_get_languages.py @@ -1,20 +1,5 @@ -import pytest -import sys import json -from app.app import create_app -from app.main import get_args -@pytest.fixture() -def app(): - sys.argv=[''] - app = create_app(get_args()) - - yield app - - -@pytest.fixture() -def client(app): - return app.test_client() def test_api_get_languages(client): response = client.get("/languages") @@ -23,3 +8,9 @@ def test_api_get_languages(client): assert "code" in response_json[0] and "name" in response_json[0] assert len(response_json) >= 1 assert response.status_code == 200 + + +def test_api_get_languages_must_fail_bad_request_type(client): + response = client.post("/spec") + + assert response.status_code == 405 diff --git a/tests/test_api/test_api_spec.py b/tests/test_api/test_api_spec.py new file mode 100644 index 0000000..3922c44 --- /dev/null +++ b/tests/test_api/test_api_spec.py @@ -0,0 +1,10 @@ +def test_api_get_spec(client): + response = client.get("/spec") + + assert response.status_code == 200 + + +def test_api_get_spec_must_fail_bad_request_type(client): + response = client.post("/spec") + + assert response.status_code == 405 From 8c7badff47699008ab316fe467166ec0701afc0e Mon Sep 17 00:00:00 2001 From: Dingedi <64697405+dingedi@users.noreply.github.com> Date: Sun, 3 Apr 2022 11:13:15 +0200 Subject: [PATCH 05/19] run pytest in verbose mode --- .github/workflows/run-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index f645f32..d5bc83b 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -42,5 +42,5 @@ jobs: flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics - name: Test with pytest - run: pytest + run: pytest -v From 2bbf17b835620eb6b632052e06a386961eb2f5ba Mon Sep 17 00:00:00 2001 From: Dingedi <64697405+dingedi@users.noreply.github.com> Date: Sun, 3 Apr 2022 12:24:39 +0200 Subject: [PATCH 06/19] fix --- tests/test_api/test_api_get_languages.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_api/test_api_get_languages.py b/tests/test_api/test_api_get_languages.py index 75404f1..d625174 100644 --- a/tests/test_api/test_api_get_languages.py +++ b/tests/test_api/test_api_get_languages.py @@ -11,6 +11,6 @@ def test_api_get_languages(client): def test_api_get_languages_must_fail_bad_request_type(client): - response = client.post("/spec") + response = client.post("/languages") assert response.status_code == 405 From d7377d174b5ae1a91f7a8fb375108123ddbc68b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Thuret?= Date: Sun, 3 Apr 2022 13:17:13 +0200 Subject: [PATCH 07/19] /languages should be only available for GET --- app/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/app.py b/app/app.py index 428de95..a06b1f1 100644 --- a/app/app.py +++ b/app/app.py @@ -239,7 +239,7 @@ def create_app(args): return render_template("javascript-licenses.html") - @app.route("/languages", methods=["GET", "POST"]) + @app.get("/languages") @limiter.exempt def langs(): """ From e3a3db5996624abb501a2451a3444c1447a8ae8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Thuret?= Date: Sun, 3 Apr 2022 19:49:49 +0200 Subject: [PATCH 08/19] remove python 3.6 --- .github/workflows/publish-package.yml | 2 +- setup.py | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish-package.yml b/.github/workflows/publish-package.yml index e9f02d5..1845d98 100644 --- a/.github/workflows/publish-package.yml +++ b/.github/workflows/publish-package.yml @@ -12,7 +12,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.6, 3.7, 3.8, 3.9] + python-version: [3.7, 3.8, 3.9] steps: - uses: actions/checkout@v2 diff --git a/setup.py b/setup.py index 970a006..ff7ebab 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ setup( ], }, - python_requires='>=3.6.0', + python_requires='>=3.7.0', long_description=open('README.md').read(), long_description_content_type="text/markdown", install_requires=open("requirements.txt", "r").readlines(), @@ -31,7 +31,6 @@ setup( classifiers=[ "License :: OSI Approved :: GNU Affero General Public License v3 ", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9" From 99c6ceba43e36ec39fba5f6ba54d478b4e3eba10 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Thuret?= Date: Sun, 3 Apr 2022 19:50:11 +0200 Subject: [PATCH 09/19] upgrade pytest --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index ff7ebab..38b0c66 100644 --- a/setup.py +++ b/setup.py @@ -26,7 +26,7 @@ setup( long_description=open('README.md').read(), long_description_content_type="text/markdown", install_requires=open("requirements.txt", "r").readlines(), - tests_require=['pytest==5.2.0'], + tests_require=['pytest==7.1.1'], setup_requires=['pytest-runner'], classifiers=[ "License :: OSI Approved :: GNU Affero General Public License v3 ", From 97ff47bc2b9e5a8ae65d784fb3253ae5d01006d2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Thuret?= Date: Sun, 3 Apr 2022 20:41:59 +0200 Subject: [PATCH 10/19] add translate test (test if it work & models are downloaded) --- tests/test_api/test_api_translate.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 tests/test_api/test_api_translate.py diff --git a/tests/test_api/test_api_translate.py b/tests/test_api/test_api_translate.py new file mode 100644 index 0000000..0df0873 --- /dev/null +++ b/tests/test_api/test_api_translate.py @@ -0,0 +1,16 @@ +import json + + +def test_api_detect_language(client): + response = client.post("/translate", data={ + "q": "Hello", + "source": "en", + "target": "es", + "format": "text" + }) + + response_json = json.loads(response.data) + + assert "translatedText" in response_json + assert response.status_code == 200 + From 55b05992b5317a5aa63a562b13a8739a6d46b254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Thuret?= Date: Mon, 4 Apr 2022 08:26:58 +0200 Subject: [PATCH 11/19] fix function name --- tests/test_api/test_api_translate.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_api/test_api_translate.py b/tests/test_api/test_api_translate.py index 0df0873..4f3e30f 100644 --- a/tests/test_api/test_api_translate.py +++ b/tests/test_api/test_api_translate.py @@ -1,7 +1,7 @@ import json -def test_api_detect_language(client): +def test_api_translate(client): response = client.post("/translate", data={ "q": "Hello", "source": "en", From 7113a30a0c932ea5c24ad7ceee0a5a386af1b682 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Thuret?= Date: Tue, 5 Apr 2022 16:39:31 +0200 Subject: [PATCH 12/19] load only en & es models (avoid to download all models) --- tests/test_api/conftest.py | 2 ++ tests/test_init.py | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/test_api/conftest.py b/tests/test_api/conftest.py index 3fc54aa..8ce03d1 100644 --- a/tests/test_api/conftest.py +++ b/tests/test_api/conftest.py @@ -2,12 +2,14 @@ import sys import pytest from app.app import create_app +from app.default_values import DEFAULT_ARGUMENTS from app.main import get_args @pytest.fixture() def app(): sys.argv = [''] + DEFAULT_ARGUMENTS['LOAD_ONLY'] = "en,es" app = create_app(get_args()) yield app diff --git a/tests/test_init.py b/tests/test_init.py index c1dbfe1..dacffef 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -4,6 +4,6 @@ from argostranslate import package def test_boot_argos(): """Test Argos translate models initialization""" - boot() + boot(["en", "es"]) - assert len(package.get_installed_packages()) > 2 + assert len(package.get_installed_packages()) >= 2 From 8d602a80c377ad850995c6af1a7b88e3e03e7d8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Thuret?= Date: Tue, 5 Apr 2022 17:12:15 +0200 Subject: [PATCH 13/19] add more tests for /translate --- tests/test_api/test_api_translate.py | 45 ++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/tests/test_api/test_api_translate.py b/tests/test_api/test_api_translate.py index 4f3e30f..96f8632 100644 --- a/tests/test_api/test_api_translate.py +++ b/tests/test_api/test_api_translate.py @@ -14,3 +14,48 @@ def test_api_translate(client): assert "translatedText" in response_json assert response.status_code == 200 + +def test_api_translate_batch(client): + + response = client.post("/translate", json={ + "q": ["Hello", "World"], + "source": "en", + "target": "es", + "format": "text" + }) + + response_json = json.loads(response.data) + + assert "translatedText" in response_json + assert isinstance(response_json["translatedText"], list) + assert len(response_json["translatedText"]) == 2 + assert response.status_code == 200 + + +def test_api_translate_unsupported_language(client): + response = client.post("/translate", data={ + "q": "Hello", + "source": "en", + "target": "zz", + "format": "text" + }) + + response_json = json.loads(response.data) + + assert "error" in response_json + assert "zz is not supported" == response_json["error"] + assert response.status_code == 400 + + +def test_api_translate_missing_parameter(client): + response = client.post("/translate", data={ + "source": "en", + "target": "es", + "format": "text" + }) + + response_json = json.loads(response.data) + + assert "error" in response_json + assert "Invalid request: missing q parameter" == response_json["error"] + assert response.status_code == 400 From c42740f6d1bd9f884b7d27802f535572954e43f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Thuret?= Date: Wed, 6 Apr 2022 14:10:41 +0200 Subject: [PATCH 14/19] Add test for docker build --- .github/workflows/run-tests.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index d5bc83b..b64f999 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -14,7 +14,7 @@ on: jobs: - tests: + tests_python: runs-on: ubuntu-latest strategy: matrix: @@ -35,7 +35,7 @@ jobs: - name: Check code style with flake8 (lint) run: | - # warnings if there are Python syntax errors or undefined names + # warnings if there are Python syntax errors or undefined names # (remove --exit-zero to fail when syntax error) flake8 . --count --exit-zero --select=E9,F63,F7,F82 --show-source --statistics # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide @@ -44,3 +44,12 @@ jobs: - name: Test with pytest run: pytest -v + + test_docker_build: + needs: [ tests_python ] + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Docker build + run: docker build -t libretranslate . From 5ea9f27ea5b9aadaa46dee88a962546b27568772 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Thuret?= Date: Wed, 6 Apr 2022 14:13:31 +0200 Subject: [PATCH 15/19] add *.py --- .github/workflows/run-tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index b64f999..d9e8948 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -7,6 +7,7 @@ on: push: branches: [ main ] paths: + - '*.py' - 'requirements.txt' - 'app/**' - 'tests/**' From c9886b736e77c7524fa7db1da6619035b014591b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Thuret?= Date: Wed, 6 Apr 2022 14:14:59 +0200 Subject: [PATCH 16/19] fix syntax error --- .github/workflows/run-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index d9e8948..3964bf7 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -53,4 +53,4 @@ jobs: steps: - uses: actions/checkout@v2 - name: Docker build - run: docker build -t libretranslate . + run: docker build -t libretranslate . From 5c44eaff17127469c188dc88248f5b8da73293bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Thuret?= Date: Wed, 6 Apr 2022 14:17:19 +0200 Subject: [PATCH 17/19] dont need to wait python tests --- .github/workflows/run-tests.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 3964bf7..fa83259 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -47,7 +47,6 @@ jobs: test_docker_build: - needs: [ tests_python ] runs-on: ubuntu-latest steps: From ba32595a43a603e60d30a2b5d6b8c92f1e449d42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Thuret?= Date: Wed, 6 Apr 2022 14:21:41 +0200 Subject: [PATCH 18/19] add another docker test --- .github/workflows/run-tests.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index fa83259..94477ce 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -53,3 +53,6 @@ jobs: - uses: actions/checkout@v2 - name: Docker build run: docker build -t libretranslate . + + - name: Docker build with some models + run: docker build -t libretranslate --build-args models=en,es . From 118924f8978533808ee38d58a78d03dec5b914ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Thuret?= Date: Wed, 6 Apr 2022 14:27:55 +0200 Subject: [PATCH 19/19] fix --- .github/workflows/run-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index 94477ce..96c6849 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -55,4 +55,4 @@ jobs: run: docker build -t libretranslate . - name: Docker build with some models - run: docker build -t libretranslate --build-args models=en,es . + run: docker build -t libretranslate --build-arg models=en,es .