1+ """
2+ Unit tests for uninstall_ray function in install_ray_or_pip_packages.py
3+ """
4+ import os
5+ import sys
6+ import subprocess
7+ import unittest
8+ from unittest .mock import patch , MagicMock
9+
10+ # Add the project root to Python path to import ray modules
11+ project_root = os .path .join (os .path .dirname (__file__ ), '..' , '..' )
12+ sys .path .insert (0 , project_root )
13+
14+ from ray ._private .runtime_env .install_ray_or_pip_packages import uninstall_ray
15+
16+
17+ class TestUninstallRay (unittest .TestCase ):
18+ """Unit test class for uninstall_ray function"""
19+
20+ def setUp (self ):
21+ """Set up test fixtures before each test method."""
22+ pass
23+
24+ def tearDown (self ):
25+ """Clean up after each test method."""
26+ pass
27+
28+ @patch ('ray._private.runtime_env.install_ray_or_pip_packages.subprocess.run' )
29+ @patch ('ray._private.runtime_env.install_ray_or_pip_packages.logger' )
30+ def test_uninstall_ray_success (self , mock_logger , mock_subprocess_run ):
31+ """Test successful uninstallation of ray packages"""
32+ # Set up mock return value
33+ mock_result = MagicMock ()
34+ mock_result .returncode = 0
35+ mock_subprocess_run .return_value = mock_result
36+
37+ # Call the function under test
38+ uninstall_ray ()
39+
40+ # Verify subprocess.run was called correctly
41+ expected_command = [sys .executable , '-m' , 'pip' , 'uninstall' , '-y' ,
42+ 'ray' , 'ant-ray' , 'ant-ray-nightly' ]
43+ mock_subprocess_run .assert_called_once_with (expected_command )
44+
45+ # Verify logger.info was called
46+ mock_logger .info .assert_called_once ()
47+ call_args = mock_logger .info .call_args [0 ][0 ]
48+ self .assertIn ("Uninstalled ray" , call_args )
49+ self .assertIn ("Return code: 0" , call_args )
50+
51+ @patch ('ray._private.runtime_env.install_ray_or_pip_packages.subprocess.run' )
52+ @patch ('ray._private.runtime_env.install_ray_or_pip_packages.logger' )
53+ def test_uninstall_ray_failure (self , mock_logger , mock_subprocess_run ):
54+ """Test uninstallation with non-zero return code"""
55+ # Set up mock return value
56+ mock_result = MagicMock ()
57+ mock_result .returncode = 1
58+ mock_subprocess_run .return_value = mock_result
59+
60+ # Call the function under test
61+ uninstall_ray ()
62+
63+ # Verify subprocess.run was called
64+ expected_command = [sys .executable , '-m' , 'pip' , 'uninstall' , '-y' ,
65+ 'ray' , 'ant-ray' , 'ant-ray-nightly' ]
66+ mock_subprocess_run .assert_called_once_with (expected_command )
67+
68+ # Verify logger.info was called even with non-zero return code
69+ mock_logger .info .assert_called_once ()
70+ call_args = mock_logger .info .call_args [0 ][0 ]
71+ self .assertIn ("Uninstalled ray" , call_args )
72+ self .assertIn ("Return code: 1" , call_args )
73+
74+ @patch ('ray._private.runtime_env.install_ray_or_pip_packages.subprocess.run' )
75+ @patch ('ray._private.runtime_env.install_ray_or_pip_packages.logger' )
76+ def test_uninstall_ray_command_structure (self , mock_logger , mock_subprocess_run ):
77+ """Test the structure of the uninstall command"""
78+ mock_result = MagicMock ()
79+ mock_result .returncode = 0
80+ mock_subprocess_run .return_value = mock_result
81+
82+ uninstall_ray ()
83+
84+ # Verify the command structure
85+ call_args = mock_subprocess_run .call_args [0 ][0 ]
86+ self .assertEqual (call_args [0 ], sys .executable )
87+ self .assertEqual (call_args [1 ], '-m' )
88+ self .assertEqual (call_args [2 ], 'pip' )
89+ self .assertEqual (call_args [3 ], 'uninstall' )
90+ self .assertEqual (call_args [4 ], '-y' )
91+
92+ # Verify all expected packages are included
93+ packages = call_args [5 :]
94+ self .assertIn ('ray' , packages )
95+ self .assertIn ('ant-ray' , packages )
96+ self .assertIn ('ant-ray-nightly' , packages )
97+ self .assertEqual (len (packages ), 3 )
98+
99+ @patch ('ray._private.runtime_env.install_ray_or_pip_packages.subprocess.run' )
100+ @patch ('ray._private.runtime_env.install_ray_or_pip_packages.logger' )
101+ def test_uninstall_ray_exception_propagation (self , mock_logger , mock_subprocess_run ):
102+ """Test that exceptions from subprocess.run are propagated"""
103+ # Mock subprocess.run to raise an exception
104+ mock_subprocess_run .side_effect = Exception ("Mocked subprocess error" )
105+
106+ # The exception should be propagated
107+ with self .assertRaises (Exception ) as context :
108+ uninstall_ray ()
109+
110+ self .assertEqual (str (context .exception ), "Mocked subprocess error" )
111+
112+
113+ if __name__ == '__main__' :
114+ unittest .main ()
0 commit comments