Skip to content

Commit d74b9aa

Browse files
committed
Basic Unittests; GitHub Actions workflow
1 parent 96ad80c commit d74b9aa

File tree

4 files changed

+129
-0
lines changed

4 files changed

+129
-0
lines changed

.github/workflows/test.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
name: Python Multi-OS Tests
2+
3+
on:
4+
push:
5+
branches: [ "main" ]
6+
pull_request:
7+
branches: [ "main" ]
8+
9+
jobs:
10+
build-and-test:
11+
runs-on: ${{ matrix.os }} # Matrix strategy picks OS
12+
strategy:
13+
matrix:
14+
os: [ubuntu-latest, windows-latest, macos-latest]
15+
python-version: [ "2.7", "3.12", "3.13" ]
16+
steps:
17+
- name: Check out the repository
18+
uses: actions/checkout@v3
19+
20+
- name: Set up Python
21+
uses: actions/setup-python@v4
22+
with:
23+
python-version: ${{ matrix.python-version }}
24+
25+
- name: Run Tests
26+
run: |
27+
python -m unittest discover -s tests

tests/test_cli_monitor_basic.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import unittest
2+
import subprocess
3+
4+
class TestCliMonitorBasic(unittest.TestCase):
5+
"""Tests the most basic functionality of cli_monitor.py."""
6+
7+
def test_echo_command(self):
8+
"""Verify 'echo Hello' runs without errors and prints 'Hello'."""
9+
cmd = [
10+
"python", "cli_monitor.py",
11+
"--command", "echo Hello",
12+
"--timer", "2" # short run
13+
]
14+
result = subprocess.run(cmd, capture_output=True, text=True)
15+
self.assertEqual(result.returncode, 0)
16+
self.assertIn("Hello", result.stdout)
17+
18+
def test_invalid_frequency(self):
19+
"""Frequency outside allowed range should cause an error exit."""
20+
cmd = [
21+
"python", "cli_monitor.py",
22+
"--command", "echo Hello",
23+
"--frequency", "999999999" # way too large
24+
]
25+
result = subprocess.run(cmd, capture_output=True, text=True)
26+
# Expecting a non-zero exit code due to frequency validation
27+
self.assertNotEqual(result.returncode, 0)
28+
self.assertIn("Error: Frequency must be between", result.stdout)
29+
30+
if __name__ == "__main__":
31+
unittest.main()

tests/test_cli_monitor_logging.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import unittest
2+
import subprocess
3+
import os
4+
5+
class TestCliMonitorLogging(unittest.TestCase):
6+
"""Tests output-file logging and log pruning."""
7+
8+
def setUp(self):
9+
self.log_file = "test_log_output.txt"
10+
# Remove log file if it exists
11+
if os.path.exists(self.log_file):
12+
os.remove(self.log_file)
13+
14+
def tearDown(self):
15+
# Clean up log file
16+
if os.path.exists(self.log_file):
17+
os.remove(self.log_file)
18+
19+
def test_log_pruning(self):
20+
"""Check that log file pruning occurs once it exceeds max size."""
21+
cmd = [
22+
"python", "cli_monitor.py",
23+
"--command", "echo TestLogLine",
24+
"--output-file", self.log_file,
25+
"--max-log-size", "1", # 1KB to force quick pruning
26+
"--timer", "3" # run a few iterations
27+
]
28+
result = subprocess.run(cmd, capture_output=True, text=True)
29+
self.assertEqual(result.returncode, 0)
30+
# We expect the log file to exist, but be under or ~1KB
31+
self.assertTrue(os.path.exists(self.log_file))
32+
file_size = os.path.getsize(self.log_file)
33+
self.assertLessEqual(file_size, 1024, "Log file should be pruned to <= 1KB")
34+
35+
if __name__ == "__main__":
36+
unittest.main()

tests/test_cli_monitor_regex.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import unittest
2+
import subprocess
3+
4+
class TestCliMonitorRegex(unittest.TestCase):
5+
"""Tests regex matching and triggered command execution."""
6+
7+
def test_regex_trigger(self):
8+
"""Should detect 'ERROR' and run the triggered command."""
9+
cmd = [
10+
"python", "cli_monitor.py",
11+
"--command", "echo ERROR OCCURRED",
12+
"--regex", "ERROR",
13+
"--regex-execute", "echo 'Trigger ran!'",
14+
"--timer", "2"
15+
]
16+
result = subprocess.run(cmd, capture_output=True, text=True)
17+
self.assertEqual(result.returncode, 0)
18+
self.assertIn("ERROR OCCURRED", result.stdout) # Main command output
19+
self.assertIn("Trigger ran!", result.stdout) # Triggered command output
20+
21+
def test_no_regex_no_trigger(self):
22+
"""No triggered command should run if no regex is provided."""
23+
cmd = [
24+
"python", "cli_monitor.py",
25+
"--command", "echo Hello Again",
26+
"--timer", "2"
27+
]
28+
result = subprocess.run(cmd, capture_output=True, text=True)
29+
self.assertEqual(result.returncode, 0)
30+
self.assertIn("Hello Again", result.stdout)
31+
# Ensure we DON'T see "Trigger ran!"
32+
self.assertNotIn("Trigger ran!", result.stdout)
33+
34+
if __name__ == "__main__":
35+
unittest.main()

0 commit comments

Comments
 (0)