- Added coverage version 7.10.1 with multiple wheel distributions. - Added iniconfig version 2.1.0 with its wheel distribution. - Added pluggy version 1.6.0 with its wheel distribution. - Added pygments version 2.19.2 with its wheel distribution. - Added pytest version 8.4.1 with its wheel distribution and dependencies. - Added pytest-cov version 6.2.1 with its wheel distribution and dependencies. - Added pytest-mock version 3.14.1 with its wheel distribution and dependencies. - Updated dev-dependencies to include coverage, pytest, pytest-cov, and pytest-mock. - Updated requires-dist to specify minimum versions for coverage, pytest, pytest-cov, and pytest-mock.
268 lines
10 KiB
Python
268 lines
10 KiB
Python
"""
|
|
Tests for the GraphManager class.
|
|
"""
|
|
import os
|
|
import pytest
|
|
import pandas as pd
|
|
import tkinter as tk
|
|
from tkinter import ttk
|
|
from unittest.mock import Mock, patch, MagicMock
|
|
import matplotlib.pyplot as plt
|
|
|
|
import sys
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src'))
|
|
|
|
from graph_manager import GraphManager
|
|
|
|
|
|
class TestGraphManager:
|
|
"""Test cases for the GraphManager class."""
|
|
|
|
@pytest.fixture
|
|
def root_window(self):
|
|
"""Create a root window for testing."""
|
|
root = tk.Tk()
|
|
yield root
|
|
root.destroy()
|
|
|
|
@pytest.fixture
|
|
def parent_frame(self, root_window):
|
|
"""Create a parent frame for testing."""
|
|
frame = ttk.LabelFrame(root_window, text="Test Frame")
|
|
frame.pack()
|
|
return frame
|
|
|
|
def test_init(self, parent_frame):
|
|
"""Test GraphManager initialization."""
|
|
gm = GraphManager(parent_frame)
|
|
|
|
assert gm.parent_frame == parent_frame
|
|
assert isinstance(gm.toggle_vars, dict)
|
|
assert "depression" in gm.toggle_vars
|
|
assert "anxiety" in gm.toggle_vars
|
|
assert "sleep" in gm.toggle_vars
|
|
assert "appetite" in gm.toggle_vars
|
|
|
|
# Check that all toggles are initially True
|
|
for var in gm.toggle_vars.values():
|
|
assert var.get() is True
|
|
|
|
def test_toggle_controls_creation(self, parent_frame):
|
|
"""Test that toggle controls are created properly."""
|
|
gm = GraphManager(parent_frame)
|
|
|
|
# Check that control frame exists
|
|
assert hasattr(gm, 'control_frame')
|
|
assert isinstance(gm.control_frame, ttk.Frame)
|
|
|
|
# Check that toggle variables exist
|
|
expected_toggles = ["depression", "anxiety", "sleep", "appetite"]
|
|
for toggle in expected_toggles:
|
|
assert toggle in gm.toggle_vars
|
|
assert isinstance(gm.toggle_vars[toggle], tk.BooleanVar)
|
|
|
|
def test_graph_frame_creation(self, parent_frame):
|
|
"""Test that graph frame is created properly."""
|
|
gm = GraphManager(parent_frame)
|
|
|
|
assert hasattr(gm, 'graph_frame')
|
|
assert isinstance(gm.graph_frame, ttk.Frame)
|
|
|
|
@patch('matplotlib.pyplot.subplots')
|
|
def test_matplotlib_initialization(self, mock_subplots, parent_frame):
|
|
"""Test matplotlib figure and canvas initialization."""
|
|
mock_fig = Mock()
|
|
mock_ax = Mock()
|
|
mock_subplots.return_value = (mock_fig, mock_ax)
|
|
|
|
with patch('graph_manager.FigureCanvasTkAgg') as mock_canvas_class:
|
|
mock_canvas = Mock()
|
|
mock_canvas_class.return_value = mock_canvas
|
|
|
|
gm = GraphManager(parent_frame)
|
|
|
|
assert gm.fig == mock_fig
|
|
assert gm.ax == mock_ax
|
|
assert gm.canvas == mock_canvas
|
|
mock_canvas_class.assert_called_once_with(figure=mock_fig, master=gm.graph_frame)
|
|
|
|
def test_update_graph_empty_dataframe(self, parent_frame):
|
|
"""Test updating graph with empty DataFrame."""
|
|
with patch('matplotlib.pyplot.subplots') as mock_subplots:
|
|
mock_fig = Mock()
|
|
mock_ax = Mock()
|
|
mock_subplots.return_value = (mock_fig, mock_ax)
|
|
|
|
with patch('graph_manager.FigureCanvasTkAgg'):
|
|
gm = GraphManager(parent_frame)
|
|
|
|
# Test with empty DataFrame
|
|
empty_df = pd.DataFrame()
|
|
gm.update_graph(empty_df)
|
|
|
|
# Verify ax.clear() was called
|
|
mock_ax.clear.assert_called()
|
|
|
|
def test_update_graph_with_data(self, parent_frame, sample_dataframe):
|
|
"""Test updating graph with valid data."""
|
|
with patch('matplotlib.pyplot.subplots') as mock_subplots:
|
|
mock_fig = Mock()
|
|
mock_ax = Mock()
|
|
mock_subplots.return_value = (mock_fig, mock_ax)
|
|
|
|
with patch('graph_manager.FigureCanvasTkAgg') as mock_canvas_class:
|
|
mock_canvas = Mock()
|
|
mock_canvas_class.return_value = mock_canvas
|
|
|
|
gm = GraphManager(parent_frame)
|
|
gm.update_graph(sample_dataframe)
|
|
|
|
# Verify methods were called
|
|
mock_ax.clear.assert_called()
|
|
mock_canvas.draw.assert_called()
|
|
|
|
def test_toggle_functionality(self, parent_frame, sample_dataframe):
|
|
"""Test that toggle variables affect graph display."""
|
|
with patch('matplotlib.pyplot.subplots') as mock_subplots:
|
|
mock_fig = Mock()
|
|
mock_ax = Mock()
|
|
mock_subplots.return_value = (mock_fig, mock_ax)
|
|
|
|
with patch('graph_manager.FigureCanvasTkAgg') as mock_canvas_class:
|
|
mock_canvas = Mock()
|
|
mock_canvas_class.return_value = mock_canvas
|
|
|
|
gm = GraphManager(parent_frame)
|
|
|
|
# Turn off depression toggle
|
|
gm.toggle_vars["depression"].set(False)
|
|
gm.update_graph(sample_dataframe)
|
|
|
|
# The graph should still update (specific plotting logic would need more detailed testing)
|
|
mock_ax.clear.assert_called()
|
|
mock_canvas.draw.assert_called()
|
|
|
|
def test_close_method(self, parent_frame):
|
|
"""Test the close method."""
|
|
with patch('matplotlib.pyplot.subplots') as mock_subplots:
|
|
mock_fig = Mock()
|
|
mock_ax = Mock()
|
|
mock_subplots.return_value = (mock_fig, mock_ax)
|
|
|
|
with patch('graph_manager.FigureCanvasTkAgg') as mock_canvas_class:
|
|
mock_canvas = Mock()
|
|
mock_canvas_class.return_value = mock_canvas
|
|
|
|
with patch('matplotlib.pyplot.close') as mock_plt_close:
|
|
gm = GraphManager(parent_frame)
|
|
gm.close()
|
|
|
|
mock_plt_close.assert_called_once_with(mock_fig)
|
|
|
|
def test_date_parsing_in_update_graph(self, parent_frame):
|
|
"""Test that date parsing works correctly in update_graph."""
|
|
# Create a DataFrame with date strings
|
|
df_with_dates = pd.DataFrame({
|
|
'date': ['2024-01-01', '2024-01-02', '2024-01-03'],
|
|
'depression': [3, 2, 4],
|
|
'anxiety': [2, 3, 1],
|
|
'sleep': [4, 3, 5],
|
|
'appetite': [3, 4, 2],
|
|
'bupropion': [1, 1, 0],
|
|
'hydroxyzine': [0, 1, 0],
|
|
'gabapentin': [2, 2, 1],
|
|
'propranolol': [1, 0, 1],
|
|
'note': ['Test note 1', 'Test note 2', '']
|
|
})
|
|
|
|
with patch('matplotlib.pyplot.subplots') as mock_subplots:
|
|
mock_fig = Mock()
|
|
mock_ax = Mock()
|
|
mock_subplots.return_value = (mock_fig, mock_ax)
|
|
|
|
with patch('graph_manager.FigureCanvasTkAgg') as mock_canvas_class:
|
|
mock_canvas = Mock()
|
|
mock_canvas_class.return_value = mock_canvas
|
|
|
|
with patch('pandas.to_datetime') as mock_to_datetime:
|
|
gm = GraphManager(parent_frame)
|
|
gm.update_graph(df_with_dates)
|
|
|
|
# Verify pandas.to_datetime was called
|
|
mock_to_datetime.assert_called()
|
|
|
|
@patch('matplotlib.pyplot.subplots')
|
|
def test_exception_handling_in_update_graph(self, mock_subplots, parent_frame, sample_dataframe):
|
|
"""Test exception handling in update_graph method."""
|
|
mock_fig = Mock()
|
|
mock_ax = Mock()
|
|
mock_ax.plot.side_effect = Exception("Plot error")
|
|
mock_subplots.return_value = (mock_fig, mock_ax)
|
|
|
|
with patch('graph_manager.FigureCanvasTkAgg') as mock_canvas_class:
|
|
mock_canvas = Mock()
|
|
mock_canvas_class.return_value = mock_canvas
|
|
|
|
gm = GraphManager(parent_frame)
|
|
|
|
# This should not raise an exception, but handle it gracefully
|
|
try:
|
|
gm.update_graph(sample_dataframe)
|
|
except Exception as e:
|
|
pytest.fail(f"update_graph should handle exceptions gracefully, but raised: {e}")
|
|
|
|
def test_grid_configuration(self, parent_frame):
|
|
"""Test that grid configuration is set up correctly."""
|
|
gm = GraphManager(parent_frame)
|
|
|
|
# The parent frame should have grid configuration
|
|
# Note: In a real test, you might need to check grid_info() or similar
|
|
# This is a basic structure test
|
|
assert hasattr(gm, 'parent_frame')
|
|
assert hasattr(gm, 'control_frame')
|
|
assert hasattr(gm, 'graph_frame')
|
|
|
|
def test_canvas_widget_packing(self, parent_frame):
|
|
"""Test that canvas widget is properly packed."""
|
|
with patch('matplotlib.pyplot.subplots') as mock_subplots:
|
|
mock_fig = Mock()
|
|
mock_ax = Mock()
|
|
mock_subplots.return_value = (mock_fig, mock_ax)
|
|
|
|
with patch('graph_manager.FigureCanvasTkAgg') as mock_canvas_class:
|
|
mock_canvas = Mock()
|
|
mock_canvas.get_tk_widget.return_value = Mock()
|
|
mock_canvas_class.return_value = mock_canvas
|
|
|
|
gm = GraphManager(parent_frame)
|
|
|
|
# Verify get_tk_widget was called (for packing)
|
|
mock_canvas.get_tk_widget.assert_called()
|
|
|
|
def test_multiple_toggle_combinations(self, parent_frame, sample_dataframe):
|
|
"""Test various combinations of toggle states."""
|
|
with patch('matplotlib.pyplot.subplots') as mock_subplots:
|
|
mock_fig = Mock()
|
|
mock_ax = Mock()
|
|
mock_subplots.return_value = (mock_fig, mock_ax)
|
|
|
|
with patch('graph_manager.FigureCanvasTkAgg') as mock_canvas_class:
|
|
mock_canvas = Mock()
|
|
mock_canvas_class.return_value = mock_canvas
|
|
|
|
gm = GraphManager(parent_frame)
|
|
|
|
# Test all toggles off
|
|
for toggle in gm.toggle_vars.values():
|
|
toggle.set(False)
|
|
gm.update_graph(sample_dataframe)
|
|
|
|
# Test mixed toggles
|
|
gm.toggle_vars["depression"].set(True)
|
|
gm.toggle_vars["anxiety"].set(False)
|
|
gm.update_graph(sample_dataframe)
|
|
|
|
# Verify the graph was updated in each case
|
|
assert mock_ax.clear.call_count >= 2
|
|
assert mock_canvas.draw.call_count >= 2
|