Skip to content

Commit e51ff94

Browse files
authored
Add comprehensive tests for VARIANTEnumerator. (#913)
* test: Add test for `VARIANTEnumerator` in `test_server_automation.py` This commit introduces a new test file `test/test_server_automation.py` containing `TestVARIANTEnumerator`. This test class verifies the functionality by creating and enumerating `IDispatch` objects and asserting the correct behavior of the `Next` method of `IEnumVARIANT`. * test: Add test for `IEnumVARIANT.Next` with multiple items Refactored `test_Next` to `test_Next_single_item` and added `test_Next_multiple_items` to `TestVARIANTEnumerator` in `test_server_automation.py`. This new test verifies that `IEnumVARIANT.Next` can correctly fetch multiple items at once, ensuring proper handling of the `celt` parameter. * test: Add test for `IEnumVARIANT.Skip` method This commit introduces a new test method `test_Skip` to `TestVARIANTEnumerator` in `test_server_automation.py`. This test verifies the functionality of `IEnumVARIANT.Skip` by testing various skip scenarios, including skipping zero items, a single item, and more items than available, asserting correct return values for `Skip` and subsequent `Next` calls. * test: Add test for `IEnumVARIANT.Reset` method This commit introduces a new test method `test_Reset` to `TestVARIANTEnumerator` in `test/test_server_automation.py`. This test verifies the functionality of `IEnumVARIANT.Reset` by advancing the enumerator, resetting it, and then asserting that subsequent `Next` calls return items from the beginning of the enumeration. * test: Add test for `IEnumVARIANT.Clone` method (results in `E_NOTIMPL`) This commit introduces a new test method `test_Clone` to `TestVARIANTEnumerator` in `test_server_automation.py`. This test verifies that calling `IEnumVARIANT.Clone` on a `VARIANTEnumerator` raises a `COMError` with `hresult.E_NOTIMPL`, as the `Clone` method is not implemented. * test: Add tests for `VARIANTEnumerator` Python protocol support This commit introduces new test methods `test_dunder_iter` and `test_dunder_getitem` to `TestVARIANTEnumerator` in `test/test_server_automation.py`. `test_dunder_iter` verifies iteration support for `IEnumVARIANT` through `VARIANTEnumerator`. `test_dunder_getitem` confirms indexed access support and proper `IndexError` handling for out-of-bounds access.
1 parent da3634c commit e51ff94

1 file changed

Lines changed: 135 additions & 0 deletions

File tree

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import unittest
2+
from _ctypes import COMError
3+
4+
import comtypes.client
5+
import comtypes.hresult as hresult
6+
from comtypes.automation import IEnumVARIANT
7+
from comtypes.server.automation import VARIANTEnumerator
8+
9+
comtypes.client.GetModule("scrrun.dll")
10+
from comtypes.gen import Scripting as scrrun
11+
12+
13+
class TestVARIANTEnumerator(unittest.TestCase):
14+
def setUp(self):
15+
# Create a list of IDispatch objects to enumerate
16+
dict1 = comtypes.client.CreateObject(
17+
"Scripting.Dictionary", interface=scrrun.IDictionary
18+
)
19+
dict1.Add("key1", "value1")
20+
dict2 = comtypes.client.CreateObject(
21+
"Scripting.Dictionary", interface=scrrun.IDictionary
22+
)
23+
dict2.Add("key2", "value2")
24+
dict3 = comtypes.client.CreateObject(
25+
"Scripting.Dictionary", interface=scrrun.IDictionary
26+
)
27+
dict3.Add("key3", "value3")
28+
self.items = [dict1, dict2, dict3]
29+
self.enumerator = VARIANTEnumerator(self.items)
30+
31+
def test_Next_single_item(self):
32+
enum_variant = self.enumerator.QueryInterface(IEnumVARIANT)
33+
# Retrieve the first item
34+
item, fetched = enum_variant.Next(1)
35+
self.assertEqual(fetched, 1)
36+
dict1 = item.QueryInterface(scrrun.IDictionary)
37+
self.assertEqual(dict1.Item("key1"), "value1")
38+
# Retrieve the second item
39+
item, fetched = enum_variant.Next(1)
40+
dict2 = item.QueryInterface(scrrun.IDictionary)
41+
self.assertEqual(dict2.Item("key2"), "value2")
42+
# Retrieve the third item
43+
item, fetched = enum_variant.Next(1)
44+
self.assertEqual(fetched, 1)
45+
dict3 = item.QueryInterface(scrrun.IDictionary)
46+
self.assertEqual(dict3.Item("key3"), "value3")
47+
# After all items are enumerated, `Next` should return 0 fetched
48+
item, fetched = enum_variant.Next(1)
49+
self.assertEqual(fetched, 0)
50+
self.assertFalse(item)
51+
52+
def test_Next_multiple_items(self):
53+
enum_variant = self.enumerator.QueryInterface(IEnumVARIANT)
54+
# Retrieve all three items at once.
55+
# We can now call Next(celt) with celt != 1, the call always returns a
56+
# list:
57+
item1, item2, item3 = enum_variant.Next(3)
58+
dict1 = item1.QueryInterface(scrrun.IDictionary)
59+
self.assertEqual(dict1.Item("key1"), "value1")
60+
dict2 = item2.QueryInterface(scrrun.IDictionary)
61+
self.assertEqual(dict2.Item("key2"), "value2")
62+
dict3 = item3.QueryInterface(scrrun.IDictionary)
63+
self.assertEqual(dict3.Item("key3"), "value3")
64+
# After all items are enumerated, Next should return 0 fetched
65+
item, fetched = enum_variant.Next(1)
66+
self.assertEqual(fetched, 0)
67+
self.assertFalse(item)
68+
69+
def test_Skip(self):
70+
enum_variant = self.enumerator.QueryInterface(IEnumVARIANT)
71+
# Explicitly reset the enumerator, though it should be fresh
72+
self.assertEqual(enum_variant.Reset(), hresult.S_OK)
73+
# Skip zero items, should return S_OK
74+
self.assertEqual(enum_variant.Skip(0), hresult.S_OK)
75+
# Skip the first item
76+
self.assertEqual(enum_variant.Skip(1), hresult.S_OK)
77+
# Next should return the second item
78+
item, fetched = enum_variant.Next(1)
79+
self.assertEqual(fetched, 1)
80+
dict2 = item.QueryInterface(scrrun.IDictionary)
81+
self.assertEqual(dict2.Item("key2"), "value2")
82+
# Skip remaining items (1 items available, but skip 2)
83+
self.assertEqual(enum_variant.Skip(2), hresult.S_FALSE)
84+
# Next should now return 0 fetched
85+
item, fetched = enum_variant.Next(1)
86+
self.assertEqual(fetched, 0)
87+
self.assertFalse(item)
88+
89+
def test_Reset(self):
90+
enum_variant = self.enumerator.QueryInterface(IEnumVARIANT)
91+
# Get some items
92+
item, fetched = enum_variant.Next(1)
93+
self.assertEqual(item.QueryInterface(scrrun.IDictionary).Item("key1"), "value1")
94+
item, fetched = enum_variant.Next(1)
95+
self.assertEqual(item.QueryInterface(scrrun.IDictionary).Item("key2"), "value2")
96+
# Reset the enumerator
97+
hr = enum_variant.Reset()
98+
self.assertEqual(hr, hresult.S_OK)
99+
# Next should return the first item again
100+
item, fetched = enum_variant.Next(1)
101+
self.assertEqual(fetched, 1)
102+
# Verify the content of the first dictionary
103+
self.assertEqual(item.QueryInterface(scrrun.IDictionary).Item("key1"), "value1")
104+
105+
def test_Clone(self):
106+
enum_variant = self.enumerator.QueryInterface(IEnumVARIANT)
107+
# Clone is not implemented in `VARIANTEnumerator`.
108+
with self.assertRaises(COMError) as cm:
109+
enum_variant.Clone()
110+
self.assertEqual(cm.exception.hresult, hresult.E_NOTIMPL)
111+
112+
def test_dunder_iter(self):
113+
enum_variant = self.enumerator.QueryInterface(IEnumVARIANT)
114+
# Ensure the enumerator is reset before iterating
115+
enum_variant.Reset()
116+
dict1, dict2, dict3 = [
117+
i.QueryInterface(scrrun.IDictionary) for i in enum_variant
118+
]
119+
self.assertEqual(dict1["key1"], "value1")
120+
self.assertEqual(dict2["key2"], "value2")
121+
self.assertEqual(dict3["key3"], "value3")
122+
123+
def test_dunder_getitem(self):
124+
enum_variant = self.enumerator.QueryInterface(IEnumVARIANT)
125+
enum_variant.Reset()
126+
# Directly access items by index
127+
dict1 = enum_variant[0].QueryInterface(scrrun.IDictionary)
128+
self.assertEqual(dict1["key1"], "value1")
129+
dict2 = enum_variant[1].QueryInterface(scrrun.IDictionary)
130+
self.assertEqual(dict2["key2"], "value2")
131+
dict3 = enum_variant[2].QueryInterface(scrrun.IDictionary)
132+
self.assertEqual(dict3["key3"], "value3")
133+
# Test index out of bounds
134+
with self.assertRaises(IndexError):
135+
_ = enum_variant[len(self.items)]

0 commit comments

Comments
 (0)