feat: add dog effect
- Ignores input, returns dog.mkv from immutable URL - Downloads from art-source with hash verification - Caches downloaded file locally - 5 automated tests (all passing) Owner: @giles@artdag.rose-ash.com 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
117
dog/test_effect.py
Normal file
117
dog/test_effect.py
Normal file
@@ -0,0 +1,117 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Automated tests for the dog effect.
|
||||
|
||||
Test plan:
|
||||
1. Test that effect ignores input and returns dog.mkv
|
||||
2. Test that output hash matches expected DOG_HASH
|
||||
3. Test idempotence: dog(dog(x)) == dog(x)
|
||||
4. Test with different inputs produce same output
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from effect import effect_dog, DOG_HASH, file_hash
|
||||
|
||||
|
||||
class TestDogEffect(unittest.TestCase):
|
||||
"""Tests for the dog effect."""
|
||||
|
||||
def setUp(self):
|
||||
"""Create temp directory for tests."""
|
||||
self.temp_dir = tempfile.mkdtemp()
|
||||
self.temp_path = Path(self.temp_dir)
|
||||
|
||||
def tearDown(self):
|
||||
"""Clean up temp directory."""
|
||||
import shutil
|
||||
shutil.rmtree(self.temp_dir, ignore_errors=True)
|
||||
|
||||
def test_returns_dog_video(self):
|
||||
"""Test that effect returns dog.mkv with correct hash."""
|
||||
# Create a dummy input file
|
||||
input_path = self.temp_path / "dummy_input.txt"
|
||||
input_path.write_text("This is a dummy input that should be ignored")
|
||||
|
||||
output_path = self.temp_path / "output"
|
||||
result = effect_dog(input_path, output_path, {})
|
||||
|
||||
# Verify output exists
|
||||
self.assertTrue(result.exists(), "Output file should exist")
|
||||
|
||||
# Verify hash
|
||||
output_hash = file_hash(result)
|
||||
self.assertEqual(output_hash, DOG_HASH, "Output hash should match DOG_HASH")
|
||||
|
||||
def test_ignores_input(self):
|
||||
"""Test that different inputs produce the same output."""
|
||||
# Input 1: text file
|
||||
input1 = self.temp_path / "input1.txt"
|
||||
input1.write_text("Input 1")
|
||||
output1 = self.temp_path / "output1"
|
||||
result1 = effect_dog(input1, output1, {})
|
||||
|
||||
# Input 2: different text file
|
||||
input2 = self.temp_path / "input2.txt"
|
||||
input2.write_text("Completely different input 2")
|
||||
output2 = self.temp_path / "output2"
|
||||
result2 = effect_dog(input2, output2, {})
|
||||
|
||||
# Both outputs should have same hash
|
||||
self.assertEqual(file_hash(result1), file_hash(result2),
|
||||
"Different inputs should produce same output")
|
||||
|
||||
def test_idempotence(self):
|
||||
"""Test that dog(dog(x)) == dog(x)."""
|
||||
# First application
|
||||
input_path = self.temp_path / "input.txt"
|
||||
input_path.write_text("Original input")
|
||||
output1 = self.temp_path / "output1"
|
||||
result1 = effect_dog(input_path, output1, {})
|
||||
hash1 = file_hash(result1)
|
||||
|
||||
# Second application (using first output as input)
|
||||
output2 = self.temp_path / "output2"
|
||||
result2 = effect_dog(result1, output2, {})
|
||||
hash2 = file_hash(result2)
|
||||
|
||||
self.assertEqual(hash1, hash2, "dog(dog(x)) should equal dog(x)")
|
||||
|
||||
def test_output_extension(self):
|
||||
"""Test that output has .mkv extension."""
|
||||
input_path = self.temp_path / "input.txt"
|
||||
input_path.write_text("test")
|
||||
output_path = self.temp_path / "output"
|
||||
result = effect_dog(input_path, output_path, {})
|
||||
|
||||
self.assertEqual(result.suffix, ".mkv", "Output should have .mkv extension")
|
||||
|
||||
def test_caching(self):
|
||||
"""Test that second call uses cache (faster)."""
|
||||
import time
|
||||
|
||||
input_path = self.temp_path / "input.txt"
|
||||
input_path.write_text("test")
|
||||
|
||||
# First call (may download)
|
||||
output1 = self.temp_path / "output1"
|
||||
start1 = time.time()
|
||||
effect_dog(input_path, output1, {})
|
||||
time1 = time.time() - start1
|
||||
|
||||
# Second call (should use cache)
|
||||
output2 = self.temp_path / "output2"
|
||||
start2 = time.time()
|
||||
effect_dog(input_path, output2, {})
|
||||
time2 = time.time() - start2
|
||||
|
||||
# Second call should be faster (or at least not much slower)
|
||||
# We're not strictly asserting this as network conditions vary
|
||||
print(f"First call: {time1:.3f}s, Second call: {time2:.3f}s")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user