From f20d686a4972db5e6bc10bdbd48d27d4b035a716 Mon Sep 17 00:00:00 2001 From: Christian Heller Date: Tue, 26 Mar 2024 01:25:27 +0100 Subject: [PATCH] Add Processes module tests, re-organize/re-factor unit tests. --- tests/{test_days.py => days.py} | 53 ++-------------- tests/processes.py | 105 ++++++++++++++++++++++++++++++++ tests/utils.py | 38 ++++++++++++ 3 files changed, 147 insertions(+), 49 deletions(-) rename tests/{test_days.py => days.py} (70%) create mode 100644 tests/processes.py create mode 100644 tests/utils.py diff --git a/tests/test_days.py b/tests/days.py similarity index 70% rename from tests/test_days.py rename to tests/days.py index bc2e82d..5ff6459 100644 --- a/tests/test_days.py +++ b/tests/days.py @@ -1,14 +1,10 @@ -"""Test days module.""" +"""Test Days module.""" from unittest import TestCase -from threading import Thread from http.client import HTTPConnection -from urllib.parse import urlencode from datetime import datetime -from os import remove as remove_file -from plomtask.http import TaskHandler, TaskServer +from tests.utils import TestCaseWithDB, TestCaseWithServer from plomtask.days import Day, todays_date from plomtask.misc import HandledException -from plomtask.db import DatabaseFile, DatabaseConnection class TestsSansDB(TestCase): @@ -41,19 +37,9 @@ class TestsSansDB(TestCase): self.assertEqual(Day('2024-03-17').weekday, 'Sunday') -class TestsWithDB(TestCase): +class TestsWithDB(TestCaseWithDB): """Days module tests not requiring DB setup.""" - def setUp(self): - timestamp = datetime.now().timestamp() - self.db_file = DatabaseFile(f'test_db:{timestamp}') - self.db_file.remake() - self.db_conn = DatabaseConnection(self.db_file) - - def tearDown(self): - self.db_conn.close() - remove_file(self.db_file.path) - def test_Day_by_date(self): """Test Day.by_date().""" self.assertEqual(None, Day.by_date(self.db_conn, '2024-01-01')) @@ -106,34 +92,9 @@ class TestsWithDB(TestCase): self.assertEqual(Day('2023-02-28').next_date, '2023-03-01') -class TestsWithServer(TestsWithDB): +class TestsWithServer(TestCaseWithServer): """Tests against our HTTP server/handler (and database).""" - def setUp(self): - super().setUp() - self.httpd = TaskServer(self.db_file, ('localhost', 0), TaskHandler) - self.server_thread = Thread(target=self.httpd.serve_forever) - self.server_thread.daemon = True - self.server_thread.start() - - def test_do_POST_day(self): - """Test POST /day and its effect on the database.""" - http_conn = HTTPConnection(*self.httpd.server_address) - form_data = {'comment': 'foo'} - encoded_form_data = urlencode(form_data).encode('utf-8') - headers = {'Content-Type': 'application/x-www-form-urlencoded', - 'Content-Length': str(len(encoded_form_data))} - http_conn.request('POST', '/day?date=FOO', - body=encoded_form_data, headers=headers) - self.assertEqual(http_conn.getresponse().status, 400) - self.assertEqual(Day.all(self.db_conn), []) - http_conn.request('POST', '/day?date=2024-01-01', - body=encoded_form_data, headers=headers) - self.assertEqual(http_conn.getresponse().status, 302) - retrieved = Day.by_date(self.db_conn, '2024-01-01') - self.assertEqual(retrieved.comment, 'foo') - self.assertEqual(Day.all(self.db_conn), [retrieved]) - def test_do_GET(self): """Test /day and /calendar response codes.""" http_conn = HTTPConnection(*self.httpd.server_address) @@ -153,9 +114,3 @@ class TestsWithServer(TestsWithDB): self.assertEqual(http_conn.getresponse().status, 200) http_conn.request('GET', '/calendar?start=foo') self.assertEqual(http_conn.getresponse().status, 400) - - def tearDown(self): - self.httpd.shutdown() - self.httpd.server_close() - self.server_thread.join() - super().tearDown() diff --git a/tests/processes.py b/tests/processes.py new file mode 100644 index 0000000..271289b --- /dev/null +++ b/tests/processes.py @@ -0,0 +1,105 @@ +"""Test Processes module.""" +from unittest import TestCase +from http.client import HTTPConnection +from urllib.parse import urlencode +from tests.utils import TestCaseWithDB, TestCaseWithServer +from plomtask.processes import Process + + +class TestsSansDB(TestCase): + """Module tests not requiring DB setup.""" + + def test_Process_versioned_defaults(self): + """Test defaults of Process' VersionedAttributes.""" + self.assertEqual(Process(None).title.newest, 'UNNAMED') + self.assertEqual(Process(None).description.newest, '') + self.assertEqual(Process(None).effort.newest, 1.0) + + +class TestsWithDB(TestCaseWithDB): + """Mdule tests not requiring DB setup.""" + + def test_Process_save(self): + """Test Process.save().""" + p_saved = Process(None) + p_saved.save(self.db_conn) + self.assertEqual(p_saved.id_, + Process.by_id(self.db_conn, 1, create=False).id_) + p_saved = Process(0) + p_saved.save(self.db_conn) + self.assertEqual(p_saved.id_, + Process.by_id(self.db_conn, 2, create=False).id_) + p_saved = Process(5) + p_saved.save(self.db_conn) + self.assertEqual(p_saved.id_, + Process.by_id(self.db_conn, 5, create=False).id_) + p_saved.title.set('named') + p_loaded = Process.by_id(self.db_conn, p_saved.id_) + self.assertNotEqual(p_saved.title.history, p_loaded.title.history) + p_saved.save(self.db_conn) + p_loaded = Process.by_id(self.db_conn, p_saved.id_) + self.assertEqual(p_saved.title.history, p_loaded.title.history) + + def test_Process_by_id(self): + """Test Process.by_id().""" + self.assertEqual(None, Process.by_id(self.db_conn, None, create=False)) + self.assertEqual(None, Process.by_id(self.db_conn, 0, create=False)) + self.assertEqual(None, Process.by_id(self.db_conn, 1, create=False)) + self.assertNotEqual(Process(1).id_, + Process.by_id(self.db_conn, None, create=True).id_) + self.assertNotEqual(Process(1).id_, + Process.by_id(self.db_conn, 0, create=True).id_) + self.assertEqual(Process(1).id_, + Process.by_id(self.db_conn, 1, create=True).id_) + self.assertEqual(Process(2).id_, + Process.by_id(self.db_conn, 2, create=True).id_) + + def test_Process_all(self): + """Test Process.all().""" + p_1 = Process(None) + p_1.save(self.db_conn) + p_2 = Process(None) + p_2.save(self.db_conn) + self.assertEqual({p_1.id_, p_2.id_}, + set(p.id_ for p in Process.all(self.db_conn))) + + +class TestsWithServer(TestCaseWithServer): + """Module tests against our HTTP server/handler (and database).""" + + def test_do_POST_process(self): + """Test POST /process and its effect on the database.""" + def post_data_to_expect(form_data: dict, to_: str, expect: int): + encoded_form_data = urlencode(form_data).encode('utf-8') + headers = {'Content-Type': 'application/x-www-form-urlencoded', + 'Content-Length': str(len(encoded_form_data))} + http_conn.request('POST', to_, + body=encoded_form_data, headers=headers) + self.assertEqual(http_conn.getresponse().status, expect) + http_conn = HTTPConnection(*self.httpd.server_address) + form_data = {'title': 'foo', 'description': 'foo', 'effort': 1.0} + post_data_to_expect(form_data, '/process?id=FOO', 400) + form_data['effort'] = 'foo' + post_data_to_expect(form_data, '/process?id=', 400) + form_data['effort'] = None + post_data_to_expect(form_data, '/process?id=', 400) + form_data = {'title': None, 'description': 1, 'effort': 1.0} + post_data_to_expect(form_data, '/process?id=', 302) + retrieved = Process.by_id(self.db_conn, 1) + self.assertEqual(retrieved.title.newest, 'None') + self.assertEqual([p.id_ for p in Process.all(self.db_conn)], + [retrieved.id_]) + + def test_do_GET(self): + """Test /process and /processes response codes.""" + http_conn = HTTPConnection(*self.httpd.server_address) + http_conn.request('GET', '/process') + self.assertEqual(http_conn.getresponse().status, 200) + http_conn.request('GET', '/process?id=') + self.assertEqual(http_conn.getresponse().status, 200) + http_conn.request('GET', '/process?id=0') + self.assertEqual(http_conn.getresponse().status, 200) + http_conn.request('GET', '/process?id=FOO') + self.assertEqual(http_conn.getresponse().status, 400) + http_conn.request('GET', '/processes') + self.assertEqual(http_conn.getresponse().status, 200) diff --git a/tests/utils.py b/tests/utils.py new file mode 100644 index 0000000..cd0c457 --- /dev/null +++ b/tests/utils.py @@ -0,0 +1,38 @@ +"""Shared test utilities.""" +from unittest import TestCase +from threading import Thread +from datetime import datetime +from os import remove as remove_file +from plomtask.db import DatabaseFile, DatabaseConnection +from plomtask.http import TaskHandler, TaskServer + + +class TestCaseWithDB(TestCase): + """Module tests not requiring DB setup.""" + + def setUp(self): + timestamp = datetime.now().timestamp() + self.db_file = DatabaseFile(f'test_db:{timestamp}') + self.db_file.remake() + self.db_conn = DatabaseConnection(self.db_file) + + def tearDown(self): + self.db_conn.close() + remove_file(self.db_file.path) + + +class TestCaseWithServer(TestCaseWithDB): + """Module tests against our HTTP server/handler (and database).""" + + def setUp(self): + super().setUp() + self.httpd = TaskServer(self.db_file, ('localhost', 0), TaskHandler) + self.server_thread = Thread(target=self.httpd.serve_forever) + self.server_thread.daemon = True + self.server_thread.start() + + def tearDown(self): + self.httpd.shutdown() + self.httpd.server_close() + self.server_thread.join() + super().tearDown() -- 2.30.2