From 172fe1c41ed6130150f9747e22f2e08b50143570 Mon Sep 17 00:00:00 2001 From: Zack Koppert Date: Tue, 7 Apr 2026 10:04:15 -0700 Subject: [PATCH 1/3] test: achieve 100% test coverage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add 6 tests covering previously uncovered paths in env.py: - get_int_env_var returning None for non-integer values - get_env_vars loading .env file when test=False - REPOSITORY validation for values starting with / - TITLE exceeding 70 character limit - BODY exceeding 65536 character limit - COMMIT_MESSAGE exceeding 65536 character limit Coverage: 96% → 100% (204 statements, 0 missed) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Zack Koppert --- test_env.py | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 1 deletion(-) diff --git a/test_env.py b/test_env.py index 8068fcc..3120f63 100644 --- a/test_env.py +++ b/test_env.py @@ -4,7 +4,7 @@ import unittest from unittest.mock import patch -from env import get_env_vars +from env import get_env_vars, get_int_env_var BODY = "Consider these updates to the CODEOWNERS file to remove users no longer in this organization." COMMIT_MESSAGE = "Remove users no longer in this organization from CODEOWNERS file" @@ -298,6 +298,81 @@ def test_get_env_vars_with_repos_no_dry_run(self): result = get_env_vars(True) self.assertEqual(result, expected_result) + def test_get_int_env_var_returns_none_for_non_integer(self): + """Test that get_int_env_var returns None when the value is not an integer.""" + with patch.dict(os.environ, {"TEST_VAR": "not_a_number"}): + result = get_int_env_var("TEST_VAR") + self.assertIsNone(result) + + @patch.dict( + os.environ, + { + "GH_TOKEN": TOKEN, + "ORGANIZATION": ORGANIZATION, + }, + clear=True, + ) + def test_get_env_vars_loads_dotenv_when_not_test(self): + """Test that get_env_vars loads from .env file when test=False.""" + # When test=False, it should attempt to load .env (no error even if missing) + result = get_env_vars(False) + self.assertEqual(result[0], ORGANIZATION) + + @patch.dict( + os.environ, + { + "GH_TOKEN": TOKEN, + "REPOSITORY": "/invalid-repo", + }, + clear=True, + ) + def test_get_env_vars_raises_for_repository_starting_with_slash(self): + """Test that REPOSITORY starting with / raises ValueError.""" + with self.assertRaises(ValueError): + get_env_vars(True) + + @patch.dict( + os.environ, + { + "GH_TOKEN": TOKEN, + "ORGANIZATION": ORGANIZATION, + "TITLE": "x" * 71, + }, + clear=True, + ) + def test_get_env_vars_raises_for_title_too_long(self): + """Test that TITLE longer than 70 characters raises ValueError.""" + with self.assertRaises(ValueError): + get_env_vars(True) + + @patch.dict( + os.environ, + { + "GH_TOKEN": TOKEN, + "ORGANIZATION": ORGANIZATION, + "BODY": "x" * 65537, + }, + clear=True, + ) + def test_get_env_vars_raises_for_body_too_long(self): + """Test that BODY longer than 65536 characters raises ValueError.""" + with self.assertRaises(ValueError): + get_env_vars(True) + + @patch.dict( + os.environ, + { + "GH_TOKEN": TOKEN, + "ORGANIZATION": ORGANIZATION, + "COMMIT_MESSAGE": "x" * 65537, + }, + clear=True, + ) + def test_get_env_vars_raises_for_commit_message_too_long(self): + """Test that COMMIT_MESSAGE longer than 65536 characters raises ValueError.""" + with self.assertRaises(ValueError): + get_env_vars(True) + if __name__ == "__main__": unittest.main() From 72842ad995376fd131ccb6d8993d271b034b1f2f Mon Sep 17 00:00:00 2001 From: Zack Koppert Date: Tue, 7 Apr 2026 15:05:04 -0700 Subject: [PATCH 2/3] test: assert load_dotenv is called in dotenv coverage test The test was covering lines 90-91 for coverage metrics but not asserting that load_dotenv() was actually invoked. Mock load_dotenv and verify it is called once when test=False. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Zack Koppert --- test_env.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test_env.py b/test_env.py index 3120f63..e31b6b0 100644 --- a/test_env.py +++ b/test_env.py @@ -304,6 +304,7 @@ def test_get_int_env_var_returns_none_for_non_integer(self): result = get_int_env_var("TEST_VAR") self.assertIsNone(result) + @patch("env.load_dotenv") @patch.dict( os.environ, { @@ -312,11 +313,11 @@ def test_get_int_env_var_returns_none_for_non_integer(self): }, clear=True, ) - def test_get_env_vars_loads_dotenv_when_not_test(self): + def test_get_env_vars_loads_dotenv_when_not_test(self, mock_load_dotenv): """Test that get_env_vars loads from .env file when test=False.""" - # When test=False, it should attempt to load .env (no error even if missing) result = get_env_vars(False) self.assertEqual(result[0], ORGANIZATION) + mock_load_dotenv.assert_called_once() @patch.dict( os.environ, From 54da56dbe7b4e6c2ae633230f6f1b1b55b2b5e3c Mon Sep 17 00:00:00 2001 From: Zack Koppert Date: Tue, 7 Apr 2026 21:39:20 -0700 Subject: [PATCH 3/3] test: require 100% test coverage in Makefile Bump --cov-fail-under from 80 to 100 now that all code paths are covered, per review feedback on PR #383. Signed-off-by: Zack Koppert Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Zack Koppert --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9244677..23e9bde 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ .PHONY: test test: - uv run python -m pytest -v --cov=. --cov-config=.coveragerc --cov-fail-under=80 --cov-report term-missing + uv run python -m pytest -v --cov=. --cov-config=.coveragerc --cov-fail-under=100 --cov-report term-missing .PHONY: clean clean: