Skip to content

Commit c215f91

Browse files
Tests: Refactored unit tests (#100)
1 parent 0b989de commit c215f91

File tree

9 files changed

+1258
-504
lines changed

9 files changed

+1258
-504
lines changed

CONTRIBUTING.md

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -132,36 +132,57 @@ ALLOWED_QUERY_PARAMS = {
132132
}
133133
```
134134
135-
If the endpoint has a key that uses an **Array**, you will need to check the **_choices** of the application the endpoint is in and build those into **netbox_utils** module util.
135+
If the endpoint has a key that uses an **Array**, you will need to add the endpoint to **REQUIRED_ID_FIND** and the key that will need to be converted. The lookup is done from the endpoint and pulls the choices from the API.
136136
137137
```python
138-
SUBDEVICE_ROLES = dict(parent=True, child=False)
139-
140138
REQUIRED_ID_FIND = {
141-
"device_types": [{"subdevice_role": SUBDEVICE_ROLES}],
139+
"circuits": set(["status"]),
140+
"devices": set(["status", "face"]),
141+
"device_types": set(["subdevice_role"]),
142+
"interfaces": set(["form_factor", "mode"]),
143+
"ip_addresses": set(["status", "role"]),
144+
"prefixes": set(["status"]),
145+
"racks": set(["status", "outer_unit", "type"]),
146+
"services": set(["protocol"]),
147+
"sites": set(["status"]),
148+
"virtual_machines": set(["status", "face"]),
149+
"vlans": set(["status"]),
142150
}
143151
# This is the method that uses the REQUIRED_ID_FIND variable (no change should be required within the method)
144-
def _change_choices_id(self, endpoint, data):
145-
"""Used to change data that is static and under _choices for the application.
146-
e.g. DEVICE_STATUS
147-
:returns data (dict): Returns the user defined data back with updated fields for _choices
148-
:params endpoint (str): The endpoint that will be used for mapping to required _choices
149-
:params data (dict): User defined data passed into the module
150-
"""
151-
if REQUIRED_ID_FIND.get(endpoint):
152-
required_choices = REQUIRED_ID_FIND[endpoint]
153-
for choice in required_choices:
154-
for key, value in choice.items():
155-
if data.get(key):
156-
try:
157-
data[key] = value[data[key].lower()]
158-
except KeyError:
159-
self._handle_errors(
160-
msg="%s may not be a valid choice. If it is valid, please submit bug report."
161-
% (key)
162-
)
163-
164-
return data
152+
def _fetch_choice_value(self, search, endpoint):
153+
app = self._find_app(endpoint)
154+
nb_app = getattr(self.nb, app)
155+
nb_endpoint = getattr(nb_app, endpoint)
156+
endpoint_choices = nb_endpoint.choices()
157+
158+
choices = [x for x in chain.from_iterable(endpoint_choices.values())]
159+
160+
for item in choices:
161+
if item["display_name"].lower() == search.lower():
162+
return item["value"]
163+
elif item["value"] == search.lower():
164+
return item["value"]
165+
self._handle_errors(
166+
msg="%s was not found as a valid choice for %s" % (search, endpoint)
167+
)
168+
169+
def _change_choices_id(self, endpoint, data):
170+
"""Used to change data that is static and under _choices for the application.
171+
ex. DEVICE_STATUS
172+
:returns data (dict): Returns the user defined data back with updated fields for _choices
173+
:params endpoint (str): The endpoint that will be used for mapping to required _choices
174+
:params data (dict): User defined data passed into the module
175+
"""
176+
if REQUIRED_ID_FIND.get(endpoint):
177+
required_choices = REQUIRED_ID_FIND[endpoint]
178+
for choice in required_choices:
179+
if data.get(choice):
180+
if isinstance(data[choice], int):
181+
continue
182+
choice_value = self._fetch_choice_value(data[choice], endpoint)
183+
data[choice] = choice_value
184+
185+
return data
165186
```
166187
167188
If the key is something that pertains to a different endpoint such as **manufacturer** it will need to be added to a few variables within **netbox_utils**.
@@ -259,7 +280,7 @@ Copying an existing module that has close to the same options is typically the p
259280
260281
#### Testing
261282
262-
- Please update `tests/unit/module_utils/test_netbox_base_class.py` if editing anything within the base class that needs to be tested. This will most likely be needed as there are a few unit tests that test the data of **ALLOWED_QUERY_PARAMS**, etc.
283+
- Please update any associated data within the `tests/unit/module_utils/test_data/` folders for the specified tests. This will most likely be needed as there are a few unit tests that test the data of **ALLOWED_QUERY_PARAMS**, etc.
263284
264285
```python
265286
def test_normalize_data_returns_correct_data()
@@ -269,7 +290,9 @@ Copying an existing module that has close to the same options is typically the p
269290
def test_build_query_params_child()
270291
```
271292
293+
- Check each test above to see which `test_data` it uses and edit the corresponding data.json file
272294
- Please add or update an existing play to test the new Netbox module for integration testing within `tests/integration/integration-tests.yml`. Make sure to test creation, duplicate, update (if possible), and deletion along with any other conditions that may want to be tested.
295+
- Run `pytest -vv` to make sure all unit tests pass
273296
- Run `black .` within the base directory for black formatting as it's required for tests to pass
274297
- Run `ansible-lint integration-tests.yml` it's required for tests to pass
275298
- Check necessary dependencies defined within `.travis.yml` for now if you're wanting to test locally
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[
2+
{
3+
"data": {
4+
"name": "Test Device",
5+
"enabled": true,
6+
"site": null,
7+
"description": null,
8+
"platform": null,
9+
"status": 0
10+
},
11+
"expected": {
12+
"name": "Test Device",
13+
"enabled": true,
14+
"status": 0
15+
}
16+
}
17+
]
Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
[
2+
{
3+
"parent": "primary_ip4",
4+
"module_data": {
5+
"name": "test100",
6+
"serial": "FXS1001",
7+
"comments": "Temp device",
8+
"primary_ip4": {
9+
"address": "172.16.180.1/24",
10+
"vrf": "Test VRF"
11+
}
12+
},
13+
"child": {
14+
"address": "172.16.180.1/24",
15+
"vrf": "Test VRF"
16+
},
17+
"expected": {
18+
"address": "172.16.180.1/24",
19+
"vrf_id": 1
20+
}
21+
},
22+
{
23+
"parent": "primary_ip6",
24+
"module_data": {
25+
"name": "test100",
26+
"serial": "FXS1001",
27+
"comments": "Temp device",
28+
"primary_ip4": {
29+
"address": "2001::1:1/64",
30+
"vrf": "Test VRF"
31+
}
32+
},
33+
"child": {
34+
"address": "2001::1:1/64",
35+
"vrf": "Test VRF"
36+
},
37+
"expected": {
38+
"address": "2001::1:1/64",
39+
"vrf_id": 1
40+
}
41+
},
42+
{
43+
"parent": "lag",
44+
"module_data": {
45+
"name": "GigabitEthernet1",
46+
"device": 1,
47+
"lag": {
48+
"name": "port-channel1"
49+
}
50+
},
51+
"child": {
52+
"name": "port-channel1"
53+
},
54+
"expected": {
55+
"device_id": 1,
56+
"form_factor": 200,
57+
"name": "port-channel1"
58+
}
59+
},
60+
{
61+
"parent": "lag",
62+
"module_data": {
63+
"name": "GigabitEthernet1",
64+
"device": "Test Device",
65+
"lag": {
66+
"name": "port-channel1"
67+
}
68+
},
69+
"child": {
70+
"name": "port-channel1"
71+
},
72+
"expected": {
73+
"device": "Test Device",
74+
"form_factor": 200,
75+
"name": "port-channel1"
76+
}
77+
},
78+
{
79+
"parent": "nat_inside",
80+
"module_data": {
81+
"address": "10.10.10.1/24",
82+
"nat_inside": {
83+
"address": "192.168.1.1/24",
84+
"vrf": "Test VRF"
85+
}
86+
},
87+
"child": {
88+
"address": "192.168.1.1/24",
89+
"vrf": "Test VRF"
90+
},
91+
"expected": {
92+
"address": "192.168.1.1/24",
93+
"vrf_id": 1
94+
}
95+
},
96+
{
97+
"parent": "vlan",
98+
"module_data": {
99+
"prefix": "10.10.10.0/24",
100+
"description": "Test Prefix",
101+
"vlan": {
102+
"name": "Test VLAN",
103+
"site": "Test Site",
104+
"tenant": "Test Tenant",
105+
"vlan_group": "Test VLAN group"
106+
}
107+
},
108+
"child": {
109+
"name": "Test VLAN",
110+
"site": "Test Site",
111+
"tenant": "Test Tenant",
112+
"vlan_group": "Test VLAN group"
113+
},
114+
"expected": {
115+
"name": "Test VLAN",
116+
"site_id": 1,
117+
"tenant_id": 1,
118+
"group": "Test VLAN group"
119+
}
120+
},
121+
{
122+
"parent": "vlan_group",
123+
"module_data": {
124+
"prefix": "10.10.10.0/24",
125+
"description": "Test Prefix",
126+
"vlan_group": {
127+
"name": "Test VLAN Group",
128+
"slug": "test-vlan-group",
129+
"site": "Test Site"
130+
}
131+
},
132+
"child": {
133+
"name": "Test VLAN Group",
134+
"slug": "test-vlan-group",
135+
"site": "Test Site"
136+
},
137+
"expected": {
138+
"slug": "test-vlan-group",
139+
"site_id": 1
140+
}
141+
},
142+
{
143+
"parent": "untagged_vlan",
144+
"module_data": {
145+
"prefix": "10.10.10.0/24",
146+
"description": "Test Prefix",
147+
"untagged_vlan": {
148+
"name": "Test VLAN",
149+
"site": "Test Site"
150+
}
151+
},
152+
"child": {
153+
"name": "Test VLAN",
154+
"site": "Test Site"
155+
},
156+
"expected": {
157+
"name": "Test VLAN",
158+
"site_id": 1
159+
}
160+
},
161+
{
162+
"parent": "vrf",
163+
"module_data": {
164+
"prefix": "10.10.10.0/24",
165+
"description": "Test Prefix",
166+
"vrf": {
167+
"name": "Test VRF",
168+
"tenant": "Test Tenant"
169+
}
170+
},
171+
"child": {
172+
"name": "Test VRF",
173+
"tenant": "Test Tenant"
174+
},
175+
"expected": {
176+
"name": "Test VRF",
177+
"tenant_id": 1
178+
}
179+
}
180+
]

0 commit comments

Comments
 (0)