Skip to content

Commit c29f95a

Browse files
rudy-07orsenthil
andauthored
gh-131178: Add tests for ftplib command-line interface (#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. Co-authored-by: Senthil Kumaran <senthil@python.org>
1 parent 2f20512 commit c29f95a

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
@@ -1191,6 +1191,74 @@ def test__all__(self):
11911191
support.check__all__(self, ftplib, not_exported=not_exported)
11921192

11931193

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

0 commit comments

Comments
 (0)