From f931dbf099fc196103a6e38ab4dde0a66352886d Mon Sep 17 00:00:00 2001 From: Nicolas Gelot Date: Fri, 11 Jan 2019 17:19:08 +0100 Subject: [PATCH 1/6] Update '/' endpoint to return json Very useful for test purpose, we have to bench and test that endpoint to ensure that the main feature works fine. From test part this is easier to deal with json object. --- README.rst | 1 + searx/webapp.py | 39 +++++++++++++++++++++++---------------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/README.rst b/README.rst index 371d9fbed..970e2fe42 100644 --- a/README.rst +++ b/README.rst @@ -20,6 +20,7 @@ with one command. - Run the docker-compose **up** command to start the project ``docker-compose up --build`` - Getting the ip of the spot service and go to http://:8888 +- Or you can use the command line ``curl -X POST -F 'category=general' -F 'language=en-US' -F 'q=lequipe' -F 'time_range=' -F 'output=json' http://:8888/`` .. note:: Here the command to get the IP of the spot service ``docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' my-spot_spot_1`` diff --git a/searx/webapp.py b/searx/webapp.py index ef7615fbf..c4d6dd913 100644 --- a/searx/webapp.py +++ b/searx/webapp.py @@ -452,21 +452,26 @@ def config_results(results, query): result['publishedDate'] = format_date(publishedDate) -def index_error(): - request.errors.append(gettext('search error')) - return render( - 'index.html', - ) +def index_error(exn, output): + user_error = gettext("search error") + if output == "json": + return jsonify({"error": f"{user_error}: {exn}"}) + + request.errors.append(user_error) + return render('index.html') @app.route('/search', methods=['GET', 'POST']) @app.route('/', methods=['GET', 'POST']) def index(): + # check the response format + output = request.form.get("output", "html") + # check if there is query if request.form.get('q') is None: - return render( - 'index.html', - ) + if output == 'json': + return jsonify({}), 204 + return render('index.html') selected_category = request.form.get('category') or 'general' first_page = request.form.get('pageno') @@ -489,9 +494,9 @@ def index(): # is it an invalid input parameter or something else ? if issubclass(e.__class__, SearxParameterException): - return index_error(), 400 + return index_error(e, output), 400 else: - return index_error(), 500 + return index_error(e, output), 500 if is_general_first_page: result_copy = copy.copy(search_data.results) @@ -512,8 +517,7 @@ def index(): config_results(images, search_data.query) config_results(videos, search_data.query) - return render( - 'results.html', + response = dict( results=search_data.results, q=search_data.query, selected_category=selected_category, @@ -521,12 +525,12 @@ def index(): time_range=search_data.time_range, number_of_results=format_decimal(search_data.results_number), advanced_search=request.form.get('advanced_search', None), - suggestions=search_data.suggestions, - answers=search_data.answers, - corrections=search_data.corrections, + suggestions=list(search_data.suggestions), + answers=list(search_data.answers), + corrections=list(search_data.corrections), infoboxes=search_data.infoboxes, paging=search_data.paging, - unresponsive_engines=search_data.unresponsive_engines, + unresponsive_engines=list(search_data.unresponsive_engines), current_language=match_language(search_data.language, LANGUAGE_CODES, fallback=settings['search']['language']), @@ -536,6 +540,9 @@ def index(): theme=get_current_theme_name(), favicons=global_favicons[themes.index(get_current_theme_name())] ) + if output == 'json': + return jsonify(response) + return render('results.html', **response) @app.route('/about', methods=['GET']) -- GitLab From bbb5e68b1ac9f5ae557093a468283621155d53a5 Mon Sep 17 00:00:00 2001 From: Nicolas Gelot Date: Fri, 11 Jan 2019 17:19:08 +0100 Subject: [PATCH 2/6] Remove useless commands in manage.sh --- manage.sh | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/manage.sh b/manage.sh index 4bfd69a39..1c17983f9 100755 --- a/manage.sh +++ b/manage.sh @@ -43,13 +43,6 @@ unit_tests() { PYTHONPATH="$BASE_DIR" pytest --cov=searx --disable-pytest-warnings "$BASE_DIR/tests/unit" } -py_test_coverage() { - echo '[!] Running python test coverage' - PYTHONPATH="`pwd`" python3 -m nose2 -C --log-capture --with-coverage --coverage "$SEARX_DIR" -s "$BASE_DIR/tests/unit" \ - && coverage report \ - && coverage html -} - tests() { set -e pep8_check @@ -128,7 +121,6 @@ Commands ------------------ update_packages - Check & update production dependency changes update_dev_packages - Check & update development and production dependency changes - install_geckodriver - Download & install geckodriver if not already installed (required for robot_tests) npm_packages - Download & install npm dependencies (source manage.sh to update the PATH) Build @@ -141,9 +133,7 @@ Commands ----- unit_tests - Run unit tests pep8_check - Pep8 validation - robot_tests - Run selenium tests tests - Run all python tests (pep8, unit, robot_tests) - py_test_coverage - Unit test coverage " } -- GitLab From cc26dde77a7ce02bd6fb7b3595bbaa59cdd755dd Mon Sep 17 00:00:00 2001 From: Nicolas Gelot Date: Wed, 16 Jan 2019 23:37:08 +0100 Subject: [PATCH 3/6] Update pep8 tools to pycodestyle pep8 is deprecated, it is replaced by pycodestyle. --- manage.sh | 3 ++- requirements-dev.txt | 2 +- searx/__init__.py | 3 ++- searx/engines/bing_images.py | 2 +- searx/engines/genius.py | 1 + searx/engines/google.py | 5 ++--- searx/engines/google_videos.py | 4 ++-- searx/engines/swisscows.py | 8 ++++---- searx/query.py | 2 +- searx/results.py | 2 +- searx/utils.py | 5 +++-- searx/webapp.py | 5 +++-- tests/unit/engines/test_currency_convert.py | 7 +++++-- 13 files changed, 28 insertions(+), 21 deletions(-) diff --git a/manage.sh b/manage.sh index 1c17983f9..eb701bfcd 100755 --- a/manage.sh +++ b/manage.sh @@ -35,7 +35,8 @@ pep8_check() { # ignored rules: # E402 module level import not at top of file # W503 line break before binary operator - pep8 --exclude=searx/static --max-line-length=120 --ignore "E402,W503" "$SEARX_DIR" "$BASE_DIR/tests" + # E722 do not use bare 'except' + pycodestyle --exclude=searx/static --max-line-length=120 --ignore "E402,W503,E722" "$SEARX_DIR" "$BASE_DIR/tests" } unit_tests() { diff --git a/requirements-dev.txt b/requirements-dev.txt index 0929b0ea8..8072c6be8 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,6 +1,6 @@ babel==2.3.4 mock==2.0.0 -pep8==1.7.0 +pycodestyle==2.4.0 mockredispy==2.9.3 pytest==4.1.0 pytest-cov==2.6.1 diff --git a/searx/__init__.py b/searx/__init__.py index 0dd557b7f..63c7f9ffe 100644 --- a/searx/__init__.py +++ b/searx/__init__.py @@ -23,7 +23,7 @@ from io import open from ssl import OPENSSL_VERSION_INFO, OPENSSL_VERSION try: from yaml import load -except: +except ImportError: from sys import exit, stderr stderr.write('[E] install pyyaml\n') exit(2) @@ -38,6 +38,7 @@ def check_settings_yml(file_name): else: return None + # find location of settings.yml if 'SEARX_SETTINGS_PATH' in environ: # if possible set path to settings using the diff --git a/searx/engines/bing_images.py b/searx/engines/bing_images.py index 876011f1d..6d769577a 100644 --- a/searx/engines/bing_images.py +++ b/searx/engines/bing_images.py @@ -116,7 +116,7 @@ def _fetch_supported_languages(resp): regions = dom.xpath(regions_xpath) for region in regions: - code = re.search('setmkt=[^\&]+', region).group()[7:] + code = re.search('setmkt=[^&]+', region).group()[7:] if code == 'nb-NO': code = 'no-NO' diff --git a/searx/engines/genius.py b/searx/engines/genius.py index b265e9d76..aa5afad9b 100644 --- a/searx/engines/genius.py +++ b/searx/engines/genius.py @@ -72,6 +72,7 @@ def parse_album(hit): result.update({'content': 'Released: {}'.format(year)}) return result + parse = {'lyric': parse_lyric, 'song': parse_lyric, 'artist': parse_artist, 'album': parse_album} diff --git a/searx/engines/google.py b/searx/engines/google.py index 180e8fc09..fc79d8ea4 100644 --- a/searx/engines/google.py +++ b/searx/engines/google.py @@ -89,9 +89,8 @@ url_map = 'https://www.openstreetmap.org/'\ # search-url search_path = '/search' -search_url = ('https://{hostname}' + - search_path + - '?{query}&start={offset}&gws_rd=cr&gbv=1&lr={lang}&hl={lang_short}&ei=x') +search_url = ('https://{hostname}' + search_path + '?{query}' + '&start={offset}&gws_rd=cr&gbv=1&lr={lang}&hl={lang_short}&ei=x') time_range_search = "&tbs=qdr:{range}" time_range_dict = {'day': 'd', diff --git a/searx/engines/google_videos.py b/searx/engines/google_videos.py index 9a41b2dfa..4274f0d07 100644 --- a/searx/engines/google_videos.py +++ b/searx/engines/google_videos.py @@ -76,11 +76,11 @@ def response(resp): # get thumbnails script = str(dom.xpath('//script[contains(., "_setImagesSrc")]')[0].text) id = result.xpath('.//div[@class="s"]//img/@id')[0] - thumbnails_data = re.findall('s=\'(.*?)(?:\\\\[a-z,1-9,\\\\]+\'|\')\;var ii=\[(?:|[\'vidthumb\d+\',]+)\'' + id, + thumbnails_data = re.findall(r's=\'(.*?)(?:\\\\[a-z,1-9,\\\\]+\'|\')\;var ii=\[(?:|[\'vidthumb\d+\',]+)\'' + id, script) tmp = [] if len(thumbnails_data) != 0: - tmp = re.findall('(data:image/jpeg;base64,[a-z,A-Z,0-9,/,\+]+)', thumbnails_data[0]) + tmp = re.findall(r'(data:image/jpeg;base64,[a-z,A-Z,0-9,/,\+]+)', thumbnails_data[0]) thumbnail = '' if len(tmp) != 0: thumbnail = tmp[-1] diff --git a/searx/engines/swisscows.py b/searx/engines/swisscows.py index f2fafec3a..17b32ec61 100644 --- a/searx/engines/swisscows.py +++ b/searx/engines/swisscows.py @@ -28,10 +28,10 @@ search_string = '?{query}&page={page}' supported_languages_url = base_url # regex -regex_json = re.compile('initialData: {"Request":(.|\n)*},\s*environment') -regex_json_remove_start = re.compile('^initialData:\s*') -regex_json_remove_end = re.compile(',\s*environment$') -regex_img_url_remove_start = re.compile('^https?://i\.swisscows\.ch/\?link=') +regex_json = re.compile(r'initialData: {"Request":(.|\n)*},\s*environment') +regex_json_remove_start = re.compile(r'^initialData:\s*') +regex_json_remove_end = re.compile(r',\s*environment$') +regex_img_url_remove_start = re.compile(r'^https?://i\.swisscows\.ch/\?link=') # do search-request diff --git a/searx/query.py b/searx/query.py index fe44496c6..fdba2e092 100644 --- a/searx/query.py +++ b/searx/query.py @@ -49,7 +49,7 @@ class RawTextQuery(object): self.query_parts = [] # split query, including whitespaces - raw_query_parts = re.split(r'(\s+)' if isinstance(self.query, str) else b'(\s+)', self.query) + raw_query_parts = re.split(r'(\s+)' if isinstance(self.query, str) else r'(\s+)'.encode(), self.query) parse_next = True diff --git a/searx/results.py b/searx/results.py index cde7be121..6c5b52eaf 100644 --- a/searx/results.py +++ b/searx/results.py @@ -171,7 +171,7 @@ class ResultContainer(object): continue try: result['url'] = result['url'] - except: + except KeyError: pass if 'title' in result and not isinstance(result['title'], str): continue diff --git a/searx/utils.py b/searx/utils.py index c59ceca9e..d1a28ea24 100644 --- a/searx/utils.py +++ b/searx/utils.py @@ -6,6 +6,7 @@ import re from babel.core import get_global from babel.dates import format_date +from babel import UnknownLocaleError from codecs import getincrementalencoder from imp import load_source from numbers import Number @@ -205,7 +206,7 @@ def format_date_by_locale(date, locale_string): # to avoid crashing if locale is not supported by babel try: formatted_date = format_date(date, locale=locale_string) - except: + except UnknownLocaleError: formatted_date = format_date(date, "YYYY-MM-dd") return formatted_date @@ -255,7 +256,7 @@ def get_torrent_size(filesize, filesize_multiplier): filesize = int(filesize * 1000 * 1000) elif filesize_multiplier == 'KiB': filesize = int(filesize * 1000) - except: + except ValueError: filesize = None return filesize diff --git a/searx/webapp.py b/searx/webapp.py index c4d6dd913..a6525a19e 100644 --- a/searx/webapp.py +++ b/searx/webapp.py @@ -40,8 +40,9 @@ logger = logger.getChild('webapp') try: from pygments import highlight from pygments.lexers import get_lexer_by_name + from pygments.util import ClassNotFound from pygments.formatters import HtmlFormatter -except: +except ImportError: logger.critical("cannot import dependency: pygments") from sys import exit @@ -178,7 +179,7 @@ def code_highlighter(codelines, language=None): try: # find lexer by programing language lexer = get_lexer_by_name(language, stripall=True) - except: + except ClassNotFound: # if lexer is not found, using default one logger.debug('highlighter cannot find lexer for {0}'.format(language)) lexer = get_lexer_by_name('text', stripall=True) diff --git a/tests/unit/engines/test_currency_convert.py b/tests/unit/engines/test_currency_convert.py index dee745110..ae7aa88b0 100644 --- a/tests/unit/engines/test_currency_convert.py +++ b/tests/unit/engines/test_currency_convert.py @@ -48,8 +48,11 @@ class TestCurrencyConvertEngine(TestCase): results = currency_convert.response(response) self.assertEqual(type(results), list) self.assertEqual(len(results), 1) - self.assertEqual(results[0]['answer'], '10.0 GBP = 5.0 USD, 1 GBP (pound sterling)' + - ' = 0.5 USD (United States dollar)') + self.assertEqual( + results[0]['answer'], + ('10.0 GBP = 5.0 USD, 1 GBP (pound sterling)' + ' = 0.5 USD (United States dollar)') + ) target_url = 'https://duckduckgo.com/js/spice/currency/1/{}/{}'.format( dicto['from'], dicto['to']) -- GitLab From 33079423a4fa374fb7491519cee5cea8a0b7e26b Mon Sep 17 00:00:00 2001 From: Nicolas Gelot Date: Fri, 11 Jan 2019 17:19:08 +0100 Subject: [PATCH 4/6] Bootstrap functional test Before to try to optimize spot engines we need to have some tests to bench the search duration and that performs some checks on the results --- .gitlab-ci.yml | 16 +++++++++++++++- Dockerfile.env | 1 + manage.sh | 11 +++++++++-- pytest.ini | 2 ++ requirements-dev.txt | 1 + tests/functional/conftest.py | 33 +++++++++++++++++++++++++++++++++ tests/functional/test_api.py | 29 +++++++++++++++++++++++++++++ 7 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 pytest.ini create mode 100644 tests/functional/conftest.py create mode 100644 tests/functional/test_api.py diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 96c4c67cb..e0e935326 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -21,10 +21,24 @@ coding-rules: script: - ./manage.sh pep8_check -unittest: +unit-test: stage: test before_script: - ./manage.sh update_dev_packages script: - ./manage.sh unit_tests coverage: '/TOTAL.*\s+(\d+%)$/' + +functional-test: + stage: test + image: docker:stable + services: + - docker:dind + variables: + DOCKER_HOST: tcp://docker:2375/ + DOCKER_DRIVER: overlay2 + before_script: + - docker run -id --rm -v $(pwd):/ws -e DOCKER_HOST=tcp://$(cat /etc/hosts | grep docker | cut -f1):2375/ -w /ws --name spotenv $CI_REGISTRY_IMAGE/env:latest sh + - docker exec -i spotenv ./manage.sh update_dev_packages + script: + - docker exec -i spotenv ./manage.sh functional_tests diff --git a/Dockerfile.env b/Dockerfile.env index 23ab4ec19..964dcbc5c 100644 --- a/Dockerfile.env +++ b/Dockerfile.env @@ -6,6 +6,7 @@ RUN dnf install -y\ wget\ python2-pip\ npm\ + docker \ && dnf groupinstall -y "Development Tools" \ && pip3 install ipdb ipython \ && pip3 install -r /requirements.txt \ diff --git a/manage.sh b/manage.sh index eb701bfcd..794bb4e4c 100755 --- a/manage.sh +++ b/manage.sh @@ -41,13 +41,19 @@ pep8_check() { unit_tests() { echo '[!] Running unit tests' - PYTHONPATH="$BASE_DIR" pytest --cov=searx --disable-pytest-warnings "$BASE_DIR/tests/unit" + PYTHONPATH="$BASE_DIR" pytest --cov=searx "$BASE_DIR/tests/unit" +} + +functional_tests() { + echo '[!] Running unit tests' + PYTHONPATH="$BASE_DIR" pytest "$BASE_DIR/tests/functional" } tests() { set -e pep8_check unit_tests + functional_tests set +e } @@ -133,8 +139,9 @@ Commands Tests ----- unit_tests - Run unit tests + functional_tests - Run functional tests pep8_check - Pep8 validation - tests - Run all python tests (pep8, unit, robot_tests) + tests - Run all python tests (pep8, unit, functional) " } diff --git a/pytest.ini b/pytest.ini new file mode 100644 index 000000000..838879d38 --- /dev/null +++ b/pytest.ini @@ -0,0 +1,2 @@ +[pytest] +addopts = -s --dockerc-build --dockerc-attach-network --disable-pytest-warnings diff --git a/requirements-dev.txt b/requirements-dev.txt index 8072c6be8..1de575509 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -4,3 +4,4 @@ pycodestyle==2.4.0 mockredispy==2.9.3 pytest==4.1.0 pytest-cov==2.6.1 +pytest-dockerc==1.0.5 diff --git a/tests/functional/conftest.py b/tests/functional/conftest.py new file mode 100644 index 000000000..cfade83ac --- /dev/null +++ b/tests/functional/conftest.py @@ -0,0 +1,33 @@ +import pytest +import redis +import requests + +from pytest_dockerc import Wait, Context + + +class SpotContext(Context): + @property + def url(self): + addr = self.container_addr("spot") + port = self.container_port("spot") + return f"http://{addr}:{port}" + + def wait_for_running_state(self): + Wait(ignored_exns=(requests.ConnectionError,))(lambda: requests.get(self.url)) + + +@pytest.fixture(scope="session") +def ctx(dockerc, dockerc_logs): + context = SpotContext(dockerc) + context.wait_for_running_state() + yield context + + +@pytest.fixture +def redisdb(ctx): + """ purge the db + """ + db = redis.Redis(ctx.container_addr("redis")) + for key in db.keys(): + db.delete(key) + yield db diff --git a/tests/functional/test_api.py b/tests/functional/test_api.py new file mode 100644 index 000000000..3211d65c7 --- /dev/null +++ b/tests/functional/test_api.py @@ -0,0 +1,29 @@ +import requests + + +class DataReq(dict): + def __init__(self, **kwargs): + self["category"] = kwargs.get("category", "general") + self["language"] = kwargs.get("language", "en-US") + self["q"] = kwargs.get("q", "lequipe.fr") + self["time_range"] = kwargs.get("time_range", "") + self["output"] = kwargs.get("output", "json") + + +def test_index(ctx, redisdb): + """ Test the main endpoint to ensure that some results are returned + """ + res = requests.post(ctx.url) + assert res.status_code == 200 + + res = requests.post(ctx.url, data={"output": "json"}) + assert res.status_code == 204 + + data = DataReq() + res = requests.post(ctx.url, data=data) + assert res.status_code == 200 + + response = res.json() + assert len(response["results"]) > 5 + assert len(response["image_results"]) == 5 + assert len(response['videos_results']) == 5 -- GitLab From 741cc323a42ff453f12015df5dc8b7bb5bbeff4a Mon Sep 17 00:00:00 2001 From: Nicolas Gelot Date: Sat, 12 Jan 2019 01:52:52 +0100 Subject: [PATCH 5/6] Copy only the python package in Dockerfile --- Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 6c0f11f86..2df7c8aa7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -32,9 +32,9 @@ RUN apk -U add \ ca-certificates \ && rm -f /var/cache/apk/* -COPY . . +COPY searx /usr/local/searx/searx -RUN chown -R searx:searx * +RUN chown -R searx:searx /usr/local/searx USER searx -- GitLab From ce092d6ee14473e65a2d8a927f501e769886be9d Mon Sep 17 00:00:00 2001 From: Nicolas Gelot Date: Sat, 12 Jan 2019 01:40:04 +0100 Subject: [PATCH 6/6] Include coverage of functional tests --- .gitlab-ci.yml | 19 ++++++++++++++++++- Dockerfile | 7 +------ docker-compose-coverage.yml | 18 ++++++++++++++++++ manage.sh | 19 +++++++++++++++++-- 4 files changed, 54 insertions(+), 9 deletions(-) create mode 100644 docker-compose-coverage.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e0e935326..537afb856 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,6 +3,7 @@ image: $CI_REGISTRY_IMAGE/env:latest stages: - build - test + - report front-end: stage: build @@ -27,7 +28,10 @@ unit-test: - ./manage.sh update_dev_packages script: - ./manage.sh unit_tests - coverage: '/TOTAL.*\s+(\d+%)$/' + artifacts: + paths: + - coverage + expire_in: 1 hour functional-test: stage: test @@ -42,3 +46,16 @@ functional-test: - docker exec -i spotenv ./manage.sh update_dev_packages script: - docker exec -i spotenv ./manage.sh functional_tests + artifacts: + paths: + - coverage + expire_in: 1 hour + +coverage: + stage: report + script: + - ./manage.sh coverage + dependencies: + - unit-test + - functional-test + coverage: '/TOTAL.*\s+(\d+%)$/' diff --git a/Dockerfile b/Dockerfile index 2df7c8aa7..49981f1d2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,8 +6,6 @@ EXPOSE 8888 WORKDIR /usr/local/searx CMD ["python", "searx/webapp.py"] -RUN adduser -D -h /usr/local/searx -s /bin/sh searx searx - COPY requirements.txt ./requirements.txt RUN apk -U add \ @@ -22,6 +20,7 @@ RUN apk -U add \ ca-certificates \ && pip install --upgrade pip \ && pip install --no-cache -r requirements.txt \ + && pip install --no-cache coverage \ && apk del \ build-base \ libffi-dev \ @@ -34,10 +33,6 @@ RUN apk -U add \ COPY searx /usr/local/searx/searx -RUN chown -R searx:searx /usr/local/searx - -USER searx - RUN sed -i "s/127.0.0.1/0.0.0.0/g" searx/settings.yml STOPSIGNAL SIGINT diff --git a/docker-compose-coverage.yml b/docker-compose-coverage.yml new file mode 100644 index 000000000..bd10ea3e4 --- /dev/null +++ b/docker-compose-coverage.yml @@ -0,0 +1,18 @@ +version: '3.6' + +services: + spot: + entrypoint: + - coverage + - run + - --source=searx + command: + - searx/webapp.py + volumes: + - coverage:/coverage + environment: + COVERAGE_FILE: /coverage/func + +volumes: + coverage: + name: spot-coverage diff --git a/manage.sh b/manage.sh index 794bb4e4c..79fdd244e 100755 --- a/manage.sh +++ b/manage.sh @@ -8,6 +8,7 @@ set -e # subshell PYTHONPATH="$BASE_DIR" SEARX_DIR="$BASE_DIR/searx" +COV_DIR="$BASE_DIR/coverage" ACTION="$1" @@ -41,12 +42,26 @@ pep8_check() { unit_tests() { echo '[!] Running unit tests' - PYTHONPATH="$BASE_DIR" pytest --cov=searx "$BASE_DIR/tests/unit" + mkdir -p "$COV_DIR" + chmod a+w "$COV_DIR" + PYTHONPATH="$BASE_DIR" COVERAGE_FILE="$COV_DIR"/unit pytest --cov=searx "$BASE_DIR/tests/unit" } functional_tests() { echo '[!] Running unit tests' - PYTHONPATH="$BASE_DIR" pytest "$BASE_DIR/tests/functional" + mkdir -p "$COV_DIR" + chmod a+w "$COV_DIR" + PYTHONPATH="$BASE_DIR" COMPOSE_FILE=docker-compose.yml:docker-compose-coverage.yml \ + pytest "$BASE_DIR/tests/functional" + docker run -itd --rm --name tmp-vol -v spot-coverage:/coverage alpine + docker cp tmp-vol:/coverage/func $COV_DIR + docker stop tmp-vol +} + +coverage() { + sed -i 's!/usr/local/searx!'$BASE_DIR'!g' "$COV_DIR"/func + coverage3 combine coverage/func coverage/unit + coverage3 report } tests() { -- GitLab