summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoris Roovers <joris.roovers@gmail.com>2023-02-22 15:12:35 +0000
committerGitHub <noreply@github.com>2023-02-22 15:12:35 +0000
commit56f77e35b24d31352900c399c7c91aa91e6ccb42 (patch)
tree5b496c6503a234eaa6ca15274b2103ed04b2eed2
parent35ff8d7a912ff7892cf686dfef2566156356bb94 (diff)
Improve unit test coverage (#453)
Improves and fixes some existing unit tests. Adds a few new tests.
-rw-r--r--gitlint-core/gitlint/__init__.py4
-rw-r--r--gitlint-core/gitlint/git.py5
-rw-r--r--gitlint-core/gitlint/rule_finder.py1
-rw-r--r--gitlint-core/gitlint/tests/base.py8
-rw-r--r--gitlint-core/gitlint/tests/cli/test_cli.py39
-rw-r--r--gitlint-core/gitlint/tests/contrib/rules/test_authors_commit.py3
-rw-r--r--gitlint-core/gitlint/tests/expected/cli/test_cli/test_lint_multiple_commits_csv_18
-rw-r--r--gitlint-core/gitlint/tests/rules/test_configuration_rules.py6
-rw-r--r--gitlint-core/gitlint/tests/rules/test_rules.py11
-rw-r--r--gitlint-core/gitlint/tests/rules/test_user_rules.py12
-rw-r--r--gitlint-core/gitlint/tests/samples/user_rules/my_commit_rules.py2
-rw-r--r--gitlint-core/gitlint/tests/samples/user_rules/parent_package/__init__.py2
-rw-r--r--gitlint-core/gitlint/tests/test_hooks.py21
-rw-r--r--gitlint-core/gitlint/tests/test_options.py4
-rw-r--r--pyproject.toml1
15 files changed, 98 insertions, 29 deletions
diff --git a/gitlint-core/gitlint/__init__.py b/gitlint-core/gitlint/__init__.py
index d08993f..a2339fd 100644
--- a/gitlint-core/gitlint/__init__.py
+++ b/gitlint-core/gitlint/__init__.py
@@ -1,8 +1,8 @@
import sys
if sys.version_info >= (3, 8):
- from importlib import metadata
+ from importlib import metadata # pragma: nocover
else:
- import importlib_metadata as metadata
+ import importlib_metadata as metadata # pragma: nocover
__version__ = metadata.version("gitlint-core")
diff --git a/gitlint-core/gitlint/git.py b/gitlint-core/gitlint/git.py
index 405d1ab..6612a7d 100644
--- a/gitlint-core/gitlint/git.py
+++ b/gitlint-core/gitlint/git.py
@@ -171,11 +171,6 @@ class GitChangedFileStats:
def __str__(self) -> str:
return f"{self.filepath}: {self.additions} additions, {self.deletions} deletions"
- def __repr__(self) -> str:
- return (
- f'GitChangedFileStats(filepath="{self.filepath}", additions={self.additions}, deletions={self.deletions})'
- )
-
class GitCommit:
"""Class representing a git commit.
diff --git a/gitlint-core/gitlint/rule_finder.py b/gitlint-core/gitlint/rule_finder.py
index 4179c9e..810faa9 100644
--- a/gitlint-core/gitlint/rule_finder.py
+++ b/gitlint-core/gitlint/rule_finder.py
@@ -137,6 +137,7 @@ def assert_valid_rule_class(clazz, rule_type="User-defined"): # noqa: PLR0912 (
if issubclass(clazz, (rules.LineRule, rules.CommitRule)):
if not hasattr(clazz, "validate") or not inspect.isroutine(clazz.validate):
raise rules.UserRuleError(f"{rule_type} rule class '{clazz.__name__}' must have a 'validate' method")
+
# Configuration rules must have an `apply` method
elif issubclass(clazz, rules.ConfigurationRule): # noqa: SIM102
if not hasattr(clazz, "apply") or not inspect.isroutine(clazz.apply):
diff --git a/gitlint-core/gitlint/tests/base.py b/gitlint-core/gitlint/tests/base.py
index 326c7cb..3899a5f 100644
--- a/gitlint-core/gitlint/tests/base.py
+++ b/gitlint-core/gitlint/tests/base.py
@@ -171,16 +171,18 @@ class BaseTestCase(unittest.TestCase):
yield
except expected_exception as exc:
exception_msg = str(exc)
- if exception_msg != expected_msg:
+ if exception_msg != expected_msg: # pragma: nocover
error = f"Right exception, wrong message:\n got: {exception_msg}\n expected: {expected_msg}"
raise self.fail(error) from exc
# else: everything is fine, just return
return
- except Exception as exc:
+ except Exception as exc: # pragma: nocover
raise self.fail(f"Expected '{expected_exception.__name__}' got '{exc.__class__.__name__}'") from exc
# No exception raised while we expected one
- raise self.fail(f"Expected to raise {expected_exception.__name__}, didn't get an exception at all")
+ raise self.fail(
+ f"Expected to raise {expected_exception.__name__}, didn't get an exception at all"
+ ) # pragma: nocover
def object_equality_test(self, obj, attr_list, ctor_kwargs=None):
"""Helper function to easily implement object equality tests.
diff --git a/gitlint-core/gitlint/tests/cli/test_cli.py b/gitlint-core/gitlint/tests/cli/test_cli.py
index 540800d..c006375 100644
--- a/gitlint-core/gitlint/tests/cli/test_cli.py
+++ b/gitlint-core/gitlint/tests/cli/test_cli.py
@@ -101,6 +101,40 @@ class CLITests(BaseTestCase):
@patch("gitlint.cli.get_stdin_data", return_value=False)
@patch("gitlint.git.sh")
+ def test_lint_multiple_commits_csv(self, sh, _):
+ """Test for --commits option"""
+
+ # fmt: off
+ sh.git.side_effect = [
+ "6f29bf81a8322a04071bb794666e48c443a90360\n", # git rev-list <SHA>
+ "25053ccec5e28e1bb8f7551fdbb5ab213ada2401\n",
+ "4da2656b0dadc76c7ee3fd0243a96cb64007f125\n",
+ # git log --pretty <FORMAT> <SHA>
+ "test åuthor1\x00test-email1@föo.com\x002016-12-03 15:28:15 +0100\x00åbc\n"
+ "commït-title1\n\ncommït-body1",
+ "#", # git config --get core.commentchar
+ "3\t5\tcommit-1/file-1\n1\t4\tcommit-1/file-2\n", # git diff-tree
+ "commit-1-branch-1\ncommit-1-branch-2\n", # git branch --contains <sha>
+ # git log --pretty <FORMAT> <SHA>
+ "test åuthor2\x00test-email3@föo.com\x002016-12-04 15:28:15 +0100\x00åbc\n"
+ "commït-title2\n\ncommït-body2",
+ "8\t3\tcommit-2/file-1\n1\t5\tcommit-2/file-2\n", # git diff-tree
+ "commit-2-branch-1\ncommit-2-branch-2\n", # git branch --contains <sha>
+ # git log --pretty <FORMAT> <SHA>
+ "test åuthor3\x00test-email3@föo.com\x002016-12-05 15:28:15 +0100\x00åbc\n"
+ "commït-title3\n\ncommït-body3",
+ "7\t2\tcommit-3/file-1\n1\t7\tcommit-3/file-2\n", # git diff-tree
+ "commit-3-branch-1\ncommit-3-branch-2\n", # git branch --contains <sha>
+ ]
+ # fmt: on
+
+ with patch("gitlint.display.stderr", new=StringIO()) as stderr:
+ result = self.cli.invoke(cli.cli, ["--commits", "6f29bf81,25053cce,4da2656b"])
+ self.assertEqual(stderr.getvalue(), self.get_expected("cli/test_cli/test_lint_multiple_commits_csv_1"))
+ self.assertEqual(result.exit_code, 3)
+
+ @patch("gitlint.cli.get_stdin_data", return_value=False)
+ @patch("gitlint.git.sh")
def test_lint_multiple_commits_config(self, sh, _):
"""Test for --commits option where some of the commits have gitlint config in the commit message"""
@@ -600,6 +634,11 @@ class CLITests(BaseTestCase):
result = self.cli.invoke(cli.cli, env={"GITLINT_CONFIG": config_path})
self.assertEqual(result.exit_code, self.CONFIG_ERROR_CODE)
+ def test_config_error(self):
+ result = self.cli.invoke(cli.cli, ["-c", "foo.bar=hur"])
+ self.assertEqual(result.output, "Config Error: No such rule 'foo'\n")
+ self.assertEqual(result.exit_code, self.CONFIG_ERROR_CODE)
+
@patch("gitlint.cli.get_stdin_data", return_value=False)
def test_target(self, _):
"""Test for the --target option"""
diff --git a/gitlint-core/gitlint/tests/contrib/rules/test_authors_commit.py b/gitlint-core/gitlint/tests/contrib/rules/test_authors_commit.py
index 5cc3355..2bad2ed 100644
--- a/gitlint-core/gitlint/tests/contrib/rules/test_authors_commit.py
+++ b/gitlint-core/gitlint/tests/contrib/rules/test_authors_commit.py
@@ -101,6 +101,5 @@ class ContribAuthorsCommitTests(BaseTestCase):
return_value=False,
)
def test_read_authors_file_missing_file(self, _mock_iterdir):
- with self.assertRaises(FileNotFoundError) as err:
+ with self.assertRaisesMessage(FileNotFoundError, "No AUTHORS file found!"):
AllowedAuthors._read_authors_from_file(self.gitcontext)
- self.assertEqual(err.exception.args[0], "AUTHORS file not found")
diff --git a/gitlint-core/gitlint/tests/expected/cli/test_cli/test_lint_multiple_commits_csv_1 b/gitlint-core/gitlint/tests/expected/cli/test_cli/test_lint_multiple_commits_csv_1
new file mode 100644
index 0000000..be3288b
--- /dev/null
+++ b/gitlint-core/gitlint/tests/expected/cli/test_cli/test_lint_multiple_commits_csv_1
@@ -0,0 +1,8 @@
+Commit 6f29bf81a8:
+3: B5 Body message is too short (12<20): "commït-body1"
+
+Commit 25053ccec5:
+3: B5 Body message is too short (12<20): "commït-body2"
+
+Commit 4da2656b0d:
+3: B5 Body message is too short (12<20): "commït-body3"
diff --git a/gitlint-core/gitlint/tests/rules/test_configuration_rules.py b/gitlint-core/gitlint/tests/rules/test_configuration_rules.py
index d5b70a9..5935a4a 100644
--- a/gitlint-core/gitlint/tests/rules/test_configuration_rules.py
+++ b/gitlint-core/gitlint/tests/rules/test_configuration_rules.py
@@ -105,6 +105,12 @@ class ConfigurationRuleTests(BaseTestCase):
]
self.assert_logged(expected_log_messages)
+ # Non-Matching regex -> expect config to stay the same
+ rule = rules.IgnoreByAuthorName({"regex": "foo"})
+ expected_config = LintConfig()
+ rule.apply(config, commit)
+ self.assertEqual(config, LintConfig())
+
# Matching regex -> expect config to ignore all rules
rule = rules.IgnoreByAuthorName({"regex": "(.*)ëst(.*)"})
expected_config = LintConfig()
diff --git a/gitlint-core/gitlint/tests/rules/test_rules.py b/gitlint-core/gitlint/tests/rules/test_rules.py
index e24d91a..b401372 100644
--- a/gitlint-core/gitlint/tests/rules/test_rules.py
+++ b/gitlint-core/gitlint/tests/rules/test_rules.py
@@ -3,6 +3,10 @@ from gitlint.tests.base import BaseTestCase
class RuleTests(BaseTestCase):
+ def test_ruleviolation__str__(self):
+ expected = '57: rule-ïd Tēst message: "Tēst content"'
+ self.assertEqual(str(RuleViolation("rule-ïd", "Tēst message", "Tēst content", 57)), expected)
+
def test_rule_equality(self):
self.assertEqual(Rule(), Rule())
# Ensure rules are not equal if they differ on their attributes
@@ -13,9 +17,16 @@ class RuleTests(BaseTestCase):
def test_rule_log(self):
rule = Rule()
+ self.assertIsNone(rule._log)
rule.log.debug("Tēst message")
self.assert_log_contains("DEBUG: gitlint.rules Tēst message")
+ # Assert the same logger is reused when logging multiple messages
+ log = rule._log
+ rule.log.debug("Anöther message")
+ self.assertEqual(log, rule._log)
+ self.assert_log_contains("DEBUG: gitlint.rules Anöther message")
+
def test_rule_violation_equality(self):
violation1 = RuleViolation("ïd1", "My messåge", "My cöntent", 1)
self.object_equality_test(violation1, ["rule_id", "message", "content", "line_nr"])
diff --git a/gitlint-core/gitlint/tests/rules/test_user_rules.py b/gitlint-core/gitlint/tests/rules/test_user_rules.py
index c2309a6..8086bea 100644
--- a/gitlint-core/gitlint/tests/rules/test_user_rules.py
+++ b/gitlint-core/gitlint/tests/rules/test_user_rules.py
@@ -103,21 +103,21 @@ class UserRuleTests(BaseTestCase):
target = rules.CommitMessageTitle
def validate(self):
- pass
+ pass # pragma: nocover
class MyCommitRuleClass(rules.CommitRule):
id = "UC2"
name = "my-cömmit-rule"
def validate(self):
- pass
+ pass # pragma: nocover
class MyConfigurationRuleClass(rules.ConfigurationRule):
id = "UC3"
name = "my-cönfiguration-rule"
def apply(self):
- pass
+ pass # pragma: nocover
# Just assert that no error is raised
self.assertIsNone(assert_valid_rule_class(MyLineRuleClass))
@@ -235,8 +235,8 @@ class UserRuleTests(BaseTestCase):
with self.assertRaisesMessage(UserRuleError, expected_msg):
assert_valid_rule_class(MyRuleClass)
- # validate attribute - not a method
- MyRuleClass.validate = "föo"
+ # apply attribute - not a method
+ MyRuleClass.apply = "föo"
with self.assertRaisesMessage(UserRuleError, expected_msg):
assert_valid_rule_class(MyRuleClass)
@@ -246,7 +246,7 @@ class UserRuleTests(BaseTestCase):
name = "my-rüle-class"
def validate(self):
- pass
+ pass # pragma: nocover
# no target
expected_msg = (
diff --git a/gitlint-core/gitlint/tests/samples/user_rules/my_commit_rules.py b/gitlint-core/gitlint/tests/samples/user_rules/my_commit_rules.py
index 6291e80..c947250 100644
--- a/gitlint-core/gitlint/tests/samples/user_rules/my_commit_rules.py
+++ b/gitlint-core/gitlint/tests/samples/user_rules/my_commit_rules.py
@@ -19,7 +19,7 @@ class MyUserCommitRule(CommitRule):
def func_should_be_ignored():
- pass
+ pass # pragma: nocover
global_variable_should_be_ignored = True
diff --git a/gitlint-core/gitlint/tests/samples/user_rules/parent_package/__init__.py b/gitlint-core/gitlint/tests/samples/user_rules/parent_package/__init__.py
index 22c3f65..c2863fe 100644
--- a/gitlint-core/gitlint/tests/samples/user_rules/parent_package/__init__.py
+++ b/gitlint-core/gitlint/tests/samples/user_rules/parent_package/__init__.py
@@ -9,4 +9,4 @@ class InitFileRule(CommitRule):
options_spec = []
def validate(self, _commit):
- return []
+ return [] # pragma: nocover
diff --git a/gitlint-core/gitlint/tests/test_hooks.py b/gitlint-core/gitlint/tests/test_hooks.py
index 8007009..7390f14 100644
--- a/gitlint-core/gitlint/tests/test_hooks.py
+++ b/gitlint-core/gitlint/tests/test_hooks.py
@@ -57,9 +57,10 @@ class HookTests(BaseTestCase):
expected_msg = f"{lint_config.target} is not a git repository."
with self.assertRaisesMessage(GitHookInstallerError, expected_msg):
GitHookInstaller.install_commit_msg_hook(lint_config)
- isdir.assert_called_with(git_hooks_dir.return_value)
- path_exists.assert_not_called()
- copy.assert_not_called()
+
+ isdir.assert_called_with(git_hooks_dir.return_value)
+ path_exists.assert_not_called()
+ copy.assert_not_called()
# mock that there is already a commit hook present
isdir.return_value = True
@@ -105,9 +106,10 @@ class HookTests(BaseTestCase):
expected_msg = f"{lint_config.target} is not a git repository."
with self.assertRaisesMessage(GitHookInstallerError, expected_msg):
GitHookInstaller.uninstall_commit_msg_hook(lint_config)
- isdir.assert_called_with(git_hooks_dir.return_value)
- path_exists.assert_not_called()
- remove.assert_not_called()
+
+ isdir.assert_called_with(git_hooks_dir.return_value)
+ path_exists.assert_not_called()
+ remove.assert_not_called()
# mock that there is no commit hook present
isdir.return_value = True
@@ -116,9 +118,10 @@ class HookTests(BaseTestCase):
expected_msg = f"There is no commit-msg hook present in {expected_dst}."
with self.assertRaisesMessage(GitHookInstallerError, expected_msg):
GitHookInstaller.uninstall_commit_msg_hook(lint_config)
- isdir.assert_called_with(git_hooks_dir.return_value)
- path_exists.assert_called_once_with(expected_dst)
- remove.assert_not_called()
+
+ isdir.assert_called_with(git_hooks_dir.return_value)
+ path_exists.assert_called_once_with(expected_dst)
+ remove.assert_not_called()
# mock that there is a different (=not gitlint) commit hook
isdir.return_value = True
diff --git a/gitlint-core/gitlint/tests/test_options.py b/gitlint-core/gitlint/tests/test_options.py
index 9b84945..deff723 100644
--- a/gitlint-core/gitlint/tests/test_options.py
+++ b/gitlint-core/gitlint/tests/test_options.py
@@ -14,6 +14,10 @@ from gitlint.tests.base import BaseTestCase
class RuleOptionTests(BaseTestCase):
+ def test_option__str__(self):
+ option = StrOption("tëst-option", "åbc", "Test Dëscription")
+ self.assertEqual(str(option), "(tëst-option: åbc (Test Dëscription))")
+
def test_option_equality(self):
options = {
IntOption: 123,
diff --git a/pyproject.toml b/pyproject.toml
index cfc6c50..98b60f5 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -199,3 +199,4 @@ branch = true # measure branch coverage in addition to statement coverage
[tool.coverage.report]
fail_under = 97
+show_missing = true