From 77d34f3280339ae7e5fe455a7a46ff70319906a3 Mon Sep 17 00:00:00 2001 From: Lisa Chung <943046+lisac@users.noreply.github.com> Date: Mon, 14 Apr 2025 17:51:32 -0400 Subject: [PATCH 01/10] add test_get_addr_info() copied implementations foudn in other navapbc repos --- .../tests/src/logging/test_audit.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/template/{{app_name}}/tests/src/logging/test_audit.py b/template/{{app_name}}/tests/src/logging/test_audit.py index d7788c66..2d3137b3 100644 --- a/template/{{app_name}}/tests/src/logging/test_audit.py +++ b/template/{{app_name}}/tests/src/logging/test_audit.py @@ -146,6 +146,25 @@ def test_audit_hook( assert_record_match(record, expected_record) +def test_get_addr_info(init_audit_hook, caplog: pytest.LogCaptureFixture): + socket.getaddrinfo("www.python.org", 80) + print(caplog.records) + + expected_record = { + "msg": "socket.getaddrinfo", + "audit.args.host": "www.python.org", + "audit.args.port": 80, + } + + message_found = False + for record in caplog.records: + if record.msg == "socket.getaddrinfo": + message_found = True + assert_record_match(record, expected_record) + + assert message_found is True + + def test_os_kill(init_audit_hook, caplog: pytest.LogCaptureFixture): # Start a process to kill process = subprocess.Popen("cat") From aff37b071e333af17a767dbbe4b8fc1dd86f608a Mon Sep 17 00:00:00 2001 From: Lisa Chung <943046+lisac@users.noreply.github.com> Date: Mon, 14 Apr 2025 17:52:28 -0400 Subject: [PATCH 02/10] add test_datetime_str_to_date() and test_utcnow() copied implementations found in other navapbc repos --- .../tests/src/util/test_datetime_util.py | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/template/{{app_name}}/tests/src/util/test_datetime_util.py b/template/{{app_name}}/tests/src/util/test_datetime_util.py index d6bf02d9..e38ee0d5 100644 --- a/template/{{app_name}}/tests/src/util/test_datetime_util.py +++ b/template/{{app_name}}/tests/src/util/test_datetime_util.py @@ -1,9 +1,9 @@ -from datetime import datetime, timezone +from datetime import date, datetime, timezone import pytest import pytz -from src.util.datetime_util import adjust_timezone +from src.util.datetime_util import adjust_timezone, datetime_str_to_date, utcnow @pytest.mark.parametrize( @@ -50,3 +50,21 @@ def test_adjust_timezone_from_non_utc(timezone_name, expected_output): # in a few places that don't observe DST (the US timezones are all 1 hour closer to UTC) assert adjust_timezone(input_datetime, timezone_name).isoformat() == expected_output + + +@pytest.mark.parametrize( + "datetime_str, expected_output", + [ + ("2022-05-31T23:00:00-06:00", date(2022, 5, 31)), + ("2022-06-01T14:00:00+09:00", date(2022, 6, 1)), + ("", None), + (None, None), + ], +) +def test_datetime_str_to_date(datetime_str, expected_output): + assert datetime_str_to_date(datetime_str) == expected_output + + +def test_utcnow(): + assert utcnow().tzinfo == timezone.utc + assert utcnow().date() == datetime.now().date() From 1b3243af0ade49b361ce1cea6ddbbcf62bfc7ec4 Mon Sep 17 00:00:00 2001 From: Lisa Chung <943046+lisac@users.noreply.github.com> Date: Mon, 14 Apr 2025 17:53:47 -0400 Subject: [PATCH 03/10] add tests for file_util.py copied implementations found in other navapbc repos --- .../tests/src/util/test_file_util.py | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 template/{{app_name}}/tests/src/util/test_file_util.py diff --git a/template/{{app_name}}/tests/src/util/test_file_util.py b/template/{{app_name}}/tests/src/util/test_file_util.py new file mode 100644 index 00000000..26369fc5 --- /dev/null +++ b/template/{{app_name}}/tests/src/util/test_file_util.py @@ -0,0 +1,83 @@ +import os + +import pytest +from smart_open import open as smart_open + +import src.util.file_util as file_util + + +def create_file(root_path, file_path): + full_path = os.path.join(root_path, file_path) + + if not file_util.is_s3_path(str(full_path)): + os.makedirs(os.path.dirname(full_path), exist_ok=True) + + with smart_open(full_path, mode="w") as outfile: + outfile.write("hello") + + return full_path + + +@pytest.mark.parametrize( + "path,is_s3", + [ + ("s3://bucket/folder/test.txt", True), + ("./relative/folder/test.txt", False), + ("http://example.com/test.txt", False), + ], +) +def test_is_s3_path(path, is_s3): + assert file_util.is_s3_path(path) is is_s3 + + +@pytest.mark.parametrize( + "path,bucket,prefix", + [ + ("s3://my_bucket/my_key", "my_bucket", "my_key"), + ("s3://my_bucket/path/to/directory/", "my_bucket", "path/to/directory/"), + ("s3://my_bucket/path/to/file.txt", "my_bucket", "path/to/file.txt"), + ], +) +def test_split_s3_url(path, bucket, prefix): + assert file_util.split_s3_url(path) == (bucket, prefix) + + +@pytest.mark.parametrize( + "path,bucket", + [ + ("s3://bucket/folder/test.txt", "bucket"), + ("s3://bucket_x/folder", "bucket_x"), + ("s3://bucket-y/folder/", "bucket-y"), + ("s3://bucketz", "bucketz"), + ], +) +def test_get_s3_bucket(path, bucket): + assert file_util.get_s3_bucket(path) == bucket + + +@pytest.mark.parametrize( + "path,file_key", + [ + ("s3://bucket/folder/test.txt", "folder/test.txt"), + ("s3://bucket_x/file.csv", "file.csv"), + ("s3://bucket-y/folder/path/to/abc.zip", "folder/path/to/abc.zip"), + ("./folder/path", "/folder/path"), + ("sftp://folder/filename", "filename"), + ], +) +def test_get_s3_file_key(path, file_key): + assert file_util.get_s3_file_key(path) == file_key + + +@pytest.mark.parametrize( + "path,file_name", + [ + ("s3://bucket/folder/test.txt", "test.txt"), + ("s3://bucket_x/file.csv", "file.csv"), + ("s3://bucket-y/folder/path/to/abc.zip", "abc.zip"), + ("./folder/path", "path"), + ("sftp://filename", "filename"), + ], +) +def test_get_s3_file_name(path, file_name): + assert file_util.get_file_name(path) == file_name From d046d979be09433000b7dcb96354a076f7df05c8 Mon Sep 17 00:00:00 2001 From: Lisa Chung <943046+lisac@users.noreply.github.com> Date: Mon, 14 Apr 2025 17:54:44 -0400 Subject: [PATCH 04/10] add test for string_utils.py copied implementations found in other navapbc repos --- .../tests/src/util/test_string_utils.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 template/{{app_name}}/tests/src/util/test_string_utils.py diff --git a/template/{{app_name}}/tests/src/util/test_string_utils.py b/template/{{app_name}}/tests/src/util/test_string_utils.py new file mode 100644 index 00000000..4c8ea527 --- /dev/null +++ b/template/{{app_name}}/tests/src/util/test_string_utils.py @@ -0,0 +1,14 @@ +from src.util.string_utils import join_list + + +def test_join_list(): + assert join_list(None) == "" + assert join_list(None, ",") == "" + assert join_list(None, "|") == "" + assert join_list([]) == "" + assert join_list([], ",") == "" + assert join_list([], "|") == "" + + assert join_list(["a", "b", "c"]) == "a\nb\nc" + assert join_list(["a", "b", "c"], ",") == "a,b,c" + assert join_list(["a", "b", "c"], "|") == "a|b|c" \ No newline at end of file From 39c3ec0baccabeb02ff5ef03e07577111c0b4456 Mon Sep 17 00:00:00 2001 From: Lisa Chung <943046+lisac@users.noreply.github.com> Date: Mon, 14 Apr 2025 17:57:51 -0400 Subject: [PATCH 05/10] add test for app_config.py --- template/{{app_name}}/tests/src/test_app_config.py | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 template/{{app_name}}/tests/src/test_app_config.py diff --git a/template/{{app_name}}/tests/src/test_app_config.py b/template/{{app_name}}/tests/src/test_app_config.py new file mode 100644 index 00000000..cbeb87ed --- /dev/null +++ b/template/{{app_name}}/tests/src/test_app_config.py @@ -0,0 +1,11 @@ +import os +from unittest import mock + +from src.app_config import AppConfig + + +@mock.patch.dict(os.environ, {"host": '192.123.123.123', "port": '5190'}) +def test_app_config_sets_values_from_environment(): + app_config = AppConfig() + assert app_config.host == '192.123.123.123' + assert app_config.port == 5190 From a7c4c24882256fc584854b73d122696dc5d3c99e Mon Sep 17 00:00:00 2001 From: Lisa Chung <943046+lisac@users.noreply.github.com> Date: Mon, 14 Apr 2025 18:00:48 -0400 Subject: [PATCH 06/10] fix format --- template/{{app_name}}/tests/src/logging/test_audit.py | 2 +- template/{{app_name}}/tests/src/test_app_config.py | 8 ++++---- .../{{app_name}}/tests/src/util/test_datetime_util.py | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/template/{{app_name}}/tests/src/logging/test_audit.py b/template/{{app_name}}/tests/src/logging/test_audit.py index 2d3137b3..3515188b 100644 --- a/template/{{app_name}}/tests/src/logging/test_audit.py +++ b/template/{{app_name}}/tests/src/logging/test_audit.py @@ -290,4 +290,4 @@ def test_least_recently_used_dict(): def assert_record_match(record: logging.LogRecord, expected_record: dict[str, Any]): for key, value in expected_record.items(): - assert record.__dict__[key] == value + assert record.__dict__[key] == value \ No newline at end of file diff --git a/template/{{app_name}}/tests/src/test_app_config.py b/template/{{app_name}}/tests/src/test_app_config.py index cbeb87ed..2cf6a97b 100644 --- a/template/{{app_name}}/tests/src/test_app_config.py +++ b/template/{{app_name}}/tests/src/test_app_config.py @@ -4,8 +4,8 @@ from src.app_config import AppConfig -@mock.patch.dict(os.environ, {"host": '192.123.123.123', "port": '5190'}) +@mock.patch.dict(os.environ, {"host": "192.123.123.123", "port": "5190"}) def test_app_config_sets_values_from_environment(): - app_config = AppConfig() - assert app_config.host == '192.123.123.123' - assert app_config.port == 5190 + app_config = AppConfig() + assert app_config.host == "192.123.123.123" + assert app_config.port == 5190 \ No newline at end of file diff --git a/template/{{app_name}}/tests/src/util/test_datetime_util.py b/template/{{app_name}}/tests/src/util/test_datetime_util.py index e38ee0d5..ff61a89f 100644 --- a/template/{{app_name}}/tests/src/util/test_datetime_util.py +++ b/template/{{app_name}}/tests/src/util/test_datetime_util.py @@ -67,4 +67,4 @@ def test_datetime_str_to_date(datetime_str, expected_output): def test_utcnow(): assert utcnow().tzinfo == timezone.utc - assert utcnow().date() == datetime.now().date() + assert utcnow().date() == datetime.now().date() \ No newline at end of file From 933f8de2f517583593691c6a0e1dcfa478c53fe6 Mon Sep 17 00:00:00 2001 From: Lisa Chung <943046+lisac@users.noreply.github.com> Date: Mon, 14 Apr 2025 18:10:01 -0400 Subject: [PATCH 07/10] add newline to mark end of file --- template/{{app_name}}/tests/src/logging/test_audit.py | 2 +- template/{{app_name}}/tests/src/test_app_config.py | 2 +- template/{{app_name}}/tests/src/util/test_datetime_util.py | 2 +- template/{{app_name}}/tests/src/util/test_string_utils.py | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/template/{{app_name}}/tests/src/logging/test_audit.py b/template/{{app_name}}/tests/src/logging/test_audit.py index 3515188b..2d3137b3 100644 --- a/template/{{app_name}}/tests/src/logging/test_audit.py +++ b/template/{{app_name}}/tests/src/logging/test_audit.py @@ -290,4 +290,4 @@ def test_least_recently_used_dict(): def assert_record_match(record: logging.LogRecord, expected_record: dict[str, Any]): for key, value in expected_record.items(): - assert record.__dict__[key] == value \ No newline at end of file + assert record.__dict__[key] == value diff --git a/template/{{app_name}}/tests/src/test_app_config.py b/template/{{app_name}}/tests/src/test_app_config.py index 2cf6a97b..784026d9 100644 --- a/template/{{app_name}}/tests/src/test_app_config.py +++ b/template/{{app_name}}/tests/src/test_app_config.py @@ -8,4 +8,4 @@ def test_app_config_sets_values_from_environment(): app_config = AppConfig() assert app_config.host == "192.123.123.123" - assert app_config.port == 5190 \ No newline at end of file + assert app_config.port == 5190 diff --git a/template/{{app_name}}/tests/src/util/test_datetime_util.py b/template/{{app_name}}/tests/src/util/test_datetime_util.py index ff61a89f..e38ee0d5 100644 --- a/template/{{app_name}}/tests/src/util/test_datetime_util.py +++ b/template/{{app_name}}/tests/src/util/test_datetime_util.py @@ -67,4 +67,4 @@ def test_datetime_str_to_date(datetime_str, expected_output): def test_utcnow(): assert utcnow().tzinfo == timezone.utc - assert utcnow().date() == datetime.now().date() \ No newline at end of file + assert utcnow().date() == datetime.now().date() diff --git a/template/{{app_name}}/tests/src/util/test_string_utils.py b/template/{{app_name}}/tests/src/util/test_string_utils.py index 4c8ea527..3ef3f170 100644 --- a/template/{{app_name}}/tests/src/util/test_string_utils.py +++ b/template/{{app_name}}/tests/src/util/test_string_utils.py @@ -11,4 +11,4 @@ def test_join_list(): assert join_list(["a", "b", "c"]) == "a\nb\nc" assert join_list(["a", "b", "c"], ",") == "a,b,c" - assert join_list(["a", "b", "c"], "|") == "a|b|c" \ No newline at end of file + assert join_list(["a", "b", "c"], "|") == "a|b|c" From d73aa337d972747520e95ca131cd9902d72a5aa3 Mon Sep 17 00:00:00 2001 From: Lisa Chung Date: Tue, 15 Apr 2025 16:07:32 -0400 Subject: [PATCH 08/10] remove unneeded print() Co-authored-by: Michael Chouinard <46358556+chouinar@users.noreply.github.com> --- template/{{app_name}}/tests/src/logging/test_audit.py | 1 - 1 file changed, 1 deletion(-) diff --git a/template/{{app_name}}/tests/src/logging/test_audit.py b/template/{{app_name}}/tests/src/logging/test_audit.py index 2d3137b3..5b59cea7 100644 --- a/template/{{app_name}}/tests/src/logging/test_audit.py +++ b/template/{{app_name}}/tests/src/logging/test_audit.py @@ -148,7 +148,6 @@ def test_audit_hook( def test_get_addr_info(init_audit_hook, caplog: pytest.LogCaptureFixture): socket.getaddrinfo("www.python.org", 80) - print(caplog.records) expected_record = { "msg": "socket.getaddrinfo", From c460a257d07111988571b8582944a63ead9ba6ef Mon Sep 17 00:00:00 2001 From: Lisa Chung <943046+lisac@users.noreply.github.com> Date: Wed, 16 Apr 2025 15:55:33 -0400 Subject: [PATCH 09/10] remove redundant test already covered by a case in test_audit_hook() --- .../tests/src/logging/test_audit.py | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/template/{{app_name}}/tests/src/logging/test_audit.py b/template/{{app_name}}/tests/src/logging/test_audit.py index 5b59cea7..d7788c66 100644 --- a/template/{{app_name}}/tests/src/logging/test_audit.py +++ b/template/{{app_name}}/tests/src/logging/test_audit.py @@ -146,24 +146,6 @@ def test_audit_hook( assert_record_match(record, expected_record) -def test_get_addr_info(init_audit_hook, caplog: pytest.LogCaptureFixture): - socket.getaddrinfo("www.python.org", 80) - - expected_record = { - "msg": "socket.getaddrinfo", - "audit.args.host": "www.python.org", - "audit.args.port": 80, - } - - message_found = False - for record in caplog.records: - if record.msg == "socket.getaddrinfo": - message_found = True - assert_record_match(record, expected_record) - - assert message_found is True - - def test_os_kill(init_audit_hook, caplog: pytest.LogCaptureFixture): # Start a process to kill process = subprocess.Popen("cat") From 41d694af5f880cf7ed3ad1ba5500e0cfaaa75935 Mon Sep 17 00:00:00 2001 From: Lisa Chung <943046+lisac@users.noreply.github.com> Date: Wed, 16 Apr 2025 15:56:26 -0400 Subject: [PATCH 10/10] remove a test for behavior that we inherit from pydantic --- template/{{app_name}}/tests/src/test_app_config.py | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100644 template/{{app_name}}/tests/src/test_app_config.py diff --git a/template/{{app_name}}/tests/src/test_app_config.py b/template/{{app_name}}/tests/src/test_app_config.py deleted file mode 100644 index 784026d9..00000000 --- a/template/{{app_name}}/tests/src/test_app_config.py +++ /dev/null @@ -1,11 +0,0 @@ -import os -from unittest import mock - -from src.app_config import AppConfig - - -@mock.patch.dict(os.environ, {"host": "192.123.123.123", "port": "5190"}) -def test_app_config_sets_values_from_environment(): - app_config = AppConfig() - assert app_config.host == "192.123.123.123" - assert app_config.port == 5190