This commit is contained in:
@@ -0,0 +1,204 @@
|
||||
import pytest
|
||||
import inspect
|
||||
from unittest.mock import MagicMock, patch
|
||||
from textwrap import dedent
|
||||
|
||||
from your_module import Shortcut, as_shortcut, shortcuts, Registry
|
||||
|
||||
# Tests for Shortcut class
|
||||
|
||||
class TestShortcutInitialization:
|
||||
def test_init_with_custom_name(self):
|
||||
# Verify initialization with custom name
|
||||
func = lambda x: x * 2
|
||||
sc = Shortcut(func, name="Doubler")
|
||||
assert sc.func(5) == 10
|
||||
assert sc.name == "Doubler"
|
||||
|
||||
def test_init_without_name(self):
|
||||
# Test auto-naming from __name__
|
||||
def addition_fct(a, b):
|
||||
return a + b
|
||||
sc = Shortcut(addition_fct)
|
||||
assert sc.name == "addition fct"
|
||||
assert sc.func(2, 3) == 5
|
||||
|
||||
def test_run_method(self, capsys):
|
||||
# Test direct execution while verifying print output
|
||||
execution_results = []
|
||||
|
||||
def sample():
|
||||
execution_results.append("executed")
|
||||
return "ok"
|
||||
|
||||
sc = Shortcut(sample, name="TestRun")
|
||||
task = sc.run(hold=False) # Testing immediate execution
|
||||
|
||||
# Verify the print output
|
||||
captured = capsys.readouterr()
|
||||
assert captured.out == 'Running "TestRun"\n'
|
||||
|
||||
# Verify the function executed
|
||||
assert execution_results == ["executed"]
|
||||
|
||||
# Verify Task properties
|
||||
assert task.func == sample
|
||||
assert task.func() == "ok"
|
||||
assert task.hold is False
|
||||
|
||||
task = sc.run(hold=True)
|
||||
assert task.hold is True
|
||||
|
||||
def test_repr_output(self):
|
||||
# Test exact __repr__ format
|
||||
def my_func():
|
||||
pass
|
||||
|
||||
sc = Shortcut(my_func, name="Test Repr")
|
||||
assert repr(sc) == f"Shortcut \"Test Repr\""
|
||||
|
||||
def test_source_with_regular_function(self):
|
||||
# Test source with normal function
|
||||
def example():
|
||||
a = 1
|
||||
b = 2
|
||||
return a + b
|
||||
|
||||
sc = Shortcut(example)
|
||||
src = sc.source
|
||||
assert "def example():" in src
|
||||
assert "a = 1" in src
|
||||
assert "b = 2" in src
|
||||
assert "return a + b" in src
|
||||
|
||||
@patch('inspect.getsource')
|
||||
def test_source_error_handling(self, mock_getsource):
|
||||
# Test exception handling when inspect fails
|
||||
mock_getsource.side_effect = OSError("No source")
|
||||
sc = Shortcut(lambda x: x)
|
||||
with pytest.raises(OSError):
|
||||
_ = sc.source
|
||||
|
||||
# Tests for as_shortcut decorator
|
||||
|
||||
def test_as_shortcut_basic():
|
||||
# Test basic decorator without parameters
|
||||
@as_shortcut
|
||||
def basic_func():
|
||||
return 42
|
||||
|
||||
assert isinstance(basic_func, Shortcut)
|
||||
assert basic_func.name == "basic func"
|
||||
assert basic_func.func() == 42
|
||||
|
||||
def test_as_shortcut_with_name():
|
||||
# Test decorator with name parameter
|
||||
@as_shortcut(name="CustomName")
|
||||
def decorated():
|
||||
pass
|
||||
|
||||
assert decorated.name == "CustomName"
|
||||
|
||||
def test_as_shortcut_factory_pattern():
|
||||
# Test factory pattern usage
|
||||
decorator = as_shortcut(name="FromFactory")
|
||||
|
||||
@decorator
|
||||
def sample():
|
||||
pass
|
||||
|
||||
assert sample.name == "FromFactory"
|
||||
|
||||
# Tests for shortcuts singleton
|
||||
|
||||
class TestShortcutsSingleton:
|
||||
def setup_method(self):
|
||||
# Reset singleton before each test
|
||||
shortcuts._instance = None
|
||||
|
||||
def test_singleton_behavior(self):
|
||||
# Verify singleton pattern
|
||||
inst1 = shortcuts
|
||||
inst2 = shortcuts
|
||||
assert inst1 is inst2
|
||||
|
||||
def test_registration(self):
|
||||
# Test automatic registration
|
||||
@as_shortcut(name="FuncA")
|
||||
def func_a():
|
||||
pass
|
||||
|
||||
@as_shortcut(name="FuncB")
|
||||
def func_b():
|
||||
pass
|
||||
|
||||
assert len(shortcuts._get()) == 2
|
||||
assert "FuncA" in shortcuts._get()
|
||||
assert shortcuts["FuncA"].func == func_a.func
|
||||
|
||||
def test_getitem_access(self):
|
||||
# Test dictionary-style access
|
||||
@as_shortcut(name="TestAccess")
|
||||
def access_test():
|
||||
return 123
|
||||
|
||||
assert shortcuts["TestAccess"].func() == 123
|
||||
|
||||
def test_missing_key(self):
|
||||
# Test access with invalid key
|
||||
with pytest.raises(KeyError):
|
||||
_ = shortcuts["InvalidKey"]
|
||||
|
||||
def test_repr_output(self):
|
||||
# Test registry display
|
||||
@as_shortcut(name="DisplayTest")
|
||||
def to_display():
|
||||
pass
|
||||
|
||||
repr_str = repr(shortcuts)
|
||||
assert "DisplayTest" in repr_str
|
||||
assert "Shortcut" in repr_str
|
||||
|
||||
# Full integration tests
|
||||
|
||||
class TestFullIntegration:
|
||||
def setup_method(self):
|
||||
shortcuts._instance = None
|
||||
|
||||
def test_workflow(self, capsys):
|
||||
# Test complete workflow from creation to execution
|
||||
@as_shortcut(name="FullTest")
|
||||
def integration_test(a, b):
|
||||
print(f"Calculating {a} + {b}")
|
||||
return a + b
|
||||
|
||||
sc = shortcuts["FullTest"]
|
||||
assert sc.name == "FullTest"
|
||||
|
||||
task = sc.run(hold=True)
|
||||
out, _ = capsys.readouterr()
|
||||
assert "Running \"FullTest\"" in out
|
||||
|
||||
assert task.func(3, 4) == 7
|
||||
|
||||
source = sc.source
|
||||
assert "def integration_test(a, b):" in source
|
||||
assert "print(f\"Calculating {a} + {b}\")" in source
|
||||
|
||||
def test_multiple_shortcuts(self):
|
||||
# Test multiple shortcuts coexistence
|
||||
@as_shortcut(name="First")
|
||||
def first():
|
||||
return 1
|
||||
|
||||
@as_shortcut(name="Second")
|
||||
def second():
|
||||
return 2
|
||||
|
||||
assert shortcuts["First"].func() == 1
|
||||
assert shortcuts["Second"].func() == 2
|
||||
assert len(shortcuts._get()) == 2
|
||||
|
||||
def test_registry_inheritance():
|
||||
# Verify Shortcut inherits from Registry
|
||||
assert issubclass(Shortcut, Registry)
|
||||
Reference in New Issue
Block a user