From e47441f0efa82eb5a59322ddd2e59a65aefe8418 Mon Sep 17 00:00:00 2001 From: mercael Date: Fri, 9 Oct 2026 01:33:27 +0300 Subject: [PATCH 1/4] Add regression tests and complete actionable assertion messages for regex checks Signed-off-by: mercael --- checks/regex/regex9.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/checks/regex/regex9.py b/checks/regex/regex9.py index 2fd54dc..67b47e2 100644 --- a/checks/regex/regex9.py +++ b/checks/regex/regex9.py @@ -3,6 +3,8 @@ assert month == "07", f"month should be '07', got {month!r}" assert day == "15", f"day should be '15', got {day!r}" m2 = re.search(pattern, "1999-12-31") -assert m2 is not None -assert m2.group("year") == "1999" and m2.group("month") == "12" and m2.group("day") == "31" +assert m2 is not None, "pattern should match '1999-12-31'" +assert m2.group("year") == "1999", f"year should be '1999', got {m2.group('year')!r}" +assert m2.group("month") == "12", f"month should be '12', got {m2.group('month')!r}" +assert m2.group("day") == "31", f"day should be '31', got {m2.group('day')!r}" print("regex9 ✓") From dea837b5ded80e859964123ecb1fd44d52961eb2 Mon Sep 17 00:00:00 2001 From: mercael Date: Fri, 9 Oct 2026 01:33:29 +0300 Subject: [PATCH 2/4] Add regression tests and complete actionable assertion messages for regex checks Signed-off-by: mercael --- checks/regex/regex10.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/checks/regex/regex10.py b/checks/regex/regex10.py index 1931875..27c365f 100644 --- a/checks/regex/regex10.py +++ b/checks/regex/regex10.py @@ -5,13 +5,13 @@ m2 = re.search(pattern, "[WARNING] app.server: disk usage at 90%") assert m2 is not None, "pattern should match a WARNING line" -assert m2.group("level") == "WARNING" -assert m2.group("logger") == "app.server" -assert m2.group("message") == "disk usage at 90%" +assert m2.group("level") == "WARNING", f"level should be 'WARNING', got {m2.group('level')!r}" +assert m2.group("logger") == "app.server", f"logger should be 'app.server', got {m2.group('logger')!r}" +assert m2.group("message") == "disk usage at 90%", f"message should be 'disk usage at 90%', got {m2.group('message')!r}" m3 = re.search(pattern, "[INFO] scheduler: job completed in 0.5s") assert m3 is not None, "pattern should match an INFO line" -assert m3.group("level") == "INFO" -assert m3.group("logger") == "scheduler" -assert m3.group("message") == "job completed in 0.5s" +assert m3.group("level") == "INFO", f"level should be 'INFO', got {m3.group('level')!r}" +assert m3.group("logger") == "scheduler", f"logger should be 'scheduler', got {m3.group('logger')!r}" +assert m3.group("message") == "job completed in 0.5s", f"message should be 'job completed in 0.5s', got {m3.group('message')!r}" print("regex10 ✓") From d018f3f327c91877235ab66765778a69783aba45 Mon Sep 17 00:00:00 2001 From: mercael Date: Fri, 9 Oct 2026 01:33:30 +0300 Subject: [PATCH 3/4] Add regression tests and complete actionable assertion messages for regex checks Signed-off-by: mercael --- tests/test_regex_assertion_messages.py | 45 ++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 tests/test_regex_assertion_messages.py diff --git a/tests/test_regex_assertion_messages.py b/tests/test_regex_assertion_messages.py new file mode 100644 index 0000000..322dfa2 --- /dev/null +++ b/tests/test_regex_assertion_messages.py @@ -0,0 +1,45 @@ +import re + + +DATE_PATTERN = r"(?P\d{4})-(?P\d{2})-(?P\d{2})" +LOG_PATTERN = r"\[(?P[A-Z]+)\] (?P[\w.]+): (?P.+)" + + +def test_regex9_assertions_include_values(): + match = re.search(DATE_PATTERN, "2024-07-15") + assert match is not None, "pattern should match '2024-07-15'" + year = match.group("year") + month = match.group("month") + day = match.group("day") + assert year == "2024", f"year should be '2024', got {year!r}" + assert month == "07", f"month should be '07', got {month!r}" + assert day == "15", f"day should be '15', got {day!r}" + + m2 = re.search(DATE_PATTERN, "1999-12-31") + assert m2 is not None, "pattern should match '1999-12-31'" + assert m2.group("year") == "1999", f"year should be '1999', got {m2.group('year')!r}" + assert m2.group("month") == "12", f"month should be '12', got {m2.group('month')!r}" + assert m2.group("day") == "31", f"day should be '31', got {m2.group('day')!r}" + + +def test_regex10_assertions_include_values(): + match = re.search(LOG_PATTERN, "[ERROR] db.engine: connection refused") + assert match is not None, "pattern should match the log line" + level = match.group("level") + logger = match.group("logger") + message = match.group("message") + assert level == "ERROR", f"level should be 'ERROR', got {level!r}" + assert logger == "db.engine", f"logger should be 'db.engine', got {logger!r}" + assert message == "connection refused", f"message should be 'connection refused', got {message!r}" + + m2 = re.search(LOG_PATTERN, "[WARNING] app.server: disk usage at 90%") + assert m2 is not None, "pattern should match a WARNING line" + assert m2.group("level") == "WARNING", f"level should be 'WARNING', got {m2.group('level')!r}" + assert m2.group("logger") == "app.server", f"logger should be 'app.server', got {m2.group('logger')!r}" + assert m2.group("message") == "disk usage at 90%", f"message should be 'disk usage at 90%', got {m2.group('message')!r}" + + m3 = re.search(LOG_PATTERN, "[INFO] scheduler: job completed in 0.5s") + assert m3 is not None, "pattern should match an INFO line" + assert m3.group("level") == "INFO", f"level should be 'INFO', got {m3.group('level')!r}" + assert m3.group("logger") == "scheduler", f"logger should be 'scheduler', got {m3.group('logger')!r}" + assert m3.group("message") == "job completed in 0.5s", f"message should be 'job completed in 0.5s', got {m3.group('message')!r}" From 178cacfc2a8b8f90e465905cf4d37567b1a49336 Mon Sep 17 00:00:00 2001 From: mercael91 Date: Fri, 9 Oct 2026 01:39:48 +0300 Subject: [PATCH 4/4] fix(curriculum): keep regex9 date predicates and wrap messages to 80 cols - regex9: the combined year/month/day assertion stays one predicate (the issue requires predicates unchanged) and now carries a message naming expected parts and actual values. - regex9/regex10: messages wrapped to the 80-column limit from CONTRIBUTING.md, same style as the other regex checks. - drop the duplicate-pattern regression test: the checks themselves are the assertions, and precedent in checks/ commits adds no tests. --- checks/regex/regex10.py | 26 +++++++++++---- checks/regex/regex9.py | 11 +++++-- tests/test_regex_assertion_messages.py | 45 -------------------------- 3 files changed, 28 insertions(+), 54 deletions(-) delete mode 100644 tests/test_regex_assertion_messages.py diff --git a/checks/regex/regex10.py b/checks/regex/regex10.py index 27c365f..1c3ae01 100644 --- a/checks/regex/regex10.py +++ b/checks/regex/regex10.py @@ -5,13 +5,27 @@ m2 = re.search(pattern, "[WARNING] app.server: disk usage at 90%") assert m2 is not None, "pattern should match a WARNING line" -assert m2.group("level") == "WARNING", f"level should be 'WARNING', got {m2.group('level')!r}" -assert m2.group("logger") == "app.server", f"logger should be 'app.server', got {m2.group('logger')!r}" -assert m2.group("message") == "disk usage at 90%", f"message should be 'disk usage at 90%', got {m2.group('message')!r}" +assert m2.group("level") == "WARNING", ( + f"m2.group('level') should be 'WARNING', got {m2.group('level')!r}" +) +assert m2.group("logger") == "app.server", ( + f"m2.group('logger') should be 'app.server', got {m2.group('logger')!r}" +) +assert m2.group("message") == "disk usage at 90%", ( + f"m2.group('message') should be 'disk usage at 90%', " + f"got {m2.group('message')!r}" +) m3 = re.search(pattern, "[INFO] scheduler: job completed in 0.5s") assert m3 is not None, "pattern should match an INFO line" -assert m3.group("level") == "INFO", f"level should be 'INFO', got {m3.group('level')!r}" -assert m3.group("logger") == "scheduler", f"logger should be 'scheduler', got {m3.group('logger')!r}" -assert m3.group("message") == "job completed in 0.5s", f"message should be 'job completed in 0.5s', got {m3.group('message')!r}" +assert m3.group("level") == "INFO", ( + f"m3.group('level') should be 'INFO', got {m3.group('level')!r}" +) +assert m3.group("logger") == "scheduler", ( + f"m3.group('logger') should be 'scheduler', got {m3.group('logger')!r}" +) +assert m3.group("message") == "job completed in 0.5s", ( + f"m3.group('message') should be 'job completed in 0.5s', " + f"got {m3.group('message')!r}" +) print("regex10 ✓") diff --git a/checks/regex/regex9.py b/checks/regex/regex9.py index 67b47e2..7903818 100644 --- a/checks/regex/regex9.py +++ b/checks/regex/regex9.py @@ -4,7 +4,12 @@ assert day == "15", f"day should be '15', got {day!r}" m2 = re.search(pattern, "1999-12-31") assert m2 is not None, "pattern should match '1999-12-31'" -assert m2.group("year") == "1999", f"year should be '1999', got {m2.group('year')!r}" -assert m2.group("month") == "12", f"month should be '12', got {m2.group('month')!r}" -assert m2.group("day") == "31", f"day should be '31', got {m2.group('day')!r}" +assert ( + m2.group("year") == "1999" + and m2.group("month") == "12" + and m2.group("day") == "31" +), ( + f"date parts should be ('1999', '12', '31'), got " + f"({m2.group('year')!r}, {m2.group('month')!r}, {m2.group('day')!r})" +) print("regex9 ✓") diff --git a/tests/test_regex_assertion_messages.py b/tests/test_regex_assertion_messages.py deleted file mode 100644 index 322dfa2..0000000 --- a/tests/test_regex_assertion_messages.py +++ /dev/null @@ -1,45 +0,0 @@ -import re - - -DATE_PATTERN = r"(?P\d{4})-(?P\d{2})-(?P\d{2})" -LOG_PATTERN = r"\[(?P[A-Z]+)\] (?P[\w.]+): (?P.+)" - - -def test_regex9_assertions_include_values(): - match = re.search(DATE_PATTERN, "2024-07-15") - assert match is not None, "pattern should match '2024-07-15'" - year = match.group("year") - month = match.group("month") - day = match.group("day") - assert year == "2024", f"year should be '2024', got {year!r}" - assert month == "07", f"month should be '07', got {month!r}" - assert day == "15", f"day should be '15', got {day!r}" - - m2 = re.search(DATE_PATTERN, "1999-12-31") - assert m2 is not None, "pattern should match '1999-12-31'" - assert m2.group("year") == "1999", f"year should be '1999', got {m2.group('year')!r}" - assert m2.group("month") == "12", f"month should be '12', got {m2.group('month')!r}" - assert m2.group("day") == "31", f"day should be '31', got {m2.group('day')!r}" - - -def test_regex10_assertions_include_values(): - match = re.search(LOG_PATTERN, "[ERROR] db.engine: connection refused") - assert match is not None, "pattern should match the log line" - level = match.group("level") - logger = match.group("logger") - message = match.group("message") - assert level == "ERROR", f"level should be 'ERROR', got {level!r}" - assert logger == "db.engine", f"logger should be 'db.engine', got {logger!r}" - assert message == "connection refused", f"message should be 'connection refused', got {message!r}" - - m2 = re.search(LOG_PATTERN, "[WARNING] app.server: disk usage at 90%") - assert m2 is not None, "pattern should match a WARNING line" - assert m2.group("level") == "WARNING", f"level should be 'WARNING', got {m2.group('level')!r}" - assert m2.group("logger") == "app.server", f"logger should be 'app.server', got {m2.group('logger')!r}" - assert m2.group("message") == "disk usage at 90%", f"message should be 'disk usage at 90%', got {m2.group('message')!r}" - - m3 = re.search(LOG_PATTERN, "[INFO] scheduler: job completed in 0.5s") - assert m3 is not None, "pattern should match an INFO line" - assert m3.group("level") == "INFO", f"level should be 'INFO', got {m3.group('level')!r}" - assert m3.group("logger") == "scheduler", f"logger should be 'scheduler', got {m3.group('logger')!r}" - assert m3.group("message") == "job completed in 0.5s", f"message should be 'job completed in 0.5s', got {m3.group('message')!r}"