Skip to content

Commit 2f7f347

Browse files
Improve test coverage to 96% for core modules
- Add test for file read error handling in kernel ID loading - Add test for resource settings with CPU conversion (100% config.py coverage) - Add test for execution timeout scenarios - Fix default directory path test for cross-environment compatibility - Comprehensive coverage: config.py (100%), jupyter_client.py (95%) - Total 23 passing tests with robust error condition coverage
1 parent 387ada3 commit 2f7f347

File tree

2 files changed

+64
-3
lines changed

2 files changed

+64
-3
lines changed

tests/test_config.py

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ def test_config_defaults():
1515
assert config.jupyter_ws_url == "ws://127.0.0.1:8888"
1616
assert config.jupyter_port == 8888
1717
assert config.jupyter_host == "127.0.0.1"
18-
assert config.shared_dir == pathlib.Path("/app/uploads")
18+
# Default shared_dir is "./uploads" for local development or "/app/uploads" in container
19+
assert config.shared_dir in [pathlib.Path("./uploads"), pathlib.Path("/app/uploads")]
1920
assert config.execution_timeout == 300.0
2021
assert config.websocket_timeout == 1.0
2122
assert config.max_wait_jupyter == 30
@@ -89,4 +90,19 @@ def test_config_bash_kernel_id_file_with_custom_path():
8990
config = Config(kernel_id_file=custom_python_path)
9091

9192
expected_bash_path = os.path.join(tmp_dir, "custom", "bash_kernel_id.txt")
92-
assert config.bash_kernel_id_file == expected_bash_path
93+
assert config.bash_kernel_id_file == expected_bash_path
94+
95+
96+
def test_config_resource_settings():
97+
"""Test resource settings configuration with CPU conversion"""
98+
env_vars = {
99+
"CODERUNNER_MAX_KERNEL_MEMORY": "2G",
100+
"CODERUNNER_MAX_KERNEL_CPU": "1.5"
101+
}
102+
103+
with patch.dict(os.environ, env_vars):
104+
config = Config()
105+
106+
assert config.max_kernel_memory == "2G"
107+
assert config.max_kernel_cpu == 1.5
108+
assert isinstance(config.max_kernel_cpu, float)

tests/test_jupyter_client.py

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,4 +332,49 @@ def test_reload_kernel_id_backward_compatibility(self, mock_config):
332332

333333
client.reload_kernel_id() # Should call reload_kernel_ids()
334334
assert client.kernel_id == "new-kernel-456"
335-
assert client.is_kernel_available("python")
335+
assert client.is_kernel_available("python")
336+
337+
def test_load_kernel_ids_file_read_error(self, mock_config):
338+
"""Test handling of file read errors during kernel ID loading"""
339+
# Create a kernel file
340+
with open(mock_config.kernel_id_file, 'w') as f:
341+
f.write("test-kernel-123")
342+
343+
# Mock file reading to raise an exception
344+
with patch('builtins.open', side_effect=PermissionError("Access denied")):
345+
client = JupyterClient()
346+
347+
# Should handle the exception gracefully
348+
assert client.kernels["python"] is None
349+
assert client.kernels["bash"] is None
350+
351+
@pytest.mark.asyncio
352+
async def test_execute_code_timeout(self, jupyter_client_with_kernel):
353+
"""Test code execution timeout"""
354+
code = "import time; time.sleep(10)"
355+
356+
# Mock WebSocket connection that never sends completion
357+
mock_websocket = AsyncMock()
358+
mock_websocket.send = AsyncMock()
359+
360+
# Mock recv to always timeout
361+
async def mock_recv():
362+
raise asyncio.TimeoutError()
363+
364+
mock_websocket.recv.side_effect = mock_recv
365+
366+
# Mock the request creation
367+
with patch.object(jupyter_client_with_kernel, '_create_execute_request') as mock_create:
368+
mock_create.return_value = ("test-msg-id", '{"test": "request"}')
369+
370+
with patch('websockets.connect') as mock_connect:
371+
mock_connect.return_value.__aenter__.return_value = mock_websocket
372+
373+
# Mock config to have short timeout
374+
with patch('jupyter_client.config') as mock_config:
375+
mock_config.execution_timeout = 0.1 # Very short timeout
376+
mock_config.websocket_timeout = 0.01
377+
mock_config.jupyter_ws_base_url = "ws://localhost:8888"
378+
379+
with pytest.raises(JupyterExecutionError, match="timed out"):
380+
await jupyter_client_with_kernel.execute_code(code)

0 commit comments

Comments
 (0)