shared fixtures for all tests

This commit is contained in:
Jesse Bannon 2023-03-07 22:22:42 -08:00
parent 6c745236d4
commit e7b91e107e
4 changed files with 113 additions and 87 deletions

View file

@ -2,6 +2,7 @@ import contextlib
import json import json
import logging import logging
import os import os
import shutil
import tempfile import tempfile
from pathlib import Path from pathlib import Path
from typing import Any from typing import Any
@ -11,10 +12,14 @@ from typing import List
from unittest.mock import patch from unittest.mock import patch
import pytest import pytest
from expected_download import _get_files_in_directory
from ytdl_sub.config.config_file import ConfigFile
from ytdl_sub.subscriptions.subscription_download import SubscriptionDownload
from ytdl_sub.utils.file_handler import FileHandler from ytdl_sub.utils.file_handler import FileHandler
from ytdl_sub.utils.logger import Logger from ytdl_sub.utils.logger import Logger
from ytdl_sub.utils.logger import LoggerLevels from ytdl_sub.utils.logger import LoggerLevels
from ytdl_sub.utils.yaml import load_yaml
@pytest.fixture(autouse=True) @pytest.fixture(autouse=True)
@ -28,9 +33,31 @@ def cleanup_debug_file():
@pytest.fixture @pytest.fixture
def working_directory() -> Path: def working_directory() -> str:
"""
Any time the working directory is used, ensure no files remain on cleaning it up
"""
logger = Logger.get("test")
with tempfile.TemporaryDirectory() as temp_dir: with tempfile.TemporaryDirectory() as temp_dir:
yield temp_dir
def _assert_working_directory_empty(self, is_error: bool = False):
files = [str(file_path) for file_path in _get_files_in_directory(temp_dir)]
num_files = len(files)
if os.path.isdir(temp_dir):
shutil.rmtree(temp_dir)
if not is_error:
if num_files > 0:
logger.error("left-over files in working dir:\n%s", "\n".join(files))
assert num_files == 0
with patch.object(
SubscriptionDownload,
"_delete_working_directory",
new=_assert_working_directory_empty,
):
yield temp_dir
@pytest.fixture() @pytest.fixture()
@ -106,3 +133,38 @@ def preset_dict_to_subscription_yaml_generator() -> Callable:
FileHandler.delete(tmp_file.name) FileHandler.delete(tmp_file.name)
return _preset_dict_to_subscription_yaml_generator return _preset_dict_to_subscription_yaml_generator
###################################################################################################
# Example config fixtures
def _load_config(config_path: Path, working_directory: Path) -> ConfigFile:
config_dict = load_yaml(file_path=config_path)
config_dict["configuration"]["working_directory"] = working_directory
return ConfigFile.from_dict(config_dict)
@pytest.fixture()
def music_video_config_path() -> Path:
return Path("examples/music_videos_config.yaml")
@pytest.fixture()
def music_video_config(music_video_config_path, working_directory) -> ConfigFile:
return _load_config(music_video_config_path, working_directory)
@pytest.fixture()
def channel_as_tv_show_config(working_directory) -> ConfigFile:
return _load_config(
config_path=Path("examples/tv_show_config.yaml"), working_directory=working_directory
)
@pytest.fixture()
def music_audio_config(working_directory) -> ConfigFile:
return _load_config(
config_path=Path("examples/music_audio_config.yaml"), working_directory=working_directory
)

View file

@ -1,69 +1,16 @@
import json import json
import os
import shutil
import sys import sys
import tempfile import tempfile
from pathlib import Path
from typing import List from typing import List
from typing import Tuple from typing import Tuple
from unittest.mock import patch from unittest.mock import patch
import pytest import pytest
from expected_download import _get_files_in_directory
from ytdl_sub.cli.main import main from ytdl_sub.cli.main import main
from ytdl_sub.config.config_file import ConfigFile
from ytdl_sub.subscriptions.subscription import Subscription from ytdl_sub.subscriptions.subscription import Subscription
from ytdl_sub.subscriptions.subscription_download import SubscriptionDownload
from ytdl_sub.utils.file_handler import FileHandler from ytdl_sub.utils.file_handler import FileHandler
from ytdl_sub.utils.file_handler import FileHandlerTransactionLog from ytdl_sub.utils.file_handler import FileHandlerTransactionLog
from ytdl_sub.utils.logger import Logger
from ytdl_sub.utils.yaml import load_yaml
logger = Logger.get("test")
@pytest.fixture
def working_directory() -> str:
"""
Any time the working directory is used, ensure no files remain on cleaning it up
"""
with tempfile.TemporaryDirectory() as temp_dir:
def _assert_working_directory_empty(self, is_error: bool = False):
files = [str(file_path) for file_path in _get_files_in_directory(temp_dir)]
num_files = len(files)
if os.path.isdir(temp_dir):
shutil.rmtree(temp_dir)
if not is_error:
if num_files > 0:
logger.error("left-over files in working dir:\n%s", "\n".join(files))
assert num_files == 0
with patch.object(
SubscriptionDownload,
"_delete_working_directory",
new=_assert_working_directory_empty,
):
yield temp_dir
@pytest.fixture()
def music_video_config_path() -> Path:
return Path("examples/music_videos_config.yaml")
def _load_config(config_path: Path, working_directory: Path) -> ConfigFile:
config_dict = load_yaml(file_path=config_path)
config_dict["configuration"]["working_directory"] = working_directory
return ConfigFile.from_dict(config_dict)
@pytest.fixture()
def music_video_config(music_video_config_path, working_directory) -> ConfigFile:
return _load_config(music_video_config_path, working_directory)
@pytest.fixture() @pytest.fixture()
@ -77,20 +24,6 @@ def music_video_config_for_cli(music_video_config) -> str:
FileHandler.delete(tmp_file.name) FileHandler.delete(tmp_file.name)
@pytest.fixture()
def channel_as_tv_show_config(working_directory) -> ConfigFile:
return _load_config(
config_path=Path("examples/tv_show_config.yaml"), working_directory=working_directory
)
@pytest.fixture()
def music_audio_config(working_directory) -> ConfigFile:
return _load_config(
config_path=Path("examples/music_audio_config.yaml"), working_directory=working_directory
)
@pytest.fixture @pytest.fixture
def timestamps_file_path(): def timestamps_file_path():
timestamps = [ timestamps = [

View file

@ -1,6 +1,9 @@
import sys import sys
import tempfile
from unittest.mock import patch from unittest.mock import patch
import pytest
from ytdl_sub.cli.main import main from ytdl_sub.cli.main import main
@ -16,3 +19,30 @@ def test_args_after_sub_work():
assert mock_sub.call_args.kwargs["args"].config == "examples/tv_show_config.yaml" assert mock_sub.call_args.kwargs["args"].config == "examples/tv_show_config.yaml"
assert mock_sub.call_args.kwargs["args"].subscription_paths == ["subscriptions.yaml"] assert mock_sub.call_args.kwargs["args"].subscription_paths == ["subscriptions.yaml"]
assert mock_sub.call_args.kwargs["args"].ytdl_sub_log_level == "debug" assert mock_sub.call_args.kwargs["args"].ytdl_sub_log_level == "debug"
@pytest.fixture
def persist_logs_directory():
with tempfile.TemporaryDirectory() as temp_dir:
yield temp_dir
@pytest.fixture
def persist_logs_config():
pass
class TestPersistLogs:
@pytest.mark.parametrize("mock_success_output", [True, False])
@pytest.mark.parametrize("keep_successful_logs", [True, False])
def test_subscription_logs_write_to_file(
self, persist_logs_directory: str, mock_success_output: bool, keep_successful_logs: bool
):
config_dict = {
"working_directory": ".",
"persist_logs": {
"logs_directory": persist_logs_directory,
"keep_successful_logs": keep_successful_logs,
},
}

View file

@ -56,6 +56,7 @@ def mock_entry_dict_factory(mock_downloaded_file_path) -> Callable:
playlist_index: int = 1, playlist_index: int = 1,
playlist_count: int = 1, playlist_count: int = 1,
is_youtube_channel: bool = False, is_youtube_channel: bool = False,
mock_download_to_working_dir: bool = True,
) -> Dict: ) -> Dict:
entry_dict = { entry_dict = {
UID: uid, UID: uid,
@ -84,12 +85,14 @@ def mock_entry_dict_factory(mock_downloaded_file_path) -> Callable:
] ]
# Create mock video file # Create mock video file
copy_file_fixture( if mock_download_to_working_dir:
fixture_name="sample_vid.mp4", output_file_path=mock_downloaded_file_path(f"{uid}.mp4") copy_file_fixture(
) fixture_name="sample_vid.mp4",
copy_file_fixture( output_file_path=mock_downloaded_file_path(f"{uid}.mp4"),
fixture_name="thumb.jpg", output_file_path=mock_downloaded_file_path(f"{uid}.jpg") )
) copy_file_fixture(
fixture_name="thumb.jpg", output_file_path=mock_downloaded_file_path(f"{uid}.jpg")
)
return entry_dict return entry_dict
return _mock_entry_dict_factory return _mock_entry_dict_factory
@ -124,36 +127,33 @@ def mock_download_collection_entries(
): ):
@contextlib.contextmanager @contextlib.contextmanager
def _mock_download_collection_entries_factory(is_youtube_channel: bool): def _mock_download_collection_entries_factory(is_youtube_channel: bool):
def _(**kwargs):
return mock_entry_dict_factory(**kwargs)
def _write_entries_to_working_dir(*args, **kwargs) -> List[Dict]: def _write_entries_to_working_dir(*args, **kwargs) -> List[Dict]:
if (len(args[0].collection.urls.list) == 1) or ( if (len(args[0].collection.urls.list) == 1) or (
"season.2" in kwargs["url"] and len(args[0].download_options.urls.list) > 1 "season.2" in kwargs["url"] and len(args[0].download_options.urls.list) > 1
): ):
return [ return [
_( mock_entry_dict_factory(
uid="21-1", uid="21-1",
upload_date="20210808", upload_date="20210808",
playlist_index=1, playlist_index=1,
playlist_count=4, playlist_count=4,
is_youtube_channel=is_youtube_channel, is_youtube_channel=is_youtube_channel,
), # 1 ), # 1
_( mock_entry_dict_factory(
uid="20-1", uid="20-1",
upload_date="20200808", upload_date="20200808",
playlist_index=2, playlist_index=2,
playlist_count=4, playlist_count=4,
is_youtube_channel=is_youtube_channel, is_youtube_channel=is_youtube_channel,
), # 2 98 ), # 2 98
_( mock_entry_dict_factory(
uid="20-2", uid="20-2",
upload_date="20200808", upload_date="20200808",
playlist_index=3, playlist_index=3,
playlist_count=4, playlist_count=4,
is_youtube_channel=is_youtube_channel, is_youtube_channel=is_youtube_channel,
), # 1 99 ), # 1 99
_( mock_entry_dict_factory(
uid="20-3", uid="20-3",
upload_date="20200807", upload_date="20200807",
playlist_index=4, playlist_index=4,
@ -163,35 +163,36 @@ def mock_download_collection_entries(
] ]
return [ return [
# 20-3 should resolve to collection 1 (which is season 2) # 20-3 should resolve to collection 1 (which is season 2)
_( mock_entry_dict_factory(
uid="20-3", uid="20-3",
upload_date="20200807", upload_date="20200807",
playlist_index=1, playlist_index=1,
playlist_count=5, playlist_count=5,
is_youtube_channel=is_youtube_channel, is_youtube_channel=is_youtube_channel,
mock_download_to_working_dir=False,
), ),
_( mock_entry_dict_factory(
uid="20-4", uid="20-4",
upload_date="20200806", upload_date="20200806",
playlist_index=2, playlist_index=2,
playlist_count=5, playlist_count=5,
is_youtube_channel=is_youtube_channel, is_youtube_channel=is_youtube_channel,
), ),
_( mock_entry_dict_factory(
uid="20-5", uid="20-5",
upload_date="20200706", upload_date="20200706",
playlist_index=3, playlist_index=3,
playlist_count=5, playlist_count=5,
is_youtube_channel=is_youtube_channel, is_youtube_channel=is_youtube_channel,
), ),
_( mock_entry_dict_factory(
uid="20-6", uid="20-6",
upload_date="20200706", upload_date="20200706",
playlist_index=4, playlist_index=4,
playlist_count=5, playlist_count=5,
is_youtube_channel=is_youtube_channel, is_youtube_channel=is_youtube_channel,
), ),
_( mock_entry_dict_factory(
uid="20-7", uid="20-7",
upload_date="20200606", upload_date="20200606",
playlist_index=5, playlist_index=5,