Skip to content

Commit 58c3260

Browse files
rudy-07orsenthil
authored andcommitted
gh-131178: Add tests for ftplib command-line interface (GH-161080)
* gh-131178: Add tests for ftplib command-line interface Add unit tests in Lib/test/test_ftplib.py covering the ftplib command-line interface: verifying usage message on empty invocation, subprocess invocation, host connection with debuglevel, directory and passive mode commands, file retrieval, and custom netrc file error handling. (cherry picked from commit c29f95a) Co-authored-by: Rudransh Shekhar <kanhaiffco2007@gmail.com> Co-authored-by: Senthil Kumaran <senthil@python.org>
1 parent 1f66a03 commit 58c3260

1 file changed

Lines changed: 68 additions & 0 deletions

File tree

‎Lib/test/test_ftplib.py‎

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,6 +1188,74 @@ def test__all__(self):
11881188
support.check__all__(self, ftplib, not_exported=not_exported)
11891189

11901190

1191+
class CommandLineTest(TestCase):
1192+
"""Tests for the ftplib command-line interface."""
1193+
1194+
def test_main_no_arguments_prints_usage(self):
1195+
with mock.patch('sys.argv', ['ftplib']), \
1196+
support.captured_stdout() as stdout:
1197+
with self.assertRaises(SystemExit) as cm:
1198+
ftplib.test()
1199+
self.assertEqual(cm.exception.code, 0)
1200+
output = stdout.getvalue()
1201+
self.assertIn('Usage:', output)
1202+
self.assertIn('Options:', output)
1203+
self.assertIn('Commands:', output)
1204+
1205+
@requires_subprocess()
1206+
def test_subprocess_invocation_no_args(self):
1207+
from test.support.script_helper import assert_python_ok
1208+
rc, out, err = assert_python_ok('-m', 'ftplib')
1209+
self.assertEqual(rc, 0)
1210+
self.assertIn(b'Usage:', out)
1211+
self.assertIn(b'Options:', out)
1212+
self.assertIn(b'Commands:', out)
1213+
self.assertEqual(err, b'')
1214+
1215+
@mock.patch('ftplib.FTP')
1216+
@mock.patch('netrc.netrc', side_effect=OSError)
1217+
def test_cli_host_and_debugging(self, mock_netrc, mock_ftp_cls):
1218+
mock_ftp = mock_ftp_cls.return_value
1219+
with mock.patch('sys.argv', ['ftplib', '-d', '-d', 'example.com']):
1220+
ftplib.test()
1221+
mock_ftp_cls.assert_called_once_with('example.com')
1222+
mock_ftp.set_debuglevel.assert_called_once_with(2)
1223+
mock_ftp.login.assert_called_once_with('', '', '')
1224+
mock_ftp.quit.assert_called_once()
1225+
1226+
@mock.patch('ftplib.FTP')
1227+
@mock.patch('netrc.netrc', side_effect=OSError)
1228+
def test_cli_commands(self, mock_netrc, mock_ftp_cls):
1229+
mock_ftp = mock_ftp_cls.return_value
1230+
with mock.patch('sys.argv', ['ftplib', 'example.com', '-l/pub', '-d/incoming', '-p']):
1231+
ftplib.test()
1232+
mock_ftp_cls.assert_called_once_with('example.com')
1233+
mock_ftp.dir.assert_called_once_with('/pub')
1234+
mock_ftp.sendcmd.assert_called_once_with('CWD /incoming')
1235+
mock_ftp.set_pasv.assert_called_once()
1236+
mock_ftp.quit.assert_called_once()
1237+
1238+
@mock.patch('ftplib.FTP')
1239+
@mock.patch('netrc.netrc', side_effect=OSError)
1240+
def test_cli_retrieve_file(self, mock_netrc, mock_ftp_cls):
1241+
mock_ftp = mock_ftp_cls.return_value
1242+
with mock.patch('sys.argv', ['ftplib', 'example.com', 'testfile.txt']):
1243+
ftplib.test()
1244+
mock_ftp.retrbinary.assert_called_once()
1245+
args, kwargs = mock_ftp.retrbinary.call_args
1246+
self.assertEqual(args[0], 'RETR testfile.txt')
1247+
mock_ftp.quit.assert_called_once()
1248+
1249+
@mock.patch('ftplib.FTP')
1250+
@mock.patch('netrc.netrc', side_effect=OSError('file not found'))
1251+
def test_cli_custom_rcfile_error(self, mock_netrc, mock_ftp_cls):
1252+
with mock.patch('sys.argv', ['ftplib', '-rnonexistent.netrc', 'example.com']), \
1253+
support.captured_stderr() as stderr:
1254+
ftplib.test()
1255+
self.assertIn("Could not open account file -- using anonymous login.",
1256+
stderr.getvalue())
1257+
1258+
11911259
def setUpModule():
11921260
thread_info = threading_helper.threading_setup()
11931261
unittest.addModuleCleanup(threading_helper.threading_cleanup, *thread_info)

0 commit comments

Comments
 (0)