test_notification.test_observers_sanity_test()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 6
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nop 0
1
import pytest
2
3
from software_patterns import Observer, Subject
4
5
6
def test_observers_sanity_test():
7
    subject1: Subject = Subject([])
8
    subject2: Subject = Subject([])
9
    assert hasattr(subject1, '_observers')
10
    assert hasattr(subject2, '_observers')
11
    assert id(subject1._observers) != id(subject2._observers)
12
13
14
# def test_observer_as_constructor(observer: t.Type[Observer]):
15
def test_observer_as_constructor():
16
17
    import sys
18
19
    observer = Observer
20
21
    with pytest.raises(TypeError) as instantiation_from_interface_error:
22
        _observer_instance = observer()  # type: ignore[abstract]
23
24
    error_msg = str(instantiation_from_interface_error.value)
25
    if sys.version_info >= (3, 12):
26
        expected = "Can't instantiate abstract class Observer without an implementation for abstract method 'update'"
27
        assert error_msg == expected
28
    else:
29
        import re
30
31
        runtime_exception_message_reg = (
32
            r"Can't instantiate abstract class Observer with abstract methods? update"
33
        )
34
        assert re.match(runtime_exception_message_reg, error_msg)
35
36
37
# def test_scenario(subject: t.Type[Subject], observer: t.Type[Observer]):
38
def test_scenario():
39
    # Scenario 1
40
    # The client code.
41
    class ObserverA(Observer):
42
        def update(self, *args, **kwargs) -> None:
43
            print("ObserverA: Reacted to the event")
44
45
    s1: Subject = Subject([])
46
    o1 = ObserverA()
47
    s1.attach(o1)
48
49
    # business logic
50
    s1.state = 0
51
    s1.notify()
52
53
    # Scenario 2
54
    class Businessubject(Subject):
55
        def some_business_logic(self) -> None:
56
            """
57
            Usually, the subscription logic is only a fraction of what a Subject can
58
            really do. Subjects commonly hold some important business logic, that
59
            triggers a notification method whenever something important is about to
60
            happen (or after it).
61
            """
62
            print("\nSubject: I'm doing something important.")
63
            self._state = 2
64
            print(f"Subject: My state has just changed to: {self._state}")
65
            self.notify()
66
67
    class ObserverB(Observer):
68
        def update(self, *args, **kwargs) -> None:
69
            subject = args[0]
70
            if subject.state == 0 or subject.state >= 2:
71
                print("ObserverB: Reacted to the event")
72
73
    s2 = Businessubject([])
74
    assert id(s1) != id(s2)
75
    assert id(s1._observers) != id(s2._observers)
76
    o1, o2 = ObserverA(), ObserverB()
77
78
    s2.add(o1, o2)
79
    # business logic
80
    print(s2._observers)
81
    s2.some_business_logic()
82
    s2.some_business_logic()
83
84
    s2.detach(o1)
85
    s2.some_business_logic()
86