1
1
# cspell:ignore nodeid
2
2
"""Common fixtures for tests."""
3
- import argparse
4
3
import json
5
4
import logging
6
5
import os
7
6
import time
8
7
9
8
from pathlib import Path
10
9
from typing import Any
10
+ from typing import Callable
11
11
from typing import Dict
12
12
from typing import Generator
13
13
from typing import List
14
14
15
15
import pytest
16
16
17
+ from pluggy ._result import _Result as pluggy_result
18
+
17
19
from .defs import AnsibleProject
18
20
from .defs import CmlWrapper
19
21
from .defs import VirshWrapper
@@ -185,6 +187,24 @@ def required_environment_variables() -> Dict[str, str]:
185
187
return variables # type: ignore[return-value]
186
188
187
189
190
+ def _github_action_log (message : str ) -> None :
191
+ """Log a message to GitHub Actions.
192
+
193
+ :param message: The message
194
+ """
195
+ if os .environ .get ("GITHUB_ACTIONS" ):
196
+ print (f"\n { message } " , flush = True )
197
+
198
+
199
+ @pytest .fixture (scope = "session" , autouse = True )
200
+ def github_action_log () -> Callable [[str ], None ]:
201
+ """Log a message to GitHub Actions.
202
+
203
+ :returns: The log function
204
+ """
205
+ return _github_action_log
206
+
207
+
188
208
@pytest .fixture (scope = "session" , name = "appliance_dhcp_address" )
189
209
def _appliance_dhcp_address (env_vars : Dict [str , str ]) -> Generator [str , None , None ]:
190
210
"""Build the lab and collect the appliance DHCP address.
@@ -193,45 +213,57 @@ def _appliance_dhcp_address(env_vars: Dict[str, str]) -> Generator[str, None, No
193
213
:raises Exception: Missing environment variables, lab, or appliance
194
214
:yields: The appliance DHCP address
195
215
"""
196
- logger . info ( " Starting lab provisioning" )
216
+ _github_action_log ( "::group:: Starting lab provisioning" )
197
217
198
- if not OPTIONS :
199
- raise Exception ("Missing CML lab" )
200
- lab_file = OPTIONS .cml_lab
201
- if not os .path .exists (lab_file ):
202
- raise Exception (f"Missing lab file '{ lab_file } '" )
218
+ logger .info ("Starting lab provisioning" )
203
219
204
- start = time .time ()
205
- cml = CmlWrapper (
206
- host = env_vars ["cml_host" ],
207
- username = env_vars ["cml_ui_user" ],
208
- password = env_vars ["cml_ui_password" ],
209
- )
210
- cml .bring_up (file = lab_file )
211
- lab_id = cml .current_lab_id
220
+ try :
212
221
213
- virsh = VirshWrapper (
214
- host = env_vars ["cml_host" ],
215
- user = env_vars ["cml_ssh_user" ],
216
- password = env_vars ["cml_ssh_password" ],
217
- port = int (env_vars ["cml_ssh_port" ]),
218
- )
222
+ if not OPTIONS :
223
+ raise Exception ("Missing CML lab" )
224
+ lab_file = OPTIONS .cml_lab
225
+ if not os .path .exists (lab_file ):
226
+ raise Exception (f"Missing lab file '{ lab_file } '" )
227
+
228
+ start = time .time ()
229
+ cml = CmlWrapper (
230
+ host = env_vars ["cml_host" ],
231
+ username = env_vars ["cml_ui_user" ],
232
+ password = env_vars ["cml_ui_password" ],
233
+ )
234
+ cml .bring_up (file = lab_file )
235
+ lab_id = cml .current_lab_id
236
+
237
+ virsh = VirshWrapper (
238
+ host = env_vars ["cml_host" ],
239
+ user = env_vars ["cml_ssh_user" ],
240
+ password = env_vars ["cml_ssh_password" ],
241
+ port = int (env_vars ["cml_ssh_port" ]),
242
+ )
243
+
244
+ try :
245
+ ip_address = virsh .get_dhcp_lease (lab_id )
246
+ except Exception as exc :
247
+ virsh .close ()
248
+ cml .remove ()
249
+ raise Exception ("Failed to get DHCP lease for the appliance" ) from exc
250
+
251
+ end = time .time ()
252
+ logger .info ("Elapsed time to provision %s seconds" , end - start )
219
253
220
- try :
221
- ip_address = virsh .get_dhcp_lease (lab_id )
222
254
except Exception as exc :
223
- virsh .close ()
224
- cml .remove ()
225
- raise Exception ("Failed to get DHCP lease for the appliance" ) from exc
226
-
227
- end = time .time ()
228
- logger .info ("Elapsed time to provision %s seconds" , end - start )
255
+ logger .error ("Failed to provision lab" )
256
+ _github_action_log ("::endgroup::" )
257
+ raise Exception ("Failed to provision lab" ) from exc
229
258
230
259
virsh .close ()
260
+ _github_action_log ("::endgroup::" )
231
261
232
262
yield ip_address
233
263
264
+ _github_action_log ("::group::Removing lab" )
234
265
cml .remove ()
266
+ _github_action_log ("::endgroup::" )
235
267
236
268
237
269
@pytest .fixture
@@ -293,3 +325,45 @@ def environment() -> Dict[str, Any]:
293
325
if "VIRTUAL_ENV" in os .environ :
294
326
env ["PATH" ] = os .path .join (os .environ ["VIRTUAL_ENV" ], "bin" ) + os .pathsep + env ["PATH" ]
295
327
return env
328
+
329
+
330
+ @pytest .hookimpl (tryfirst = True , hookwrapper = True ) # type: ignore[misc]
331
+ def pytest_runtest_makereport (
332
+ item : pytest .Item , * _args : Any , ** _kwargs : Any
333
+ ) -> Generator [None , pluggy_result , None ]:
334
+ """Add additional information to the test item.
335
+
336
+ :param item: The test item
337
+ :param _args: The positional arguments
338
+ :param _kwargs: The keyword arguments
339
+ :yields: To all other hooks
340
+ """
341
+ # execute all other hooks to obtain the report object
342
+ outcome = yield
343
+ rep = outcome .get_result ()
344
+
345
+ # set a report attribute for each phase of a call, which can
346
+ # be "setup", "call", "teardown"
347
+
348
+ setattr (item , "rep_" + rep .when , rep )
349
+
350
+
351
+ @pytest .fixture (autouse = True )
352
+ def github_log (request : pytest .FixtureRequest ) -> Generator [None , None , None ]:
353
+ """Log a message to GitHub Actions.
354
+
355
+ :param request: The request
356
+ :yields: To the test
357
+ """
358
+ if not os .environ .get ("GITHUB_ACTIONS" ):
359
+ return
360
+
361
+ name = request .node .name
362
+
363
+ _github_action_log (f"::group::Run integration test: '{ name } '" )
364
+ yield
365
+
366
+ if request .node .rep_setup .passed and request .node .rep_call .failed :
367
+ _github_action_log (f"::error title=Integration test failure::{ name } " )
368
+
369
+ _github_action_log ("::endgroup::" )
0 commit comments