From 4d0b6d834caa0f21edfcc682ed6cea78a917574f Mon Sep 17 00:00:00 2001 From: Greyson LaLonde Date: Thu, 22 Jan 2026 14:08:40 -0500 Subject: [PATCH] test: add real video file tests for duration detection --- .../tests/files/processing/test_validators.py | 81 ++++++++++++++++++ lib/crewai/tests/fixtures/sample_video.mp4 | Bin 0 -> 10024 bytes 2 files changed, 81 insertions(+) create mode 100644 lib/crewai/tests/fixtures/sample_video.mp4 diff --git a/lib/crewai/tests/files/processing/test_validators.py b/lib/crewai/tests/files/processing/test_validators.py index 64f803192..4be47e1d7 100644 --- a/lib/crewai/tests/files/processing/test_validators.py +++ b/lib/crewai/tests/files/processing/test_validators.py @@ -492,3 +492,84 @@ class TestGetVideoDuration: result = _get_video_duration(corrupt_data) assert result is None + + +class TestRealVideoFile: + """Tests using real video fixture file.""" + + @pytest.fixture + def sample_video_path(self): + """Path to sample video fixture.""" + from pathlib import Path + + path = Path(__file__).parent.parent.parent / "fixtures" / "sample_video.mp4" + if not path.exists(): + pytest.skip("sample_video.mp4 fixture not found") + return path + + @pytest.fixture + def sample_video_content(self, sample_video_path): + """Read sample video content.""" + return sample_video_path.read_bytes() + + def test_get_video_duration_real_file(self, sample_video_content): + """Test duration detection with real video file.""" + try: + import av # noqa: F401 + except ImportError: + pytest.skip("PyAV not installed") + + duration = _get_video_duration(sample_video_content, "video/mp4") + + assert duration is not None + assert 4.5 <= duration <= 5.5 # ~5 seconds with tolerance + + def test_get_video_duration_real_file_no_format_hint(self, sample_video_content): + """Test duration detection without format hint.""" + try: + import av # noqa: F401 + except ImportError: + pytest.skip("PyAV not installed") + + duration = _get_video_duration(sample_video_content) + + assert duration is not None + assert 4.5 <= duration <= 5.5 + + def test_validate_video_real_file_passes(self, sample_video_path): + """Test validating real video file within constraints.""" + try: + import av # noqa: F401 + except ImportError: + pytest.skip("PyAV not installed") + + constraints = VideoConstraints( + max_size_bytes=10 * 1024 * 1024, + max_duration_seconds=60, + supported_formats=("video/mp4",), + ) + file = VideoFile(source=str(sample_video_path)) + + errors = validate_video(file, constraints, raise_on_error=False) + + assert len(errors) == 0 + + def test_validate_video_real_file_duration_exceeded(self, sample_video_path): + """Test validating real video file that exceeds duration limit.""" + try: + import av # noqa: F401 + except ImportError: + pytest.skip("PyAV not installed") + + constraints = VideoConstraints( + max_size_bytes=10 * 1024 * 1024, + max_duration_seconds=2, # Video is ~5 seconds + supported_formats=("video/mp4",), + ) + file = VideoFile(source=str(sample_video_path)) + + with pytest.raises(FileValidationError) as exc_info: + validate_video(file, constraints) + + assert "duration" in str(exc_info.value).lower() + assert "2s" in str(exc_info.value) diff --git a/lib/crewai/tests/fixtures/sample_video.mp4 b/lib/crewai/tests/fixtures/sample_video.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..7f208967f9f289b73a41d3b3bf3592cef955842a GIT binary patch literal 10024 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