207 lines
5.6 KiB
Python
207 lines
5.6 KiB
Python
import pytest
|
|
import inspect
|
|
from unittest.mock import MagicMock, patch
|
|
from textwrap import dedent
|
|
from slic.utils.shortcut import Shortcut, as_shortcut, shortcuts, Registry
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def reset_shortcuts():
|
|
# Reset shortcuts before each test
|
|
shortcuts._instance = None
|
|
yield
|
|
shortcuts._instance = None
|
|
|
|
# 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(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.status == "done"
|
|
|
|
def test_repr_output():
|
|
# 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():
|
|
# 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(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) |