diff --git a/.gitignore b/.gitignore index 2886e55f4ebd761f44add8cccf47fa9ea63f9f85..299c19dad7c879992bab33d3dac6f0eb2fa87bf2 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,5 @@ nginx.log nginx.pid nginx.conf uwsgi.sock +.coverage +htmlcov/ diff --git a/README.md b/README.md index 5089659ed206165e1cf778fc05623763021ee1c3..b8d5b45bbcb196c3adafa39fc3f0071f2beec3d3 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,11 @@ Hinweis: diese Variante startet eine lokale Testversion der Website, es sind nic Alternativ, insbesondere zum Testen der Zugriffsbeschränkungen: Siehe `nginx.example.conf`. +### Unittests +Tests können mittels `./tests.py` ausgeführt werden. + +Coverage Tests können mittels `rm .coverage; python -m coverage run tests.py; python -m coverage html` ausgeführt werden. Dies erstellt einen Ordner `htmlcov` in dem HTML Output liegt. + ### Zum Mitmachen: 1. Repo für den eigenen User forken, dafür den "Fork-Button" auf der Website verwenden 2. Sicherstellen, dass der Upstream richtig konfiguriert ist: @@ -39,6 +44,7 @@ Optional (wird für einzelne Features benötigt): * python-ldap (Login mit Fachschaftsaccount) * python-icalendar (SoGo-Kalenderimport für Sitzungsankündigungen) * python-mysql-connector (wenn MySQL als Datenbank verwendet werden soll) +* python-coverage (Für Coverage Tests benötigt) Kurzform unter Ubuntu: `sudo apt install python3 python3-flask sqlite python3-requests python3-lxml python3-ldap3 python3-icalendar python3-mysql.connector` diff --git a/db.py b/db.py index 04f7fe83ff4ff4540f7d138c819fbce7bc6a9a0f..f64e6a36b6db5dabb604c0bbdaaebf3c20133fdb 100644 --- a/db.py +++ b/db.py @@ -23,8 +23,10 @@ if config['DB_ENGINE'] == 'sqlite': db = sqlite3.connect(config['SQLITE_DB']) cur = db.cursor() if config['SQLITE_INIT_SCHEMA']: + print('Init db schema') cur.executescript(open(config['DB_SCHEMA']).read()) if config['SQLITE_INIT_DATA'] and created: + print('Init db data') cur.executescript(open(config['DB_DATA']).read()) db.commit() db.close() diff --git a/server.py b/server.py index 0d6884800832851607080f4dafdd777e0a8fe1e3..b13d02c78416130a3124146c5cef805b61e4e7e1 100644 --- a/server.py +++ b/server.py @@ -25,6 +25,16 @@ if sys.argv[0].endswith('run.py'): config['SQLITE_INIT_DATA'] = True config['DEBUG'] = True config.from_pyfile('config.py', silent=True) +if sys.argv[0].endswith('tests.py'): + print('running in test mode') + import tempfile + # ensure we always use a clean sqlite db for tests + config['DB_ENGINE'] = 'sqlite' + config['SQLITE_DB'] = tempfile.mktemp(prefix='flasktestingtmp') + print('DB File: {}'.format(config['SQLITE_DB'])) + config['SQLITE_INIT_DATA'] = True + config['SQLITE_INIT_SCHEMA'] = True + config['DEBUG'] = True if config['DEBUG']: app.jinja_env.auto_reload = True @@ -338,7 +348,7 @@ def login(): user = userinfo.get('uid') if not check_mod(user, groups): flash('Login fehlgeschlagen!') - return render_template('login.html') + return make_response(render_template('login.html'), 403) session['user'] = userinfo dbuser = query('SELECT * FROM users WHERE name = ?', user) if not dbuser: diff --git a/tests.py b/tests.py new file mode 100755 index 0000000000000000000000000000000000000000..d0a7a69aa7227e3235654594fc46273b4ad637ec --- /dev/null +++ b/tests.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 + +import os +import unittest +import server + +import flask + +class VideoTestCase(unittest.TestCase): + @classmethod + def setUpClass(cls): + server.app.testing = True + + @classmethod + def tearDownClass(cls): + os.unlink(server.app.config['SQLITE_DB']) + + def setUp(self): + self.app = server.app.test_client() + + def test_index(self): + r = self.app.get('/') + assert r.status_code == 200 + + def test_courses(self): + r = self.app.get('/courses') + assert r.status_code == 200 + + def test_faq(self): + r = self.app.get('/faq') + assert r.status_code == 200 + + def test_sitemap(self): + r = self.app.get('/sitemap.xml') + assert r.status_code == 200 + + def test_login(self): + # test login page + r = self.app.get('/internal/login') + assert r.status_code == 200 + # test successfull login + with self.app as c: + r = c.post('/internal/login', data={'user': 'videoag', 'password': 'videoag', 'ref': '/'}) + assert flask.session['user'] + assert r.status_code == 302 + assert '<a href="/">' in r.data.decode() + # test unsuccessfull login + with self.app as c: + r = c.post('/internal/login', data={'user': 'videoag', 'password': 'asd', 'ref': '/'}) + assert flask.session['user'] + assert r.status_code == 403 + assert 'Login fehlgeschlagen' in r.data.decode() + + +if __name__ == '__main__': + unittest.main() +