diff --git a/eos/tests.py b/eos/tests.py
index 496481b..212fed3 100644
--- a/eos/tests.py
+++ b/eos/tests.py
@@ -55,41 +55,45 @@ class BaseJSTestCase(TestCase):
setattr(cls, method, call_method)
# Test discovery
-import eos.core.tests
-for dirpath, dirnames, filenames in os.walk('eos'):
- if dirpath == 'eos':
- # Skip this file
- continue
- if 'tests.py' in filenames:
- module_name = dirpath.replace('/', '.') + '.tests'
- module = importlib.import_module(module_name)
- for name in dir(module):
- obj = getattr(module, name)
- if isinstance(obj, type):
- if issubclass(obj, eos.core.tests.EosTestCase):
- if obj.__module__ != module_name:
- continue
- if len(sys.argv) > 1 and not obj.__module__.startswith(sys.argv[1]):
- continue
-
- impl = obj()
- cls_py = type(name + 'ImplPy', (BasePyTestCase,), {'impl': impl})
- cls_js = type(name + 'ImplJS', (BaseJSTestCase,), {'module': module_name, 'name': name})
- for method in dir(impl):
- method_val = getattr(impl, method)
- if isinstance(method_val, types.MethodType) and not hasattr(cls_py, method):
- # Python
- if not (len(sys.argv) > 2 and sys.argv[2] == 'js') and not getattr(method_val, '_js_only', False):
- cls_py.add_method(method)
- if method.startswith('test_'):
- test_case = cls_py(method)
- test_suite.addTest(test_case)
-
- # Javascript
- if not (len(sys.argv) > 2 and sys.argv[2] == 'py') and not getattr(method_val, '_py_only', False):
- if method.startswith('test_'):
- cls_js.add_method(method)
- test_case = cls_js(method)
- test_suite.addTest(test_case)
+def run_tests(prefix=None, lang=None):
+ import eos.core.tests
+ for dirpath, dirnames, filenames in os.walk('eos'):
+ if dirpath == 'eos':
+ # Skip this file
+ continue
+ if 'tests.py' in filenames:
+ module_name = dirpath.replace('/', '.') + '.tests'
+ module = importlib.import_module(module_name)
+ for name in dir(module):
+ obj = getattr(module, name)
+ if isinstance(obj, type):
+ if issubclass(obj, eos.core.tests.EosTestCase):
+ if obj.__module__ != module_name:
+ continue
+ if prefix is not None and not obj.__module__.startswith(prefix):
+ continue
+
+ impl = obj()
+ cls_py = type(name + 'ImplPy', (BasePyTestCase,), {'impl': impl})
+ cls_js = type(name + 'ImplJS', (BaseJSTestCase,), {'module': module_name, 'name': name})
+ for method in dir(impl):
+ method_val = getattr(impl, method)
+ if isinstance(method_val, types.MethodType) and not hasattr(cls_py, method):
+ # Python
+ if not (lang is not None and lang == 'js') and not getattr(method_val, '_js_only', False):
+ cls_py.add_method(method)
+ if method.startswith('test_'):
+ test_case = cls_py(method)
+ test_suite.addTest(test_case)
+
+ # Javascript
+ if not (lang is not None and lang == 'py') and not getattr(method_val, '_py_only', False):
+ if method.startswith('test_'):
+ cls_js.add_method(method)
+ test_case = cls_js(method)
+ test_suite.addTest(test_case)
+
+ TextTestRunner(verbosity=3, failfast=True).run(test_suite)
-TextTestRunner(verbosity=3, failfast=True).run(test_suite)
+if __name__ == '__main__':
+ run_tests(*sys.argv[1:])
diff --git a/eosweb/__init__.py b/eosweb/__init__.py
new file mode 100644
index 0000000..c9e4d20
--- /dev/null
+++ b/eosweb/__init__.py
@@ -0,0 +1,18 @@
+# Eos - Verifiable elections
+# Copyright © 2017 RunasSudo (Yingtong Li)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+# Allow FLASK_APP=eosweb instead of eosweb.eosweb
+from .eosweb import app
diff --git a/eosweb/eosweb.py b/eosweb/eosweb.py
new file mode 100644
index 0000000..2169be8
--- /dev/null
+++ b/eosweb/eosweb.py
@@ -0,0 +1,27 @@
+# Eos - Verifiable elections
+# Copyright © 2017 RunasSudo (Yingtong Li)
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+
+import click
+import flask
+
+app = flask.Flask(__name__)
+
+@app.cli.command('test')
+@click.option('--prefix', default=None)
+@click.option('--lang', default=None)
+def run_tests(prefix, lang):
+ import eos.tests
+ eos.tests.run_tests(prefix, lang)
diff --git a/requirements.txt b/requirements.txt
index 118885e..643bc53 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,7 +1,13 @@
+click==6.7
coverage==4.4.1
+Flask==0.12.2
+itsdangerous==0.24
+Jinja2==2.10
+MarkupSafe==1.0
mypy==0.521
PyExecJS==1.4.1
pymongo==3.5.1
six==1.10.0
Transcrypt==3.6.50
typed-ast==1.0.4
+Werkzeug==0.12.2