Commit 71557c7a authored by Nicolas Gelot's avatar Nicolas Gelot

Rework tests

The infra to run selenium these tests was too complex, and the test are
not updated since 2016. This patch removes the dependencies of
these tests and it adds `pytest` as runner for the unit tests.
parent 54760155
FROM fedora
COPY requirements.txt requirements-dev.txt /
RUN dnf install -y\
wget\
python2-pip\
npm\
&& dnf groupinstall -y "Development Tools" \
&& pip3 install pytest ipdb ipython
&& pip3 install ipdb ipython \
&& pip3 install -r /requirements.txt \
&& pip3 install -r /requirements-dev.txt \
&& rm -f /requirements.txt /requirements-dev.txt
......@@ -26,46 +26,6 @@ update_dev_packages() {
pip3 install -r "$BASE_DIR/requirements-dev.txt"
}
install_geckodriver() {
echo '[!] Checking geckodriver'
# TODO : check the current geckodriver version
set -e
geckodriver -V > /dev/null 2>&1 || NOTFOUND=1
set +e
if [ -z "$NOTFOUND" ]; then
return
fi
GECKODRIVER_VERSION="v0.19.1"
PLATFORM="`python3 -c "import platform; print(platform.system().lower(), platform.architecture()[0])"`"
case "$PLATFORM" in
"linux 32bit" | "linux2 32bit") ARCH="linux32";;
"linux 64bit" | "linux2 64bit") ARCH="linux64";;
"windows 32 bit") ARCH="win32";;
"windows 64 bit") ARCH="win64";;
"mac 64bit") ARCH="macos";;
esac
GECKODRIVER_URL="https://github.com/mozilla/geckodriver/releases/download/$GECKODRIVER_VERSION/geckodriver-$GECKODRIVER_VERSION-$ARCH.tar.gz";
if [ -z "$1" ]; then
if [ -z "$VIRTUAL_ENV" ]; then
printf "geckodriver can't be installed because VIRTUAL_ENV is not set, you should download it from\n %s" "$GECKODRIVER_URL"
exit
else
GECKODRIVER_DIR="$VIRTUAL_ENV/bin"
fi
else
GECKODRIVER_DIR="$1"
mkdir -p -- "$GECKODRIVER_DIR"
fi
printf "Installing %s/geckodriver from\n %s" "$GECKODRIVER_DIR" "$GECKODRIVER_URL"
FILE="`mktemp`"
wget -qO "$FILE" -- "$GECKODRIVER_URL" && tar xz -C "$GECKODRIVER_DIR" -f "$FILE" geckodriver
rm -- "$FILE"
chmod 777 -- "$GECKODRIVER_DIR/geckodriver"
}
locales() {
pybabel compile -d "$SEARX_DIR/translations"
}
......@@ -80,7 +40,7 @@ pep8_check() {
unit_tests() {
echo '[!] Running unit tests'
python3 -m nose2 -s "$BASE_DIR/tests/unit"
PYTHONPATH="$BASE_DIR" pytest --disable-pytest-warnings "$BASE_DIR/tests/unit"
}
py_test_coverage() {
......@@ -90,17 +50,10 @@ py_test_coverage() {
&& coverage html
}
robot_tests() {
echo '[!] Running robot tests'
PYTHONPATH="`pwd`" python3 "$SEARX_DIR/testing.py" robot
}
tests() {
set -e
pep8_check
unit_tests
install_geckodriver
robot_tests
set +e
}
......
babel==2.3.4
mock==2.0.0
nose2[coverage-plugin]
cov-core==1.15.0
pep8==1.7.0
plone.testing==5.0.0
splinter==0.7.5
transifex-client==0.12.2
unittest2==1.1.0
zope.testrunner==4.5.1
selenium==3.5.0
mockredispy==2.9.3
pytest==4.1.0
general:
debug : False
instance_name : "searx_test"
search:
safe_search : 0
autocomplete : ""
language: "en-US"
server:
port : 11111
bind_address : 127.0.0.1
secret_key : "ultrasecretkey" # change this!
base_url : False
image_proxy : False
http_protocol_version : "1.0"
ui:
static_path : ""
templates_path : ""
default_theme : oscar
default_locale : ""
outgoing:
request_timeout : 1.0 # seconds
useragent_suffix : ""
engines:
- name : general dummy
engine : dummy
categories : general
shortcut : gd
- name : dummy dummy
engine : dummy
categories : dummy
shortcut : dd
locales:
en : English
hu : Magyar
# -*- coding: utf-8 -*-
"""Shared testing code."""
import os
import subprocess
import traceback
from os.path import dirname, join, abspath
from splinter import Browser
from unittest2 import TestCase
class SearxTestLayer:
"""Base layer for non-robot tests."""
__name__ = 'SearxTestLayer'
def setUp(cls):
pass
setUp = classmethod(setUp)
def tearDown(cls):
pass
tearDown = classmethod(tearDown)
def testSetUp(cls):
pass
testSetUp = classmethod(testSetUp)
def testTearDown(cls):
pass
testTearDown = classmethod(testTearDown)
class SearxRobotLayer():
"""Searx Robot Test Layer"""
def setUp(self):
os.setpgrp() # create new process group, become its leader
# get program paths
webapp = os.path.join(
os.path.abspath(os.path.dirname(os.path.realpath(__file__))),
'webapp.py'
)
exe = 'python'
# set robot settings path
os.environ['SEARX_SETTINGS_PATH'] = abspath(
dirname(__file__) + '/settings_robot.yml')
# run the server
self.server = subprocess.Popen(
[exe, webapp],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT
)
def tearDown(self):
os.kill(self.server.pid, 9)
# remove previously set environment variable
del os.environ['SEARX_SETTINGS_PATH']
# SEARXROBOTLAYER = SearxRobotLayer()
def run_robot_tests(tests):
print('Running {0} tests'.format(len(tests)))
for test in tests:
with Browser() as browser:
test(browser)
class SearxTestCase(TestCase):
"""Base test case for non-robot tests."""
layer = SearxTestLayer
if __name__ == '__main__':
import sys
# test cases
from tests import robot
base_dir = abspath(join(dirname(__file__), '../tests'))
if sys.argv[1] == 'robot':
test_layer = SearxRobotLayer()
errors = False
try:
test_layer.setUp()
run_robot_tests([getattr(robot, x) for x in dir(robot) if x.startswith('test_')])
except Exception:
errors = True
print('Error occured: {0}'.format(traceback.format_exc()))
test_layer.tearDown()
sys.exit(1 if errors else 0)
# -*- coding: utf-8 -*-
from time import sleep
url = "http://localhost:11111/"
def test_index(browser):
# Visit URL
browser.visit(url)
assert browser.is_text_present('about')
def test_404(browser):
# Visit URL
browser.visit(url + 'missing_link')
assert browser.is_text_present('Page not found')
def test_about(browser):
browser.visit(url)
browser.click_link_by_text('about')
assert browser.is_text_present('Why use searx?')
def test_preferences(browser):
browser.visit(url)
browser.click_link_by_text('preferences')
assert browser.is_text_present('Preferences')
assert browser.is_text_present('Cookies')
assert browser.is_element_present_by_xpath('//label[@for="checkbox_dummy"]')
def test_preferences_engine_select(browser):
browser.visit(url)
browser.click_link_by_text('preferences')
assert browser.is_element_present_by_xpath('//a[@href="#tab_engine"]')
browser.find_by_xpath('//a[@href="#tab_engine"]').first.click()
assert not browser.find_by_xpath('//input[@id="engine_general_dummy__general"]').first.checked
browser.find_by_xpath('//label[@for="engine_general_dummy__general"]').first.check()
browser.find_by_xpath('//input[@value="save"]').first.click()
# waiting for the redirect - without this the test is flaky..
sleep(1)
browser.visit(url)
browser.click_link_by_text('preferences')
browser.find_by_xpath('//a[@href="#tab_engine"]').first.click()
assert browser.find_by_xpath('//input[@id="engine_general_dummy__general"]').first.checked
def test_preferences_locale(browser):
browser.visit(url)
browser.click_link_by_text('preferences')
browser.select('locale', 'hu')
browser.find_by_xpath('//input[@value="save"]').first.click()
# waiting for the redirect - without this the test is flaky..
sleep(1)
browser.visit(url)
browser.click_link_by_text('beállítások')
browser.is_text_present('Beállítások')
def test_search(browser):
browser.visit(url)
browser.fill('q', 'test search query')
browser.find_by_xpath('//button[@type="submit"]').first.click()
assert browser.is_text_present('didn\'t find any results')
# -*- coding: utf-8 -*-
import os
import unittest2 as unittest
from plone.testing import layered
from robotsuite import RobotTestSuite
from searx.testing import SEARXROBOTLAYER
def test_suite():
suite = unittest.TestSuite()
current_dir = os.path.abspath(os.path.dirname(__file__))
robot_dir = os.path.join(current_dir, 'robot')
tests = [
os.path.join('robot', f) for f in
os.listdir(robot_dir) if f.endswith('.robot') and
f.startswith('test_')
]
for test in tests:
suite.addTests([
layered(RobotTestSuite(test), layer=SEARXROBOTLAYER),
])
return suite
......@@ -2,10 +2,10 @@
from collections import defaultdict
import mock
from searx.engines import pubmed
from searx.testing import SearxTestCase
from unittest import TestCase
class TestPubmedEngine(SearxTestCase):
class TestPubmedEngine(TestCase):
def test_request(self):
query = 'test_query'
......
......@@ -2,10 +2,10 @@
from collections import defaultdict
import mock
from searx.engines import acgsou
from searx.testing import SearxTestCase
from unittest import TestCase
class TestAcgsouEngine(SearxTestCase):
class TestAcgsouEngine(TestCase):
def test_request(self):
query = 'test_query'
......
from collections import defaultdict
import mock
from searx.engines import archlinux
from searx.testing import SearxTestCase
from unittest import TestCase
domains = {
'en': 'https://wiki.archlinux.org',
......@@ -13,7 +13,7 @@ domains = {
}
class TestArchLinuxEngine(SearxTestCase):
class TestArchLinuxEngine(TestCase):
def test_request(self):
query = 'test_query'
......
......@@ -2,10 +2,10 @@
from collections import defaultdict
import mock
from searx.engines import arxiv
from searx.testing import SearxTestCase
from unittest import TestCase
class TestBaseEngine(SearxTestCase):
class TestBaseEngine(TestCase):
def test_request(self):
query = 'test_query'
......
......@@ -2,10 +2,10 @@
from collections import defaultdict
import mock
from searx.engines import base
from searx.testing import SearxTestCase
from unittest import TestCase
class TestBaseEngine(SearxTestCase):
class TestBaseEngine(TestCase):
def test_request(self):
query = 'test_query'
......
from collections import defaultdict
import mock
from searx.engines import bing
from searx.testing import SearxTestCase
from unittest import TestCase
class TestBingEngine(SearxTestCase):
class TestBingEngine(TestCase):
def test_request(self):
bing.supported_languages = ['en', 'fr', 'zh-CHS', 'zh-CHT', 'pt-PT', 'pt-BR']
......
......@@ -2,10 +2,10 @@
from collections import defaultdict
import mock
from searx.engines import bing_images
from searx.testing import SearxTestCase
from unittest import TestCase
class TestBingImagesEngine(SearxTestCase):
class TestBingImagesEngine(TestCase):
def test_request(self):
bing_images.supported_languages = ['fr-FR', 'en-US']
......
from collections import defaultdict
import mock
from searx.engines import bing_news
from searx.testing import SearxTestCase
from unittest import TestCase
import lxml
class TestBingNewsEngine(SearxTestCase):
class TestBingNewsEngine(TestCase):
def test_request(self):
bing_news.supported_languages = ['en', 'fr']
......
......@@ -2,10 +2,10 @@
from collections import defaultdict
import mock
from searx.engines import bing_videos
from searx.testing import SearxTestCase
from unittest import TestCase
class TestBingVideosEngine(SearxTestCase):
class TestBingVideosEngine(TestCase):
def test_request(self):
bing_videos.supported_languages = ['fr-FR', 'en-US']
......
......@@ -2,10 +2,10 @@
from collections import defaultdict
import mock
from searx.engines import btdigg
from searx.testing import SearxTestCase
from unittest import TestCase
class TestBtdiggEngine(SearxTestCase):
class TestBtdiggEngine(TestCase):
def test_request(self):
query = 'test_query'
......
......@@ -2,10 +2,10 @@ from collections import defaultdict
from datetime import datetime
import mock
from searx.engines import currency_convert
from searx.testing import SearxTestCase
from unittest import TestCase
class TestCurrencyConvertEngine(SearxTestCase):
class TestCurrencyConvertEngine(TestCase):
def test_request(self):
query = 'test_query'
......
......@@ -2,10 +2,10 @@
from collections import defaultdict
import mock
from searx.engines import dailymotion
from searx.testing import SearxTestCase
from unittest import TestCase
class TestDailymotionEngine(SearxTestCase):
class TestDailymotionEngine(TestCase):
def test_request(self):
dailymotion.supported_languages = ['en', 'fr']
......
from collections import defaultdict
import mock
from searx.engines import deezer
from searx.testing import SearxTestCase
from unittest import TestCase
class TestDeezerEngine(SearxTestCase):
class TestDeezerEngine(TestCase):
def test_request(self):
query = 'test_query'
......
from collections import defaultdict
import mock
from searx.engines import deviantart
from searx.testing import SearxTestCase
from unittest import TestCase
class TestDeviantartEngine(SearxTestCase):
class TestDeviantartEngine(TestCase):
def test_request(self):
dicto = defaultdict(dict)
......
from collections import defaultdict
import mock
from searx.engines import digbt
from searx.testing import SearxTestCase
from unittest import TestCase
class TestDigBTEngine(SearxTestCase):
class TestDigBTEngine(TestCase):
def test_request(self):
query = 'test_query'
......
from collections import defaultdict
import mock
from searx.engines import digg
from searx.testing import SearxTestCase
from unittest import TestCase
class TestDiggEngine(SearxTestCase):
class TestDiggEngine(TestCase):
def test_request(self):
query = 'test_query'
......
......@@ -2,10 +2,10 @@
from collections import defaultdict
import mock
from searx.engines import doku
from searx.testing import SearxTestCase
from unittest import TestCase
class TestDokuEngine(SearxTestCase):
class TestDokuEngine(TestCase):
def test_request(self):
query = 'test_query'
......
......@@ -2,10 +2,10 @@
from collections import defaultdict
import mock
from searx.engines import load_engine, duckduckgo
from searx.testing import SearxTestCase
from unittest import TestCase
class TestDuckduckgoEngine(SearxTestCase):
class TestDuckduckgoEngine(TestCase):
def test_request(self):
duckduckgo = load_engine({'engine': 'duckduckgo', 'name': 'duckduckgo'})
......
from collections import defaultdict
import mock
from searx.engines import duckduckgo_definitions
from searx.testing import SearxTestCase
from unittest import TestCase
class TestDDGDefinitionsEngine(SearxTestCase):
class TestDDGDefinitionsEngine(TestCase):
def test_result_to_text(self):
url = ''
......
......@@ -2,10 +2,10 @@
from collections import defaultdict
import mock
from searx.engines import duckduckgo_images
from searx.testing import SearxTestCase
from unittest import TestCase
class TestDuckduckgoImagesEngine(SearxTestCase):
class TestDuckduckgoImagesEngine(TestCase):
def test_request(self):
duckduckgo_images.supported_languages = ['de-CH', 'en-US']
......
from collections import defaultdict
import mock
from searx.engines import duden
from searx.testing import SearxTestCase
from unittest import TestCase
from datetime import datetime
class TestDudenEngine(SearxTestCase):
class TestDudenEngine(TestCase):
def test_request(self):
query = 'Haus'
......
from searx.engines import dummy
from searx.testing import SearxTestCase
from unittest import TestCase
class TestDummyEngine(SearxTestCase):
class TestDummyEngine(TestCase):
def test_request(self):
test_params = [
......
......@@ -2,10 +2,10 @@
from collections import defaultdict
import mock
from searx.engines import faroo
from searx.testing import SearxTestCase
from unittest import TestCase
class TestFarooEngine(SearxTestCase):
class TestFarooEngine(TestCase):
def test_request(self):
query = 'test_query'
......
import mock
from collections import defaultdict
from searx.engines import fdroid
from searx.testing import SearxTestCase
from unittest import TestCase
class TestFdroidEngine(SearxTestCase):
class TestFdroidEngine(TestCase):
def test_request(self):
query = 'test_query'
......
from collections import defaultdict
import mock
from searx.engines import flickr
from searx.testing import SearxTestCase
from unittest import TestCase
class TestFlickrEngine(SearxTestCase):
class TestFlickrEngine(TestCase):
def test_request(self):
query = 'test_query'
......
from collections import defaultdict
import mock
from searx.engines import flickr_noapi
from searx.testing import SearxTestCase