From edd5c6244714a7de1a6e10d267a150ab3c3b63dd Mon Sep 17 00:00:00 2001 From: Nachtzuster Date: Sun, 9 Nov 2025 19:39:29 +0100 Subject: [PATCH] Fix test (#512) * cleanup * fix & cleanup * make testable * please add the install log --- .github/ISSUE_TEMPLATE/bug_report.md | 1 + requirements.txt | 2 +- scripts/utils/notifications.py | 8 +- tests/test_apprise_notifications.py | 285 +++++++++++++++------------ 4 files changed, 162 insertions(+), 134 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index dad3c1b..ae9a4ec 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -31,6 +31,7 @@ Add any other context about the problem or your installation here. The hardware on which BirdNET-Pi is running goes here. **Code or log snippets** +The installation creates a log in `~/`, please include it where applicable.
log or code diff --git a/requirements.txt b/requirements.txt index 55e5e17..c84bce0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -tflite_runtime-2.6.0-cp39-none-linux_aarch64.whl +tflite_runtime librosa pytz tzlocal diff --git a/scripts/utils/notifications.py b/scripts/utils/notifications.py index f7a32a1..4f425a5 100644 --- a/scripts/utils/notifications.py +++ b/scripts/utils/notifications.py @@ -146,14 +146,14 @@ def sendAppriseNotifications(species, confidence, confidencepct, path, def get_todays_count_for(db_path, sci_name): today = datetime.now().strftime("%Y-%m-%d") - select_sql = f"SELECT COUNT(*) FROM detections WHERE Date = DATE('{today}') AND Sci_name = '{sci_name}'" + select_sql = f"SELECT COUNT(*) FROM detections WHERE Date = DATE('{today}') AND Sci_Name = '{sci_name}'" records = get_records(db_path, select_sql) return records[0][0] if records else 0 def get_this_weeks_count_for(db_path, sci_name): today = datetime.now().strftime("%Y-%m-%d") - select_sql = f"SELECT COUNT(*) FROM detections WHERE Date >= DATE('{today}', '-7 day') AND Sci_name = '{sci_name}'" + select_sql = f"SELECT COUNT(*) FROM detections WHERE Date >= DATE('{today}', '-7 day') AND Sci_Name = '{sci_name}'" records = get_records(db_path, select_sql) return records[0][0] if records else 0 @@ -165,8 +165,8 @@ def get_records(db_path, select_sql): cur.execute(select_sql) records = cur.fetchall() con.close() - except sqlite3.Error: - print("Database busy") + except sqlite3.Error as e: + print(f"Database busy: {e}") timeim.sleep(2) records = [] return records diff --git a/tests/test_apprise_notifications.py b/tests/test_apprise_notifications.py index 15a81ad..d45ca4c 100644 --- a/tests/test_apprise_notifications.py +++ b/tests/test_apprise_notifications.py @@ -1,138 +1,165 @@ import os import sqlite3 -import pytest -from scripts.utils.notifications import sendAppriseNotifications from datetime import datetime +import unittest +from unittest.mock import patch + +from scripts.utils import notifications +from scripts.utils.notifications import sendAppriseNotifications -def create_test_db(db_file): - """ create a database connection to a SQLite database """ - conn = None - try: - conn = sqlite3.connect(db_file) - sql_create_detections_table = """ CREATE TABLE IF NOT EXISTS detections ( - id integer PRIMARY KEY, - Com_Name text NOT NULL, - Date date NULL, - Time time NULL - ); """ - cur = conn.cursor() - cur.execute(sql_create_detections_table) - sql = ''' INSERT INTO detections(Com_Name, Date) - VALUES(?,?) ''' +class TestAppriseNotifications(unittest.TestCase): - cur = conn.cursor() - today = datetime.now().strftime("%Y-%m-%d") # SQLite stores date as YYYY-MM-DD - cur.execute(sql, ["Great Crested Flycatcher", today]) - conn.commit() + @classmethod + def setUpClass(cls): + cls.db_file = "test.db" + cls.apprise_body_file = "test_apprise_body" + cls.apprise_config_file = "test_apprise_config" - except Exception as e: - print(e) - finally: - if conn: - conn.close() + def create_test_db(self): + """ create a database connection to a SQLite database """ + conn = None + try: + conn = sqlite3.connect(self.db_file) + sql_create_detections_table = """ CREATE TABLE IF NOT EXISTS detections ( + id integer PRIMARY KEY, + Sci_Name text NOT NULL, + Com_Name text NOT NULL, + Date date NOT NULL, + Time time NULL + ); """ + cur = conn.cursor() + cur.execute(sql_create_detections_table) + sql = ''' INSERT INTO detections(Sci_Name, Com_Name, Date) + VALUES(?,?,?) ''' + + today = datetime.now().strftime("%Y-%m-%d") # SQLite stores date as YYYY-MM-DD + cur.execute(sql, ["Myiarchus crinitus", "Great Crested Flycatcher", today]) + conn.commit() + + except Exception as e: + print(e) + finally: + if conn: + conn.close() + + def create_apprise_config(self): + with open(self.apprise_body_file, 'w') as f: + f.write('A $comname ($sciname) was just detected with a confidence of $confidencepct ($reason)') + with open(self.apprise_config_file, 'w') as f: + f.write('a dummy config') + notifications.APPRISE_BODY = self.apprise_body_file + notifications.APPRISE_CONFIG = self.apprise_config_file + + def tearDown(self): + if os.path.exists(self.db_file): + os.remove(self.db_file) + if os.path.exists(self.apprise_body_file): + os.remove(self.apprise_body_file) + if os.path.exists(self.apprise_config_file): + os.remove(self.apprise_config_file) + + @patch('scripts.utils.notifications.notify') + def test_notifications(self, mock_notify): + self.create_test_db() + self.create_apprise_config() + settings_dict = { + "APPRISE_NOTIFICATION_TITLE": "New backyard bird!", + "APPRISE_NOTIFY_EACH_DETECTION": "0", + "APPRISE_NOTIFY_NEW_SPECIES": "0", + "APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY": "0", + "APPRISE_MINIMUM_SECONDS_BETWEEN_NOTIFICATIONS_PER_SPECIES": "0" + } + sendAppriseNotifications("Myiarchus crinitus_Great Crested Flycatcher", + "0.91", + "91", + "filename", + "1666-06-06", + "06:06:06", + "06", + "-1", + "-1", + "0.7", + "1.25", + "0.0", + settings_dict, + self.db_file) + + # No active apprise notifications configured. Confirm no notifications. + self.assertEqual(mock_notify.call_count, 0) + + # Add daily notification. + mock_notify.reset_mock() + settings_dict["APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY"] = "1" + sendAppriseNotifications("Myiarchus crinitus_Great Crested Flycatcher", + "0.91", + "91", + "filename", + "1666-06-06", + "06:06:06", + "06", + "-1", + "-1", + "0.7", + "1.25", + "0.0", + settings_dict, + self.db_file) + + self.assertEqual(mock_notify.call_count, 1) + self.assertEqual( + mock_notify.call_args_list[0][0][0], + "A Great Crested Flycatcher (Myiarchus crinitus) was just detected with a confidence of 91 (first time today)" + ) + + # Add new species notification. + mock_notify.reset_mock() + settings_dict["APPRISE_NOTIFY_NEW_SPECIES"] = "1" + sendAppriseNotifications("Myiarchus crinitus_Great Crested Flycatcher", + "0.91", + "91", + "filename", + "1666-06-06", + "06:06:06", + "06", + "-1", + "-1", + "0.7", + "1.25", + "0.0", + settings_dict, + self.db_file) + + self.assertEqual(mock_notify.call_count, 2) + self.assertEqual( + mock_notify.call_args_list[0][0][0], + "A Great Crested Flycatcher (Myiarchus crinitus) was just detected with a confidence of 91 (first time today)" + ) + self.assertEqual( + mock_notify.call_args_list[1][0][0], + "A Great Crested Flycatcher (Myiarchus crinitus) was just detected with a confidence of 91 (only seen 1 times in last 7d)" + ) + + # Add each species notification. + mock_notify.reset_mock() + settings_dict["APPRISE_NOTIFY_EACH_DETECTION"] = "1" + sendAppriseNotifications("Myiarchus crinitus_Great Crested Flycatcher", + "0.91", + "91", + "filename", + "1666-06-06", + "06:06:06", + "06", + "-1", + "-1", + "0.7", + "1.25", + "0.0", + settings_dict, + self.db_file) + + self.assertEqual(mock_notify.call_count, 3) -@pytest.fixture(autouse=True) -def clean_up_after_each_test(): - yield - os.remove("test.db") - - -def test_notifications(mocker): - notify_call = mocker.patch('scripts.utils.notifications.notify') - create_test_db("test.db") - settings_dict = { - "APPRISE_NOTIFICATION_TITLE": "New backyard bird!", - "APPRISE_NOTIFICATION_BODY": "A $comname ($sciname) was just detected with a confidence of $confidence", - "APPRISE_NOTIFY_EACH_DETECTION": "0", - "APPRISE_NOTIFY_NEW_SPECIES": "0", - "APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY": "0" - } - sendAppriseNotifications("Myiarchus crinitus_Great Crested Flycatcher", - "0.91", - "91", - "filename", - "1666-06-06", - "06:06:06", - "06", - "-1", - "-1", - "0.7", - "1.25", - "0.0", - settings_dict, - "test.db") - - # No active apprise notifcations configured. Confirm no notifications. - assert (notify_call.call_count == 0) # No notification should be sent. - - # Add daily notification. - notify_call.reset_mock() - settings_dict["APPRISE_NOTIFY_NEW_SPECIES_EACH_DAY"] = "1" - sendAppriseNotifications("Myiarchus crinitus_Great Crested Flycatcher", - "0.91", - "91", - "filename", - "1666-06-06", - "06:06:06", - "06", - "-1", - "-1", - "0.7", - "1.25", - "0.0", - settings_dict, - "test.db") - - assert (notify_call.call_count == 1) - assert ( - notify_call.call_args_list[0][0][0] == "A Great Crested Flycatcher (Myiarchus crinitus) was just detected with a confidence of 91 (first time today)" - ) - - # Add new species notification. - notify_call.reset_mock() - settings_dict["APPRISE_NOTIFY_NEW_SPECIES"] = "1" - sendAppriseNotifications("Myiarchus crinitus_Great Crested Flycatcher", - "0.91", - "91", - "filename", - "1666-06-06", - "06:06:06", - "06", - "-1", - "-1", - "0.7", - "1.25", - "0.0", - settings_dict, - "test.db") - - assert (notify_call.call_count == 2) - assert ( - notify_call.call_args_list[0][0][0] == "A Great Crested Flycatcher (Myiarchus crinitus) was just detected with a confidence of 91 (first time today)" - ) - assert ( - notify_call.call_args_list[1][0][0] == "A Great Crested Flycatcher (Myiarchus crinitus) was just detected with a confidence \ - of 91 (only seen 1 times in last 7d)" - ) - - # Add each species notification. - notify_call.reset_mock() - settings_dict["APPRISE_NOTIFY_EACH_DETECTION"] = "1" - sendAppriseNotifications("Myiarchus crinitus_Great Crested Flycatcher", - "0.91", - "91", - "filename", - "1666-06-06", - "06:06:06", - "06", - "-1", - "-1", - "0.7", - "1.25", - "0.0", - settings_dict, - "test.db") - - assert (notify_call.call_count == 3) +if __name__ == '__main__': + unittest.main()