Skip to content

Commit 113755c

Browse files
committed
Refactor test setup and fix Unicode issues in CLI tests:
- BaseTestCase: improved docstrings, simplified setup/teardown, pre-create logs folder, restore working directory after tests, ensure temp dir cleanup. - TestEntropyManager: disable MDAnalysis and commands loggers to prevent logging noise during tests. - TestLoggingConfig: use self.test_dir consistently instead of temp_dir.name for log file paths. - TestMain: force UTF-8 mode for subprocess (-X utf8) and capture output with UTF-8 encoding to avoid UnicodeEncodeErrors on Windows. - Inlcude `windows2025` within `project-ci.yaml` as the test cases now work on Windows
1 parent 297dd97 commit 113755c

5 files changed

Lines changed: 36 additions & 27 deletions

File tree

.github/workflows/project-ci.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
runs-on: ${{ matrix.os }}
1414
strategy:
1515
matrix:
16-
os: [ubuntu-24.04]
16+
os: [ubuntu-24.04, windows-2025]
1717
python-version: ["3.11", "3.12", "3.13"]
1818
steps:
1919
- name: Checkout repo
Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,45 @@
1-
import logging
21
import os
32
import shutil
43
import tempfile
54
import unittest
6-
import uuid
75

86

97
class BaseTestCase(unittest.TestCase):
108
"""
11-
Base class for tests with cross-platform setup and teardown.
12-
Creates unique temporary directories and pre-creates expected log files.
9+
Base test case class for cross-platform unit tests.
10+
11+
Provides:
12+
1. A unique temporary directory for each test to avoid filesystem conflicts.
13+
2. Automatic restoration of the working directory after each test.
14+
3. Prepares a logs folder path for tests that need logging configuration.
1315
"""
1416

1517
def setUp(self):
16-
# Unique temporary test directory
18+
"""
19+
Prepare the test environment before each test method runs.
20+
21+
Actions performed:
22+
1. Creates a unique temporary directory for the test.
23+
2. Creates a 'logs' subdirectory within the temp directory.
24+
3. Changes the current working directory to the temporary directory.
25+
"""
26+
# Create a unique temporary test directory
1727
self.test_dir = tempfile.mkdtemp(prefix="CodeEntropy_")
18-
self._orig_dir = os.getcwd()
19-
os.chdir(self.test_dir)
20-
21-
# Unique job folder + logs
22-
self.job_id = f"job_{uuid.uuid4().hex[:6]}"
23-
self.job_path = os.path.join(self.test_dir, self.job_id)
24-
self.logs_path = os.path.join(self.job_path, "logs")
28+
self.logs_path = os.path.join(self.test_dir, "logs")
2529
os.makedirs(self.logs_path, exist_ok=True)
2630

27-
# Pre-create log files
28-
for fname in ["mdanalysis.log", "program.log", "program.com"]:
29-
with open(os.path.join(self.logs_path, fname), "w") as f:
30-
f.write("")
31+
self._orig_dir = os.getcwd()
32+
os.chdir(self.test_dir)
3133

3234
def tearDown(self):
33-
# Shutdown logging and remove handlers (important for Windows)
34-
logging.shutdown()
35-
for handler in logging.root.handlers[:]:
36-
logging.root.removeHandler(handler)
35+
"""
36+
Clean up the test environment after each test method runs.
3737
38-
# Restore working directory
38+
Actions performed:
39+
1. Restores the original working directory.
40+
2. Deletes the temporary test directory along with all its contents.
41+
"""
3942
os.chdir(self._orig_dir)
4043

41-
# Remove temp directory (fail loudly if locked)
4244
if os.path.exists(self.test_dir):
43-
shutil.rmtree(self.test_dir, ignore_errors=False)
45+
shutil.rmtree(self.test_dir, ignore_errors=True)

tests/test_CodeEntropy/test_entropy.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import logging
12
import math
23
import os
34
import shutil
@@ -32,6 +33,10 @@ def setUp(self):
3233
super().setUp()
3334
self.test_data_dir = os.path.dirname(data.__file__)
3435

36+
# Disable MDAnalysis and commands file logging entirely
37+
logging.getLogger("MDAnalysis").handlers = [logging.NullHandler()]
38+
logging.getLogger("commands").handlers = [logging.NullHandler()]
39+
3540
def test_execute_full_workflow(self):
3641
# Setup universe and args
3742
tprfile = os.path.join(self.test_data_dir, "md_A4_dna.tpr")

tests/test_CodeEntropy/test_logging_config.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def test_update_logging_level(self):
6767
def test_mdanalysis_and_command_loggers_exist(self):
6868
"""Ensure specialized loggers are set up with correct configuration"""
6969
log_level = logging.DEBUG
70-
self.logging_config = LoggingConfig(folder=self.temp_dir.name, level=log_level)
70+
self.logging_config = LoggingConfig(folder=self.test_dir, level=log_level)
7171
self.logging_config.setup_logging()
7272

7373
mda_logger = logging.getLogger("MDAnalysis")
@@ -86,7 +86,7 @@ def test_save_console_log_writes_file(self):
8686
filename = "test_log.txt"
8787
self.logging_config.save_console_log(filename)
8888

89-
output_path = os.path.join(self.temp_dir.name, "logs", filename)
89+
output_path = os.path.join(self.test_dir, "logs", filename)
9090
# Check file exists
9191
self.assertTrue(os.path.exists(output_path))
9292

tests/test_CodeEntropy/test_main.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ def test_main_entry_point_runs(self):
102102
result = subprocess.run(
103103
[
104104
sys.executable,
105+
"-X",
106+
"utf8",
105107
"-m",
106108
"CodeEntropy.main",
107109
"--top_traj_file",
@@ -110,7 +112,7 @@ def test_main_entry_point_runs(self):
110112
],
111113
cwd=self.test_dir,
112114
capture_output=True,
113-
text=True,
115+
encoding="utf-8",
114116
)
115117

116118
self.assertEqual(result.returncode, 0)

0 commit comments

Comments
 (0)