/ tests / unit / test_dependencies.py
test_dependencies.py
  1  """
  2  Unit tests for dependencies.py functions.
  3  """
  4  
  5  import os
  6  from unittest.mock import patch
  7  
  8  import pytest
  9  import yaml
 10  
 11  import dependencies
 12  
 13  
 14  @pytest.mark.unit
 15  def test_get_venv_path():
 16      """Test get_venv_path returns correct path format."""
 17      env_name = "abc123def456"
 18      expected = os.path.join(dependencies.VENVS_ROOT_PATH, env_name, "bin", "python")
 19      result = dependencies.get_venv_path(env_name)
 20      assert result == expected
 21  
 22  
 23  @pytest.mark.unit
 24  def test_get_venv_path_with_hash():
 25      """Test get_venv_path with realistic hash value."""
 26      env_hash = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
 27      result = dependencies.get_venv_path(env_hash)
 28      assert env_hash in result
 29      assert result.endswith("bin/python")
 30  
 31  
 32  @pytest.mark.unit
 33  @patch('dependencies.config')
 34  @patch('builtins.open')
 35  def test_get_venvs_definitions_empty_rulesets(mock_open, mock_config):
 36      """Test get_venvs_definitions with no rulesets configured."""
 37      mock_config.rulesets = []
 38      mock_config.enabled_rules = []
 39  
 40      virtualenvs, enabled_rules_def = dependencies.get_venvs_definitions()
 41  
 42      assert virtualenvs == {}
 43      assert enabled_rules_def == {}
 44  
 45  
 46  @pytest.mark.unit
 47  @patch('dependencies.config')
 48  def test_get_venvs_definitions_with_ruleset(mock_config, tmp_path):
 49      """Test get_venvs_definitions with a valid ruleset file."""
 50      # Create temporary ruleset file
 51      ruleset_data = {
 52          "name": "test-ruleset",
 53          "version": "1.0.0",
 54          "rules": [
 55              {
 56                  "id": "D-SCHEMA-03",
 57                  "type": "deterministic",
 58                  "enabled": True,
 59                  "requirements": ["pyyaml>=6.0"],
 60              },
 61              {
 62                  "id": "P-QUALITY-01",
 63                  "type": "probabilistic",
 64                  "enabled": True,
 65                  "requirements": ["pyyaml>=6.0", "numpy>=1.20"],
 66              },
 67          ],
 68      }
 69  
 70      ruleset_file = tmp_path / "test-ruleset.yml"
 71      with open(ruleset_file, 'w') as f:
 72          yaml.dump(ruleset_data, f)
 73  
 74      # Patch config and file path
 75      mock_config.rulesets = ["test-ruleset.yml"]
 76      mock_config.enabled_rules = []
 77  
 78      # Patch the file opening to use our temp file
 79      _original_dirname = dependencies.os.path.dirname
 80      with patch('dependencies.os.path.dirname', return_value=str(tmp_path.parent)):
 81          with patch('dependencies.os.path.join', side_effect=lambda *args: str(ruleset_file) if "rulesets" in args else os.path.join(*args)):
 82              virtualenvs, enabled_rules_def = dependencies.get_venvs_definitions()
 83  
 84      # Should have 2 different venv hashes (different requirements)
 85      assert len(virtualenvs) == 2
 86      assert len(enabled_rules_def) == 2
 87      assert "D-SCHEMA-03" in enabled_rules_def
 88      assert "P-QUALITY-01" in enabled_rules_def
 89  
 90  
 91  @pytest.mark.unit
 92  @patch('subprocess.run')
 93  def test_generate_venvs_creates_new_env(mock_subprocess):
 94      """Test generate_venvs creates new virtualenv and installs dependencies."""
 95      definitions = {
 96          "abc123": ["pyyaml>=6.0", "numpy>=1.20"],
 97      }
 98  
 99      with patch('os.path.exists', return_value=False):
100          dependencies.generate_venvs(definitions)
101  
102      # Should have called subprocess twice: virtualenv creation + pip install
103      assert mock_subprocess.call_count >= 2
104  
105      # Check virtualenv creation call
106      create_call = mock_subprocess.call_args_list[0]
107      assert "virtualenv" in create_call[0][0]
108  
109      # Check pip install call
110      install_call = mock_subprocess.call_args_list[1]
111      assert "pip" in install_call[0][0][0]
112      assert "install" in install_call[0][0]
113  
114  
115  @pytest.mark.unit
116  @patch('subprocess.run')
117  def test_generate_venvs_updates_existing_env(mock_subprocess):
118      """Test generate_venvs updates dependencies for existing venv."""
119      definitions = {
120          "abc123": ["pyyaml>=6.0"],
121      }
122  
123      with patch('os.path.exists', return_value=True):
124          dependencies.generate_venvs(definitions)
125  
126      # Should only call pip install (venv already exists)
127      assert mock_subprocess.call_count >= 1
128      install_call = mock_subprocess.call_args_list[0]
129      assert "pip" in install_call[0][0][0]
130      assert "install" in install_call[0][0]
131  
132  
133  @pytest.mark.unit
134  def test_venvs_root_path_exists():
135      """Test VENVS_ROOT_PATH is a valid path structure."""
136      assert isinstance(dependencies.VENVS_ROOT_PATH, str)
137      assert "venvs" in dependencies.VENVS_ROOT_PATH