diff options
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/test_client.py | 2 | ||||
| -rw-r--r-- | tests/test_dl.py | 115 | ||||
| -rw-r--r-- | tests/test_file_class.py | 4 | ||||
| -rw-r--r-- | tests/test_logging.py | 110 | ||||
| -rw-r--r-- | tests/test_parse.py | 10 | ||||
| -rw-r--r-- | tests/test_validations.py | 26 | ||||
| -rw-r--r-- | tests/test_wikiget_cli.py | 84 |
7 files changed, 165 insertions, 186 deletions
diff --git a/tests/test_client.py b/tests/test_client.py index 9b1b8a4..c34a842 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -25,7 +25,6 @@ from wikiget.client import connect_to_site, query_api from wikiget.wikiget import parse_args -# TODO: don't hit the actual API when doing tests class TestQueryApi: @patch("mwclient.Site.__new__") def test_connect_to_site( @@ -42,6 +41,7 @@ class TestQueryApi: assert mock_site.called assert "Connecting to commons.wikimedia.org" in caplog.text + # TODO: don't hit the actual API when doing tests @pytest.mark.skip(reason="skip tests that query a live API") def test_query_api(self, caplog: pytest.LogCaptureFixture) -> None: """ diff --git a/tests/test_dl.py b/tests/test_dl.py index a57c3c1..297c59d 100644 --- a/tests/test_dl.py +++ b/tests/test_dl.py @@ -16,7 +16,6 @@ # along with Wikiget. If not, see <https://www.gnu.org/licenses/>. from pathlib import Path -from unittest.mock import MagicMock, patch import pytest @@ -25,13 +24,11 @@ from wikiget.file import File from wikiget.wikiget import parse_args -# TODO: don't hit the actual API when doing tests class TestPrepDownload: + # TODO: don't hit the actual API when doing tests @pytest.mark.skip(reason="skip tests that query a live API") def test_prep_download(self) -> None: - """ - The prep_download function should create a file object. - """ + """The prep_download function should create a file object.""" args = parse_args(["File:Example.jpg"]) file = prep_download(args.FILE, args) assert file is not None @@ -49,60 +46,68 @@ class TestPrepDownload: class TestProcessDownload: - @patch("wikiget.dl.batch_download") - def test_batch_download(self, mock_batch_download: MagicMock) -> None: - """ - A successful batch download should not return any errors. - """ - args = parse_args(["-a", "batch.txt"]) - mock_batch_download.return_value = 0 - exit_code = process_download(args) - assert mock_batch_download.called - assert exit_code == 0 + def test_batch_download(self, monkeypatch: pytest.MonkeyPatch) -> None: + """A successful batch download should not return any errors.""" + + def mock_batch_download(*args, **kwargs): # noqa: ARG001 + return 0 + + with monkeypatch.context() as m: + m.setattr("wikiget.dl.batch_download", mock_batch_download) + + args = parse_args(["-a", "batch.txt"]) + exit_code = process_download(args) + assert exit_code == 0 - @patch("wikiget.dl.batch_download") def test_batch_download_with_errors( - self, mock_batch_download: MagicMock, caplog: pytest.LogCaptureFixture + self, monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture ) -> None: """ Any errors during batch download should create a log message containing the number of errors and result in a non-zero exit code. """ - args = parse_args(["-a", "batch.txt"]) - mock_batch_download.return_value = 4 - exit_code = process_download(args) - assert mock_batch_download.called - assert exit_code == 1 - assert "4 problems encountered during batch processing" in caplog.text - - @patch("wikiget.dl.prep_download") - @patch("wikiget.dl.download") - def test_single_download( - self, mock_download: MagicMock, mock_prep_download: MagicMock - ) -> None: - """ - A successful download should not return any errors. - """ - args = parse_args(["File:Example.jpg"]) - mock_download.return_value = 0 - mock_prep_download.return_value = MagicMock(File) - exit_code = process_download(args) - assert mock_prep_download.called - assert mock_download.called - assert exit_code == 0 - - @patch("wikiget.dl.prep_download") - @patch("wikiget.dl.download") - def test_single_download_with_errors( - self, mock_download: MagicMock, mock_prep_download: MagicMock - ) -> None: - """ - Any errors during download should result in a non-zero exit code. - """ - args = parse_args(["File:Example.jpg"]) - mock_download.return_value = 1 - mock_prep_download.return_value = MagicMock(File) - exit_code = process_download(args) - assert mock_prep_download.called - assert mock_download.called - assert exit_code == 1 + + def mock_batch_download(*args, **kwargs): # noqa: ARG001 + return 4 + + with monkeypatch.context() as m: + m.setattr("wikiget.dl.batch_download", mock_batch_download) + + args = parse_args(["-a", "batch.txt"]) + exit_code = process_download(args) + assert exit_code == 1 + assert "4 problems encountered during batch processing" in caplog.text + + def test_single_download(self, monkeypatch: pytest.MonkeyPatch) -> None: + """A successful download should not return any errors.""" + + def mock_download(*args, **kwargs): # noqa: ARG001 + return 0 + + def mock_prep_download(*args, **kwargs): # noqa ARG001 + return File("Example.jpg") + + with monkeypatch.context() as m: + m.setattr("wikiget.dl.download", mock_download) + m.setattr("wikiget.dl.prep_download", mock_prep_download) + + args = parse_args(["File:Example.jpg"]) + exit_code = process_download(args) + assert exit_code == 0 + + def test_single_download_with_errors(self, monkeypatch: pytest.MonkeyPatch) -> None: + """Any errors during download should result in a non-zero exit code.""" + + def mock_download(*args, **kwargs): # noqa: ARG001 + return 1 + + def mock_prep_download(*args, **kwargs): # noqa ARG001 + return File("Example.jpg") + + with monkeypatch.context() as m: + m.setattr("wikiget.dl.download", mock_download) + m.setattr("wikiget.dl.prep_download", mock_prep_download) + + args = parse_args(["File:Example.jpg"]) + exit_code = process_download(args) + assert exit_code == 1 diff --git a/tests/test_file_class.py b/tests/test_file_class.py index b935efc..ede4be1 100644 --- a/tests/test_file_class.py +++ b/tests/test_file_class.py @@ -22,7 +22,7 @@ from wikiget.file import File class TestFileClass: - @pytest.fixture(scope="class") + @pytest.fixture def file_with_name(self) -> File: """ A File object created with only a name should set its destination property to @@ -39,7 +39,7 @@ class TestFileClass: def test_file_with_name_site(self, file_with_name: File) -> None: assert file_with_name.site == DEFAULT_SITE - @pytest.fixture(scope="class") + @pytest.fixture def file_with_name_and_dest(self) -> File: """ A File object created with a name and destination should set those properties diff --git a/tests/test_logging.py b/tests/test_logging.py index b189c28..55a3397 100644 --- a/tests/test_logging.py +++ b/tests/test_logging.py @@ -23,67 +23,51 @@ from pytest import LogCaptureFixture from wikiget.logging import FileLogAdapter, configure_logging from wikiget.wikiget import parse_args -logger = logging.getLogger() - -def test_custom_log_adapter(caplog: LogCaptureFixture) -> None: - """ - The custom log adapter should prepend the filename to log messages. - """ - args = parse_args(["File:Example.jpg"]) - configure_logging(args.verbose, args.logfile, quiet=args.quiet) - adapter = FileLogAdapter(logger, {"filename": "Example.jpg"}) - adapter.warning("test log") - assert "[Example.jpg] test log" in caplog.text - - -def test_file_logging(tmp_path: Path) -> None: - """ - Logging to a file should create the file in the specified location. - """ - logfile_location = tmp_path / "test.log" - args = parse_args(["File:Example.jpg", "-l", str(logfile_location)]) - configure_logging(args.verbose, args.logfile, quiet=args.quiet) - assert logfile_location.is_file() - - -def test_default_logging() -> None: - """ - The default log level should be set to WARNING. - """ - args = parse_args(["File:Example.jpg"]) - configure_logging(args.verbose, args.logfile, quiet=args.quiet) - # each call of configure_logging() adds a new handler to the logger, so we need to - # grab the most recently added one to test - handler = logger.handlers[-1] - assert handler.level == logging.WARNING - - -def test_verbose_logging() -> None: - """ - When -v is passed, the log level should be set to INFO. - """ - args = parse_args(["File:Example.jpg", "-v"]) - configure_logging(args.verbose, args.logfile, quiet=args.quiet) - handler = logger.handlers[-1] - assert handler.level == logging.INFO - - -def test_very_verbose_logging() -> None: - """ - When -vv is passed, the log level should be set to DEBUG. - """ - args = parse_args(["File:Example.jpg", "-vv"]) - configure_logging(args.verbose, args.logfile, quiet=args.quiet) - handler = logger.handlers[-1] - assert handler.level == logging.DEBUG - - -def test_quiet_logging() -> None: - """ - When -q is passed, the log level should be set to ERROR. - """ - args = parse_args(["File:Example.jpg", "-q"]) - configure_logging(args.verbose, args.logfile, quiet=args.quiet) - handler = logger.handlers[-1] - assert handler.level == logging.ERROR +class TestLogging: + logger = logging.getLogger() + + def test_custom_log_adapter(self, caplog: LogCaptureFixture) -> None: + """The custom log adapter should prepend the filename to log messages.""" + args = parse_args(["File:Example.jpg"]) + configure_logging(args.verbose, args.logfile, quiet=args.quiet) + adapter = FileLogAdapter(self.logger, {"filename": "Example.jpg"}) + adapter.warning("test log") + assert "[Example.jpg] test log" in caplog.text + + def test_file_logging(self, tmp_path: Path) -> None: + """Logging to a file should create the file in the specified location.""" + logfile_location = tmp_path / "test.log" + args = parse_args(["File:Example.jpg", "-l", str(logfile_location)]) + configure_logging(args.verbose, args.logfile, quiet=args.quiet) + assert logfile_location.is_file() + + def test_default_logging(self) -> None: + """The default log level should be set to WARNING.""" + args = parse_args(["File:Example.jpg"]) + configure_logging(args.verbose, args.logfile, quiet=args.quiet) + # each call of configure_logging() adds a new handler to the logger, so we need + # to grab the most recently added one to test + handler = self.logger.handlers[-1] + assert handler.level == logging.WARNING + + def test_verbose_logging(self) -> None: + """When -v is passed, the log level should be set to INFO.""" + args = parse_args(["File:Example.jpg", "-v"]) + configure_logging(args.verbose, args.logfile, quiet=args.quiet) + handler = self.logger.handlers[-1] + assert handler.level == logging.INFO + + def test_very_verbose_logging(self) -> None: + """When -vv is passed, the log level should be set to DEBUG.""" + args = parse_args(["File:Example.jpg", "-vv"]) + configure_logging(args.verbose, args.logfile, quiet=args.quiet) + handler = self.logger.handlers[-1] + assert handler.level == logging.DEBUG + + def test_quiet_logging(self) -> None: + """When -q is passed, the log level should be set to ERROR.""" + args = parse_args(["File:Example.jpg", "-q"]) + configure_logging(args.verbose, args.logfile, quiet=args.quiet) + handler = self.logger.handlers[-1] + assert handler.level == logging.ERROR diff --git a/tests/test_parse.py b/tests/test_parse.py index e767597..e0ac707 100644 --- a/tests/test_parse.py +++ b/tests/test_parse.py @@ -29,7 +29,7 @@ from wikiget.wikiget import parse_args class TestGetDest: - @pytest.fixture(scope="class") + @pytest.fixture def file_with_filename(self) -> File: """ When a filename is passed to get_dest, it should create a File object with the @@ -47,7 +47,7 @@ class TestGetDest: def test_get_dest_site_with_filename(self, file_with_filename: File) -> None: assert file_with_filename.site == "commons.wikimedia.org" - @pytest.fixture(scope="class") + @pytest.fixture def file_with_url(self) -> File: """ When a URL is passed to get_dest, it should create a File object with the @@ -92,7 +92,7 @@ class TestGetDest: class TestReadBatchFile: - @pytest.fixture() + @pytest.fixture def dl_dict(self, tmp_path: Path) -> Dict[int, str]: """ Create and process a test batch file with three lines, returning a dictionary. @@ -129,7 +129,7 @@ class TestReadBatchFile: expected_list = {1: "File:Foo.jpg", 2: "File:Bar.jpg", 3: "File:Baz.jpg"} assert dl_dict == expected_list - @pytest.fixture() + @pytest.fixture def dl_dict_stdin(self, monkeypatch: pytest.MonkeyPatch) -> Dict[int, str]: """ Pass three lines of filenames from stdin to read_batch_file and return a dict. @@ -165,7 +165,7 @@ class TestReadBatchFile: expected_list = {1: "File:Foo.jpg", 2: "File:Bar.jpg", 3: "File:Baz.jpg"} assert dl_dict_stdin == expected_list - @pytest.fixture() + @pytest.fixture def dl_dict_with_comment(self, tmp_path: Path) -> Dict[int, str]: """ Create and process a test batch file with four lines, one of which is diff --git a/tests/test_validations.py b/tests/test_validations.py index 30e59a3..b3976b6 100644 --- a/tests/test_validations.py +++ b/tests/test_validations.py @@ -26,7 +26,6 @@ from wikiget.validations import valid_file, valid_site, verify_hash class TestSiteInput: @pytest.fixture( - scope="class", params=[ "example.com", "vim.wikia.com", @@ -38,7 +37,6 @@ class TestSiteInput: return valid_site(request.param) @pytest.fixture( - scope="class", params=[ "en.wikipedia.org", "commons.wikimedia.org", @@ -50,20 +48,16 @@ class TestSiteInput: return valid_site(request.param) def test_invalid_site_input(self, invalid_input: None) -> None: - """ - Invalid site strings should not return regex match objects. - """ + """Invalid site strings should not return regex match objects.""" assert invalid_input is None def test_valid_site_input(self, valid_input: Match) -> None: - """ - Valid site strings should return regex match objects. - """ + """Valid site strings should return regex match objects.""" assert valid_input is not None class TestFileRegex: - @pytest.fixture(scope="class") + @pytest.fixture def file_match(self) -> Optional[Match]: """ File regex should return a match object with match groups corresponding @@ -86,7 +80,6 @@ class TestFileRegex: class TestFileInput: @pytest.fixture( - scope="class", params=[ "file:example", "example.jpg", @@ -98,7 +91,6 @@ class TestFileInput: return valid_file(request.param) @pytest.fixture( - scope="class", params=[ "Image:example.jpg", "file:example.jpg", @@ -112,23 +104,17 @@ class TestFileInput: return valid_file(request.param) def test_invalid_file_input(self, invalid_input: None) -> None: - """ - Invalid file strings should not return regex match objects. - """ + """Invalid file strings should not return regex match objects.""" assert invalid_input is None def test_valid_file_input(self, valid_input: Match) -> None: - """ - Valid file strings should return regex match objects. - """ + """Valid file strings should return regex match objects.""" assert valid_input is not None class TestVerifyHash: def test_verify_hash(self, tmp_path: Path) -> None: - """ - Confirm that verify_hash returns the proper SHA1 hash. - """ + """Confirm that verify_hash returns the proper SHA1 hash.""" file_name = "testfile" file_contents = "foobar" file_sha1 = "8843d7f92416211de9ebb963ff4ce28125932878" diff --git a/tests/test_wikiget_cli.py b/tests/test_wikiget_cli.py index 99d113e..86b3780 100644 --- a/tests/test_wikiget_cli.py +++ b/tests/test_wikiget_cli.py @@ -15,55 +15,59 @@ # You should have received a copy of the GNU General Public License # along with Wikiget. If not, see <https://www.gnu.org/licenses/>. -from unittest.mock import MagicMock, patch - import pytest from wikiget import USER_AGENT, __version__ from wikiget.wikiget import cli -def test_cli_no_params(monkeypatch: pytest.MonkeyPatch): - monkeypatch.setattr("sys.argv", ["wikiget"]) - with pytest.raises(SystemExit) as e: - cli() - assert e.value.code == 2 +class TestCli: + def test_cli_no_params(self, monkeypatch: pytest.MonkeyPatch) -> None: + monkeypatch.setattr("sys.argv", ["wikiget"]) + with pytest.raises(SystemExit) as e: + cli() + assert e.value.code == 2 + + def test_cli_completed_successfully(self, monkeypatch: pytest.MonkeyPatch) -> None: + def mock_process_download(*args, **kwargs) -> int: # noqa: ARG001 + """A successful call to process_download returns 0.""" + return 0 + + with monkeypatch.context() as m: + m.setattr("sys.argv", ["wikiget", "File:Example.jpg"]) + m.setattr("wikiget.wikiget.process_download", mock_process_download) + + with pytest.raises(SystemExit) as e: + cli() + assert e.value.code == 0 + def test_cli_completed_with_problems(self, monkeypatch: pytest.MonkeyPatch) -> None: + def mock_process_download(*args, **kwargs) -> int: # noqa: ARG001 + """An unsuccessful call to process_download returns 1.""" + return 1 -@patch("wikiget.wikiget.process_download") -def test_cli_completed_successfully( - mock_process_download: MagicMock, monkeypatch: pytest.MonkeyPatch -) -> None: - monkeypatch.setattr("sys.argv", ["wikiget", "File:Example.jpg"]) - mock_process_download.return_value = 0 - with pytest.raises(SystemExit) as e: - cli() - assert mock_process_download.called - assert e.value.code == 0 + with monkeypatch.context() as m: + m.setattr("sys.argv", ["wikiget", "File:Example.jpg"]) + m.setattr("wikiget.wikiget.process_download", mock_process_download) + with pytest.raises(SystemExit) as e: + cli() + assert e.value.code == 1 -@patch("wikiget.wikiget.process_download") -def test_cli_completed_with_problems( - mock_process_download: MagicMock, monkeypatch: pytest.MonkeyPatch -) -> None: - monkeypatch.setattr("sys.argv", ["wikiget", "File:Example.jpg"]) - mock_process_download.return_value = 1 - with pytest.raises(SystemExit) as e: - cli() - assert mock_process_download.called - assert e.value.code == 1 + def test_cli_logs( + self, monkeypatch: pytest.MonkeyPatch, caplog: pytest.LogCaptureFixture + ) -> None: + def mock_process_download(*args, **kwargs) -> int: # noqa: ARG001 + """A successful call to process_download returns 0.""" + return 0 + with monkeypatch.context() as m: + m.setattr("sys.argv", ["wikiget", "File:Example.jpg"]) + m.setattr("wikiget.wikiget.process_download", mock_process_download) -@patch("wikiget.wikiget.process_download") -def test_cli_logs( - mock_process_download: MagicMock, - monkeypatch: pytest.MonkeyPatch, - caplog: pytest.LogCaptureFixture, -) -> None: - monkeypatch.setattr("sys.argv", ["wikiget", "File:Example.jpg"]) - mock_process_download.return_value = 0 - with pytest.raises(SystemExit): - cli() - assert mock_process_download.called - assert f"Starting download session using wikiget {__version__}" in caplog.text - assert USER_AGENT in caplog.text + with pytest.raises(SystemExit): + cli() + assert ( + f"Starting download session using wikiget {__version__}" in caplog.text + ) + assert USER_AGENT in caplog.text |
