Skip to content

Commit e28be21

Browse files
committed
chore: refactor ffi tests
This simplifies/reorganises tests to make them more logically organised, and more intentful (even if not as exhaustive). Signed-off-by: JP-Ellis <[email protected]>
1 parent 4e5aae8 commit e28be21

File tree

1 file changed

+133
-91
lines changed

1 file changed

+133
-91
lines changed

pact-python-ffi/tests/test_init.py

Lines changed: 133 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -84,136 +84,178 @@ class TestInteractionIteration:
8484
Test interaction iteration functionality.
8585
"""
8686

87-
def test_pact_interaction(self) -> None:
88-
"""Test PactInteraction class."""
87+
@pytest.fixture
88+
def pact(self) -> pact_ffi.PactHandle:
89+
"""Create a V4 pact for testing."""
8990
pact = pact_ffi.new_pact("consumer", "provider")
9091
pact_ffi.with_specification(pact, pact_ffi.PactSpecification.V4)
92+
return pact
9193

92-
# Create HTTP interaction
93-
pact_ffi.new_sync_message_interaction(pact, "test")
94+
def test_interaction_iterator_repr(self, pact: pact_ffi.PactHandle) -> None:
95+
iterator = pact_ffi.pact_model_interaction_iterator(pact.pointer())
96+
assert str(iterator) == "PactInteractionIterator"
97+
assert repr(iterator).startswith("PactInteractionIterator(")
9498

95-
# Get interactions via iterator
96-
sync_http_iter = pact_ffi.pact_handle_get_sync_http_iter(pact)
97-
list(sync_http_iter)
98-
# Test string representation works on iterator
99-
assert "PactSyncHttpIterator" in str(sync_http_iter) or str(sync_http_iter)
99+
def test_http_iterator_repr(self, pact: pact_ffi.PactHandle) -> None:
100+
iterator = pact_ffi.pact_handle_get_sync_http_iter(pact)
101+
assert str(iterator) == "PactSyncHttpIterator"
102+
assert repr(iterator).startswith("PactSyncHttpIterator(")
100103

101-
def test_pact_message_iterator(self) -> None:
102-
"""Test PactMessageIterator class."""
103-
pact = pact_ffi.new_pact("consumer", "provider")
104-
pact_ffi.with_specification(pact, pact_ffi.PactSpecification.V4)
104+
def test_async_message_iterator_repr(self, pact: pact_ffi.PactHandle) -> None:
105+
iterator = pact_ffi.pact_handle_get_async_message_iter(pact)
106+
assert str(iterator) == "PactAsyncMessageIterator"
107+
assert repr(iterator).startswith("PactAsyncMessageIterator(")
105108

106-
# Create message interaction
107-
pact_ffi.new_message_interaction(pact, "test message")
109+
def test_sync_message_iterator_repr(self, pact: pact_ffi.PactHandle) -> None:
110+
iterator = pact_ffi.pact_handle_get_sync_message_iter(pact)
111+
assert str(iterator) == "PactSyncMessageIterator"
112+
assert repr(iterator).startswith("PactSyncMessageIterator(")
108113

109-
# Get message iterator
110-
iterator = pact_ffi.pact_handle_get_message_iter(pact)
114+
def test_empty_iterators(self, pact: pact_ffi.PactHandle) -> None:
115+
inter_iter = pact_ffi.pact_model_interaction_iterator(pact.pointer())
116+
assert sum(1 for _ in inter_iter) == 0
111117

112-
# Test string representation
113-
assert "PactMessageIterator" in str(iterator)
114-
assert "PactMessageIterator" in repr(iterator)
118+
http_iterator = pact_ffi.pact_handle_get_sync_http_iter(pact)
119+
assert sum(1 for _ in http_iterator) == 0
115120

116-
# Iterate and count messages
117-
message_count = sum(1 for _ in iterator)
121+
async_iterator = pact_ffi.pact_handle_get_async_message_iter(pact)
122+
assert sum(1 for _ in async_iterator) == 0
118123

119-
# Should have the message
120-
assert message_count >= 1
124+
sync_iterator = pact_ffi.pact_handle_get_sync_message_iter(pact)
125+
assert sum(1 for _ in sync_iterator) == 0
121126

122-
def test_pact_interaction_owned(self) -> None:
123-
"""Test PactInteraction with owned parameter."""
124-
pact = pact_ffi.new_pact("consumer", "provider")
125-
pact_ffi.with_specification(pact, pact_ffi.PactSpecification.V4)
126-
pact_ffi.new_sync_message_interaction(pact, "test")
127+
def test_iterators(self, pact: pact_ffi.PactHandle) -> None:
128+
pact_ffi.new_interaction(pact, "http")
129+
pact_ffi.new_message_interaction(pact, "async")
130+
pact_ffi.new_sync_message_interaction(pact, "sync")
127131

128-
# Get an interaction through the iterator
129-
sync_iter = pact_ffi.pact_handle_get_sync_message_iter(pact)
130-
for interaction in sync_iter:
131-
# Interaction should be owned by the iterator
132-
# Test destructor doesn't crash
133-
del interaction
134-
break
135-
136-
def test_pact_message_iterator_empty(self) -> None:
137-
"""Test PactMessageIterator with no messages."""
138-
pact = pact_ffi.new_pact("consumer", "provider")
139-
pact_ffi.with_specification(pact, pact_ffi.PactSpecification.V4)
132+
# Test each iterator type
133+
interaction_iter = pact_ffi.pact_model_interaction_iterator(pact.pointer())
134+
assert sum(1 for _ in interaction_iter) == 3
135+
assert sum(1 for _ in interaction_iter) == 0 # exhausted
140136

141-
iterator = pact_ffi.pact_handle_get_message_iter(pact)
137+
http_iter = pact_ffi.pact_handle_get_sync_http_iter(pact)
138+
assert sum(1 for _ in http_iter) == 1
139+
assert sum(1 for _ in http_iter) == 0 # exhausted
142140

143-
# Should iterate zero times
144-
message_count = sum(1 for _ in iterator)
145-
assert message_count == 0
141+
async_iter = pact_ffi.pact_handle_get_async_message_iter(pact)
142+
assert sum(1 for _ in async_iter) == 1
143+
assert sum(1 for _ in async_iter) == 0 # exhausted
146144

147-
def test_pact_interaction_iterator_next(self) -> None:
148-
"""Test iterator next functions."""
149-
pact = pact_ffi.new_pact("consumer", "provider")
150-
pact_ffi.with_specification(pact, pact_ffi.PactSpecification.V4)
145+
sync_iter = pact_ffi.pact_handle_get_sync_message_iter(pact)
146+
assert sum(1 for _ in sync_iter) == 1
147+
assert sum(1 for _ in sync_iter) == 0 # exhausted
151148

152-
# Create multiple interactions
149+
def test_iterator_types(self, pact: pact_ffi.PactHandle) -> None:
153150
pact_ffi.new_interaction(pact, "http")
154151
pact_ffi.new_message_interaction(pact, "async")
155152
pact_ffi.new_sync_message_interaction(pact, "sync")
156153

157-
# Test each iterator type
154+
interaction_iter = pact_ffi.pact_model_interaction_iterator(pact.pointer())
155+
assert all(
156+
isinstance(interaction, pact_ffi.PactInteraction)
157+
for interaction in interaction_iter
158+
)
159+
158160
http_iter = pact_ffi.pact_handle_get_sync_http_iter(pact)
159-
http_count = sum(1 for _ in http_iter)
160-
assert http_count == 1
161+
assert all(
162+
isinstance(interaction, pact_ffi.SynchronousHttp)
163+
for interaction in http_iter
164+
)
161165

162166
async_iter = pact_ffi.pact_handle_get_async_message_iter(pact)
163-
async_count = sum(1 for _ in async_iter)
164-
assert async_count == 1
167+
assert all(
168+
isinstance(interaction, pact_ffi.AsynchronousMessage)
169+
for interaction in async_iter
170+
)
165171

166172
sync_iter = pact_ffi.pact_handle_get_sync_message_iter(pact)
167-
sync_count = sum(1 for _ in sync_iter)
168-
assert sync_count == 1
173+
assert all(
174+
isinstance(interaction, pact_ffi.SynchronousMessage)
175+
for interaction in sync_iter
176+
)
169177

170-
def test_pact_message_iterator_repr(self) -> None:
171-
"""Test PactMessageIterator __repr__ method."""
178+
179+
class TestPactModelHandle:
180+
"""
181+
Test basic Pact model pointer handling.
182+
"""
183+
184+
@pytest.fixture
185+
def pact(self) -> pact_ffi.PactHandle:
186+
"""Create a V4 pact for testing."""
172187
pact = pact_ffi.new_pact("consumer", "provider")
173188
pact_ffi.with_specification(pact, pact_ffi.PactSpecification.V4)
189+
return pact
174190

175-
iterator = pact_ffi.pact_handle_get_message_iter(pact)
176-
repr_str = repr(iterator)
191+
def test_pact_handle_repr(self, pact: pact_ffi.PactHandle) -> None:
192+
assert str(pact).startswith("PactHandle(")
193+
assert repr(pact).startswith("PactHandle(")
177194

178-
assert "PactMessageIterator" in repr_str
179-
assert "0x" in repr_str or ">" in repr_str
195+
def test_pact_repr(self, pact: pact_ffi.PactHandle) -> None:
196+
pact_model = pact_ffi.pact_handle_to_pointer(pact)
180197

181-
def test_pact_interaction_str_repr(self) -> None:
182-
"""Test PactInteraction __str__ and __repr__ methods."""
183-
pact = pact_ffi.new_pact("consumer", "provider")
184-
pact_ffi.with_specification(pact, pact_ffi.PactSpecification.V4)
185-
pact_ffi.new_sync_message_interaction(pact, "test")
198+
assert isinstance(pact_model, pact_ffi.Pact)
199+
assert str(pact_model) == "Pact"
200+
assert repr(pact_model).startswith("Pact(")
186201

187-
# Get an interaction from iterator
188-
sync_iter = pact_ffi.pact_handle_get_sync_message_iter(pact)
189-
for interaction in sync_iter:
190-
str_result = str(interaction)
191-
repr_result = repr(interaction)
192202

193-
assert "SynchronousMessage" in str_result
194-
assert "SynchronousMessage" in repr_result
195-
break
203+
class TestPactInteractionCasting:
204+
"""
205+
Test casting interactions to specific subtypes via iterators.
206+
"""
196207

197-
def test_multiple_iterator_types_simultaneously(self) -> None:
198-
"""Test using multiple iterator types at the same time."""
208+
@pytest.fixture
209+
def pact(self) -> pact_ffi.PactHandle:
210+
"""Create a V4 pact for testing."""
199211
pact = pact_ffi.new_pact("consumer", "provider")
200212
pact_ffi.with_specification(pact, pact_ffi.PactSpecification.V4)
213+
return pact
201214

202-
# Create one of each type
215+
def test_synchronous_http_casting(self, pact: pact_ffi.PactHandle) -> None:
216+
"""Test SynchronousHttp interaction casting and representation."""
203217
pact_ffi.new_interaction(pact, "http")
218+
219+
# Test HTTP iterator yields SynchronousHttp
220+
interaction_iter = pact_ffi.pact_model_interaction_iterator(pact.pointer())
221+
interaction = next(interaction_iter)
222+
assert isinstance(interaction, pact_ffi.PactInteraction)
223+
http = interaction.as_synchronous_http()
224+
assert isinstance(http, pact_ffi.SynchronousHttp)
225+
226+
with pytest.raises(TypeError):
227+
interaction.as_asynchronous_message()
228+
with pytest.raises(TypeError):
229+
interaction.as_synchronous_message()
230+
231+
def test_asynchronous_message_casting(self, pact: pact_ffi.PactHandle) -> None:
232+
"""Test AsynchronousMessage interaction casting and representation."""
204233
pact_ffi.new_message_interaction(pact, "async")
205-
pact_ffi.new_sync_message_interaction(pact, "sync")
206234

207-
# Create all three iterators
208-
http_iter = pact_ffi.pact_handle_get_sync_http_iter(pact)
209-
async_iter = pact_ffi.pact_handle_get_async_message_iter(pact)
210-
sync_iter = pact_ffi.pact_handle_get_sync_message_iter(pact)
235+
# Test async message iterator yields AsynchronousMessage
236+
interaction_iter = pact_ffi.pact_model_interaction_iterator(pact.pointer())
237+
interaction = next(interaction_iter)
238+
assert isinstance(interaction, pact_ffi.PactInteraction)
239+
async_msg = interaction.as_asynchronous_message()
240+
assert isinstance(async_msg, pact_ffi.AsynchronousMessage)
211241

212-
# Iterate through all of them
213-
http_list = list(http_iter)
214-
async_list = list(async_iter)
215-
sync_list = list(sync_iter)
242+
with pytest.raises(TypeError):
243+
interaction.as_synchronous_http()
244+
with pytest.raises(TypeError):
245+
interaction.as_synchronous_message()
246+
247+
def test_synchronous_message_casting(self, pact: pact_ffi.PactHandle) -> None:
248+
"""Test SynchronousMessage interaction casting and representation."""
249+
pact_ffi.new_sync_message_interaction(pact, "sync")
216250

217-
assert len(http_list) == 1
218-
assert len(async_list) == 1
219-
assert len(sync_list) == 1
251+
# Test sync message iterator yields SynchronousMessage
252+
interaction_iter = pact_ffi.pact_model_interaction_iterator(pact.pointer())
253+
interaction = next(interaction_iter)
254+
assert isinstance(interaction, pact_ffi.PactInteraction)
255+
sync_msg = interaction.as_synchronous_message()
256+
assert isinstance(sync_msg, pact_ffi.SynchronousMessage)
257+
258+
with pytest.raises(TypeError):
259+
interaction.as_synchronous_http()
260+
with pytest.raises(TypeError):
261+
interaction.as_asynchronous_message()

0 commit comments

Comments
 (0)