chore: cleanup old testing strategy

This commit is contained in:
Benexl
2025-07-28 13:36:55 +03:00
parent b874bef2d5
commit 007954802f
2 changed files with 0 additions and 325 deletions

View File

@@ -1,115 +0,0 @@
"""Tests for episode range parser."""
import pytest
from fastanime.cli.utils.parser import parse_episode_range
class TestParseEpisodeRange:
"""Test cases for the parse_episode_range function."""
@pytest.fixture
def episodes(self):
"""Sample episode list for testing."""
return ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]
def test_no_range_returns_all_episodes(self, episodes):
"""Test that None or empty range returns all episodes."""
result = list(parse_episode_range(None, episodes))
assert result == episodes
def test_colon_only_returns_all_episodes(self, episodes):
"""Test that ':' returns all episodes."""
result = list(parse_episode_range(":", episodes))
assert result == episodes
def test_start_end_range(self, episodes):
"""Test start:end range format."""
result = list(parse_episode_range("2:5", episodes))
assert result == ["3", "4", "5"]
def test_start_only_range(self, episodes):
"""Test start: range format."""
result = list(parse_episode_range("5:", episodes))
assert result == ["6", "7", "8", "9", "10"]
def test_end_only_range(self, episodes):
"""Test :end range format."""
result = list(parse_episode_range(":3", episodes))
assert result == ["1", "2", "3"]
def test_start_end_step_range(self, episodes):
"""Test start:end:step range format."""
result = list(parse_episode_range("2:8:2", episodes))
assert result == ["3", "5", "7"]
def test_single_number_range(self, episodes):
"""Test single number format (start from index)."""
result = list(parse_episode_range("5", episodes))
assert result == ["6", "7", "8", "9", "10"]
def test_empty_start_end_in_three_part_range_raises_error(self, episodes):
"""Test that empty parts in start:end:step format raise error."""
with pytest.raises(ValueError, match="When using 3 parts"):
list(parse_episode_range(":5:2", episodes))
with pytest.raises(ValueError, match="When using 3 parts"):
list(parse_episode_range("2::2", episodes))
with pytest.raises(ValueError, match="When using 3 parts"):
list(parse_episode_range("2:5:", episodes))
def test_invalid_integer_raises_error(self, episodes):
"""Test that invalid integers raise ValueError."""
with pytest.raises(ValueError, match="Must be a valid integer"):
list(parse_episode_range("abc", episodes))
with pytest.raises(ValueError, match="Start and end must be valid integers"):
list(parse_episode_range("2:abc", episodes))
with pytest.raises(ValueError, match="All parts must be valid integers"):
list(parse_episode_range("2:5:abc", episodes))
def test_zero_step_raises_error(self, episodes):
"""Test that zero step raises ValueError."""
with pytest.raises(ValueError, match="Step value must be positive"):
list(parse_episode_range("2:5:0", episodes))
def test_negative_step_raises_error(self, episodes):
"""Test that negative step raises ValueError."""
with pytest.raises(ValueError, match="Step value must be positive"):
list(parse_episode_range("2:5:-1", episodes))
def test_too_many_colons_raises_error(self, episodes):
"""Test that too many colons raise ValueError."""
with pytest.raises(ValueError, match="Too many colon separators"):
list(parse_episode_range("2:5:7:9", episodes))
def test_edge_case_empty_list(self):
"""Test behavior with empty episode list."""
result = list(parse_episode_range(":", []))
assert result == []
def test_edge_case_single_episode(self):
"""Test behavior with single episode."""
episodes = ["1"]
result = list(parse_episode_range(":", episodes))
assert result == ["1"]
result = list(parse_episode_range("0:1", episodes))
assert result == ["1"]
def test_numerical_sorting(self):
"""Test that episodes are sorted numerically, not lexicographically."""
episodes = ["10", "2", "1", "11", "3"]
result = list(parse_episode_range(":", episodes))
assert result == ["1", "2", "3", "10", "11"]
def test_index_out_of_bounds_behavior(self, episodes):
"""Test behavior when indices exceed available episodes."""
# Python slicing handles out-of-bounds gracefully
result = list(parse_episode_range("15:", episodes))
assert result == [] # No episodes beyond index 15
result = list(parse_episode_range(":20", episodes))
assert result == episodes # All episodes (slice stops at end)

View File

@@ -1,210 +0,0 @@
"""
Tests for the TorrentDownloader class.
"""
import tempfile
import unittest
from pathlib import Path
from unittest.mock import Mock, patch
from fastanime.core.downloader.torrents import (
TorrentDownloader,
TorrentDownloadError,
LIBTORRENT_AVAILABLE,
)
from fastanime.core.exceptions import DependencyNotFoundError
class TestTorrentDownloader(unittest.TestCase):
"""Test cases for TorrentDownloader class."""
def setUp(self):
"""Set up test fixtures."""
self.temp_dir = Path(tempfile.mkdtemp())
self.downloader = TorrentDownloader(
download_path=self.temp_dir,
max_upload_rate=100,
max_download_rate=200,
max_connections=50,
)
def tearDown(self):
"""Clean up test fixtures."""
import shutil
shutil.rmtree(self.temp_dir, ignore_errors=True)
def test_init(self):
"""Test TorrentDownloader initialization."""
self.assertEqual(self.downloader.download_path, self.temp_dir)
self.assertEqual(self.downloader.max_upload_rate, 100)
self.assertEqual(self.downloader.max_download_rate, 200)
self.assertEqual(self.downloader.max_connections, 50)
self.assertTrue(self.temp_dir.exists())
def test_init_creates_download_directory(self):
"""Test that download directory is created if it doesn't exist."""
non_existent_dir = self.temp_dir / "new_dir"
self.assertFalse(non_existent_dir.exists())
downloader = TorrentDownloader(download_path=non_existent_dir)
self.assertTrue(non_existent_dir.exists())
@patch("fastanime.core.downloader.torrents.shutil.which")
def test_download_with_webtorrent_cli_not_available(self, mock_which):
"""Test webtorrent CLI fallback when not available."""
mock_which.return_value = None
with self.assertRaises(DependencyNotFoundError) as context:
self.downloader.download_with_webtorrent_cli("magnet:test")
self.assertIn("webtorrent CLI is not available", str(context.exception))
@patch("fastanime.core.downloader.torrents.subprocess.run")
@patch("fastanime.core.downloader.torrents.shutil.which")
def test_download_with_webtorrent_cli_success(self, mock_which, mock_run):
"""Test successful webtorrent CLI download."""
mock_which.return_value = "/usr/bin/webtorrent"
mock_result = Mock()
mock_result.stdout = f"Downloaded test-file to {self.temp_dir}/test-file"
mock_run.return_value = mock_result
# Create a dummy file to simulate download
test_file = self.temp_dir / "test-file"
test_file.touch()
result = self.downloader.download_with_webtorrent_cli("magnet:test")
mock_run.assert_called_once()
self.assertEqual(result, test_file)
@patch("fastanime.core.downloader.torrents.subprocess.run")
@patch("fastanime.core.downloader.torrents.shutil.which")
def test_download_with_webtorrent_cli_failure(self, mock_which, mock_run):
"""Test webtorrent CLI download failure."""
mock_which.return_value = "/usr/bin/webtorrent"
mock_run.side_effect = subprocess.CalledProcessError(
1, "webtorrent", stderr="Error"
)
with self.assertRaises(TorrentDownloadError) as context:
self.downloader.download_with_webtorrent_cli("magnet:test")
self.assertIn("webtorrent CLI failed", str(context.exception))
@unittest.skipUnless(LIBTORRENT_AVAILABLE, "libtorrent not available")
def test_setup_libtorrent_session(self):
"""Test libtorrent session setup when available."""
session = self.downloader._setup_libtorrent_session()
self.assertIsNotNone(session)
@unittest.skipIf(LIBTORRENT_AVAILABLE, "libtorrent is available")
def test_setup_libtorrent_session_not_available(self):
"""Test libtorrent session setup when not available."""
with self.assertRaises(DependencyNotFoundError):
self.downloader._setup_libtorrent_session()
@patch("fastanime.core.downloader.torrents.LIBTORRENT_AVAILABLE", False)
def test_download_with_libtorrent_not_available(self):
"""Test libtorrent download when not available."""
with self.assertRaises(DependencyNotFoundError) as context:
self.downloader.download_with_libtorrent("magnet:test")
self.assertIn("libtorrent is not available", str(context.exception))
def test_progress_callback(self):
"""Test progress callback functionality."""
callback_mock = Mock()
downloader = TorrentDownloader(
download_path=self.temp_dir, progress_callback=callback_mock
)
# The callback should be stored
self.assertEqual(downloader.progress_callback, callback_mock)
@patch.object(TorrentDownloader, "download_with_webtorrent_cli")
@patch.object(TorrentDownloader, "download_with_libtorrent")
def test_download_prefers_libtorrent(self, mock_libtorrent, mock_webtorrent):
"""Test that download method prefers libtorrent by default."""
mock_libtorrent.return_value = self.temp_dir / "test"
with patch("fastanime.core.downloader.torrents.LIBTORRENT_AVAILABLE", True):
result = self.downloader.download("magnet:test", prefer_libtorrent=True)
mock_libtorrent.assert_called_once()
mock_webtorrent.assert_not_called()
@patch.object(TorrentDownloader, "download_with_webtorrent_cli")
@patch.object(TorrentDownloader, "download_with_libtorrent")
def test_download_fallback_to_webtorrent(self, mock_libtorrent, mock_webtorrent):
"""Test fallback to webtorrent when libtorrent fails."""
mock_libtorrent.side_effect = DependencyNotFoundError("libtorrent not found")
mock_webtorrent.return_value = self.temp_dir / "test"
with patch("fastanime.core.downloader.torrents.LIBTORRENT_AVAILABLE", True):
result = self.downloader.download("magnet:test")
mock_libtorrent.assert_called_once()
mock_webtorrent.assert_called_once()
self.assertEqual(result, self.temp_dir / "test")
@patch.object(TorrentDownloader, "download_with_webtorrent_cli")
@patch.object(TorrentDownloader, "download_with_libtorrent")
def test_download_all_methods_fail(self, mock_libtorrent, mock_webtorrent):
"""Test when all download methods fail."""
mock_libtorrent.side_effect = DependencyNotFoundError("libtorrent not found")
mock_webtorrent.side_effect = DependencyNotFoundError("webtorrent not found")
with self.assertRaises(TorrentDownloadError) as context:
self.downloader.download("magnet:test")
self.assertIn("All torrent download methods failed", str(context.exception))
def test_magnet_link_detection(self):
"""Test detection of magnet links."""
magnet_link = "magnet:?xt=urn:btih:test"
http_link = "http://example.com/test.torrent"
file_path = "/path/to/test.torrent"
# These would be tested in integration tests with actual libtorrent
# Here we just verify the method exists and handles different input types
self.assertTrue(magnet_link.startswith("magnet:"))
self.assertTrue(http_link.startswith(("http://", "https://")))
self.assertFalse(file_path.startswith(("magnet:", "http://", "https://")))
class TestLegacyFunction(unittest.TestCase):
"""Test the legacy function for backward compatibility."""
def setUp(self):
"""Set up test fixtures."""
self.temp_dir = Path(tempfile.mkdtemp())
def tearDown(self):
"""Clean up test fixtures."""
import shutil
shutil.rmtree(self.temp_dir, ignore_errors=True)
@patch.object(TorrentDownloader, "download_with_webtorrent_cli")
def test_legacy_function(self, mock_download):
"""Test the legacy download_torrent_with_webtorrent_cli function."""
from fastanime.core.downloader.torrents import (
download_torrent_with_webtorrent_cli,
)
test_path = self.temp_dir / "test.mkv"
mock_download.return_value = test_path
result = download_torrent_with_webtorrent_cli(test_path, "magnet:test")
mock_download.assert_called_once_with("magnet:test")
self.assertEqual(result, test_path)
if __name__ == "__main__":
# Add subprocess import for the test
import subprocess
unittest.main()