Skip to content

Commit 7b4f037

Browse files
authored
Improved logging for end2end testcases (#2121)
Details: * Used the existing pytest fixture 'zhmc_logger' in all end2end test functions in order to get automatic entry and exit log records. * Improved the zhmc_logger fixture to show the pytest test ID/name in the entry and exit log records. * Fixed that the zhmc_logger fixture added the file handler with every invocation, which lead to duplicated log records in the log file. * Added a new utils function skip_log() that skips the testcase but logs the skip message. That allows to see in the log why the function left again shortly after entering. It also allows to see which HMC interactions or zhmcclient API calls were made before and after the skip. * Changed any use of skip_warn() to use the new skip_log(). That moves the skip information into the log file which is now always created, and allows to much better relate the skip messages to the test functions. * As part of that, all skipif_*() functions got an additional argument for the logger. Signed-off-by: Andreas Maier <maiera@de.ibm.com>
1 parent 2745941 commit 7b4f037

34 files changed

Lines changed: 778 additions & 576 deletions

tests/end2end/conftest.py

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,18 @@
3030
LOG_DATETIME_TIMEZONE = time.gmtime
3131

3232

33+
def has_file_handler(logger, log_file):
34+
"""
35+
Returns whether a Python logger has a FileHandler for the specified log
36+
file.
37+
"""
38+
abs_log_file = os.path.abspath(log_file)
39+
return any(
40+
isinstance(h, logging.FileHandler) and h.baseFilename == abs_log_file
41+
for h in logger.handlers
42+
)
43+
44+
3345
@pytest.fixture(scope='function')
3446
def zhmc_logger(request):
3547
# Note: The first paragraph is shown by 'pytest --fixtures'
@@ -54,27 +66,24 @@ def zhmc_logger(request):
5466
Returns:
5567
logging.Logger: Logger for the test function
5668
"""
69+
testfunc_name = request.function.__name__
70+
testfunc_logger = logging.getLogger(testfunc_name)
71+
5772
log_file = os.getenv('TESTLOGFILE', None)
5873
if log_file:
5974
logging.Formatter.converter = LOG_DATETIME_TIMEZONE
6075
log_formatter = logging.Formatter(
6176
LOG_FORMAT_STRING, datefmt=LOG_DATETIME_FORMAT)
6277
log_handler = logging.FileHandler(log_file, encoding='utf-8')
6378
log_handler.setFormatter(log_formatter)
64-
65-
testfunc_name = request.function.__name__
66-
testfunc_logger = logging.getLogger(testfunc_name)
67-
68-
if log_file and log_handler not in testfunc_logger.handlers:
69-
testfunc_logger.addHandler(log_handler)
70-
71-
if log_file:
79+
if not has_file_handler(testfunc_logger, log_file):
80+
testfunc_logger.addHandler(log_handler)
7281
testfunc_logger.setLevel(logging.DEBUG)
7382
else:
7483
testfunc_logger.setLevel(logging.NOTSET)
7584

76-
testfunc_logger.debug("Entered test function")
85+
testfunc_logger.debug("Entered test function for %s", request.node.name)
7786
try:
7887
yield testfunc_logger
7988
finally:
80-
testfunc_logger.debug("Leaving test function")
89+
testfunc_logger.debug("Leaving test function for %s", request.node.name)

tests/end2end/test_activation_profile.py

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,10 @@
2626

2727
import zhmcclient
2828

29-
from .utils import skip_warn, pick_test_resources, runtest_find_list, \
29+
from .utils import skip_log, pick_test_resources, runtest_find_list, \
3030
runtest_get_properties, End2endTestWarning, skip_missing_api_feature
3131

32+
3233
urllib3.disable_warnings()
3334

3435
# Properties in minimalistic ActivationProfile objects (e.g. find_by_name())
@@ -81,14 +82,15 @@ def test_actprof_crud(zhmc_logger, classic_mode_cpcs, profile_type):
8182
Test create, read, update and delete an activation profile.
8283
"""
8384
if not classic_mode_cpcs:
84-
pytest.skip("HMC definition does not include any CPCs in classic mode")
85+
skip_log(zhmc_logger,
86+
"HMC definition does not include any CPCs in classic mode")
8587

8688
for cpc in classic_mode_cpcs:
8789
assert not cpc.dpm_enabled
8890

8991
console = cpc.manager.console
9092
skip_missing_api_feature(
91-
console, 'create-delete-activation-profiles',
93+
zhmc_logger, console, 'create-delete-activation-profiles',
9294
cpc, 'create-delete-activation-profiles')
9395

9496
actprof_mgr = getattr(cpc, profile_type + '_activation_profiles')
@@ -163,12 +165,13 @@ def test_actprof_crud(zhmc_logger, classic_mode_cpcs, profile_type):
163165
@pytest.mark.parametrize(
164166
"profile_type", ['reset', 'image', 'load']
165167
)
166-
def test_actprof_find_list(classic_mode_cpcs, profile_type):
168+
def test_actprof_find_list(zhmc_logger, classic_mode_cpcs, profile_type):
167169
"""
168170
Test list(), find(), findall().
169171
"""
170172
if not classic_mode_cpcs:
171-
pytest.skip("HMC definition does not include any CPCs in classic mode")
173+
skip_log(zhmc_logger,
174+
"HMC definition does not include any CPCs in classic mode")
172175

173176
for cpc in classic_mode_cpcs:
174177
assert not cpc.dpm_enabled
@@ -180,9 +183,9 @@ def test_actprof_find_list(classic_mode_cpcs, profile_type):
180183
# Pick the activation profiles to test with
181184
actprof_list = actprof_mgr.list()
182185
if not actprof_list:
183-
skip_warn(
184-
f"No {profile_type} activation profiles on CPC {cpc.name} "
185-
f"managed by HMC {hd.host}")
186+
skip_log(zhmc_logger,
187+
f"No {profile_type} activation profiles on CPC {cpc.name} "
188+
f"managed by HMC {hd.host}")
186189
actprof_list = pick_test_resources(actprof_list)
187190

188191
for actprof in actprof_list:
@@ -201,12 +204,13 @@ def test_actprof_find_list(classic_mode_cpcs, profile_type):
201204
@pytest.mark.parametrize(
202205
"profile_type", ['reset', 'image', 'load']
203206
)
204-
def test_actprof_property(classic_mode_cpcs, profile_type):
207+
def test_actprof_property(zhmc_logger, classic_mode_cpcs, profile_type):
205208
"""
206209
Test property related methods
207210
"""
208211
if not classic_mode_cpcs:
209-
pytest.skip("HMC definition does not include any CPCs in classic mode")
212+
skip_log(zhmc_logger,
213+
"HMC definition does not include any CPCs in classic mode")
210214

211215
for cpc in classic_mode_cpcs:
212216
assert not cpc.dpm_enabled
@@ -218,9 +222,9 @@ def test_actprof_property(classic_mode_cpcs, profile_type):
218222
# Pick the activation profiles to test with
219223
actprof_list = actprof_mgr.list()
220224
if not actprof_list:
221-
skip_warn(
222-
f"No {profile_type} activation profiles on CPC {cpc.name} "
223-
f"managed by HMC {hd.host}")
225+
skip_log(zhmc_logger,
226+
f"No {profile_type} activation profiles on CPC {cpc.name} "
227+
f"managed by HMC {hd.host}")
224228
actprof_list = pick_test_resources(actprof_list)
225229

226230
for actprof in actprof_list:

tests/end2end/test_adapter.py

Lines changed: 56 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929
import zhmcclient
3030

31-
from .utils import skip_warn, pick_test_resources, TEST_PREFIX, \
31+
from .utils import skip_log, pick_test_resources, TEST_PREFIX, \
3232
standard_partition_props, runtest_find_list, runtest_get_properties
3333

3434
urllib3.disable_warnings()
@@ -54,17 +54,19 @@ def se_version_info(cpc):
5454
return list(map(int, cpc.prop('se-version').split('.')))
5555

5656

57-
def test_adapter_find_list(all_cpcs):
57+
def test_adapter_find_list(zhmc_logger, all_cpcs):
5858
"""
5959
Test list(), find(), findall().
6060
"""
6161
if not all_cpcs:
62-
pytest.skip("HMC definition does not include any CPCs")
62+
skip_log(zhmc_logger,
63+
"HMC definition does not include any CPCs")
6364

6465
for cpc in all_cpcs:
6566
if not cpc.dpm_enabled and se_version_info(cpc) < [2, 16]:
66-
pytest.skip(f"CPC with SE {cpc.prop('se-version')} in classic "
67-
"mode does not support Adapter objects")
67+
skip_log(zhmc_logger,
68+
f"CPC with SE {cpc.prop('se-version')} in classic "
69+
"mode does not support Adapter objects")
6870

6971
session = cpc.manager.session
7072
hd = session.hmc_definition
@@ -74,7 +76,8 @@ def test_adapter_find_list(all_cpcs):
7476
# Pick the adapters to test with
7577
adapter_list = cpc.adapters.list()
7678
if not adapter_list:
77-
skip_warn(f"No adapters on CPC {cpc.name} managed by HMC {hd.host}")
79+
skip_log(zhmc_logger,
80+
f"No adapters on CPC {cpc.name} managed by HMC {hd.host}")
7881
adapter_list = pick_test_resources(adapter_list)
7982

8083
for adapter in adapter_list:
@@ -86,17 +89,19 @@ def test_adapter_find_list(all_cpcs):
8689
ADAPTER_LIST_PROPS, ADAPTER_ADDITIONAL_PROPS)
8790

8891

89-
def test_adapter_property(all_cpcs):
92+
def test_adapter_property(zhmc_logger, all_cpcs):
9093
"""
9194
Test property related methods
9295
"""
9396
if not all_cpcs:
94-
pytest.skip("HMC definition does not include any CPCs")
97+
skip_log(zhmc_logger,
98+
"HMC definition does not include any CPCs")
9599

96100
for cpc in all_cpcs:
97101
if not cpc.dpm_enabled and se_version_info(cpc) < [2, 16]:
98-
pytest.skip(f"CPC with SE {cpc.prop('se-version')} in classic "
99-
"mode does not support Adapter objects")
102+
skip_log(zhmc_logger,
103+
f"CPC with SE {cpc.prop('se-version')} in classic "
104+
"mode does not support Adapter objects")
100105
cpc_mode_str = "DPM" if cpc.dpm_enabled else "classic"
101106

102107
session = cpc.manager.session
@@ -105,8 +110,9 @@ def test_adapter_property(all_cpcs):
105110
# Pick the adapters to test with
106111
adapter_list = cpc.adapters.list()
107112
if not adapter_list:
108-
skip_warn(f"No adapters on CPC {cpc.name} ({cpc_mode_str} mode) "
109-
f"managed by HMC {hd.host}")
113+
skip_log(zhmc_logger,
114+
f"No adapters on CPC {cpc.name} ({cpc_mode_str} mode) "
115+
f"managed by HMC {hd.host}")
110116
adapter_list = pick_test_resources(adapter_list)
111117

112118
for adapter in adapter_list:
@@ -119,12 +125,13 @@ def test_adapter_property(all_cpcs):
119125
runtest_get_properties(adapter.manager, non_list_prop)
120126

121127

122-
def test_adapter_hs_crud(dpm_mode_cpcs):
128+
def test_adapter_hs_crud(zhmc_logger, dpm_mode_cpcs):
123129
"""
124130
Test create, read, update and delete a Hipersocket adapter.
125131
"""
126132
if not dpm_mode_cpcs:
127-
pytest.skip("HMC definition does not include any CPCs in DPM mode")
133+
skip_log(zhmc_logger,
134+
"HMC definition does not include any CPCs in DPM mode")
128135

129136
for cpc in dpm_mode_cpcs:
130137
assert cpc.dpm_enabled
@@ -133,7 +140,8 @@ def test_adapter_hs_crud(dpm_mode_cpcs):
133140
if se_version_info(cpc) >= [2, 17]:
134141
# TODO: Enable this case again once create_hipersocket() has been
135142
# reimplemented using partition links.
136-
pytest.skip("create_hipersocket() is not supported on z17 CPCs")
143+
skip_log(zhmc_logger,
144+
"create_hipersocket() is not supported on z17 CPCs")
137145

138146
print(f"Testing on CPC {cpc.name} ({cpc_mode_str} mode)")
139147

@@ -236,12 +244,13 @@ def test_adapter_hs_crud(dpm_mode_cpcs):
236244
@pytest.mark.parametrize(
237245
"test_family",
238246
ADAPTER_FAMILIES)
239-
def test_adapter_list_assigned_part(dpm_mode_cpcs, test_family):
247+
def test_adapter_list_assigned_part(zhmc_logger, dpm_mode_cpcs, test_family):
240248
"""
241249
Test Adapter.list_assigned_partitions().
242250
"""
243251
if not dpm_mode_cpcs:
244-
pytest.skip("HMC definition does not include any CPCs in DPM mode")
252+
skip_log(zhmc_logger,
253+
"HMC definition does not include any CPCs in DPM mode")
245254

246255
for cpc in dpm_mode_cpcs:
247256
assert cpc.dpm_enabled
@@ -264,8 +273,9 @@ def test_adapter_list_assigned_part(dpm_mode_cpcs, test_family):
264273
family_adapters.append(adapter)
265274

266275
if not family_adapters:
267-
pytest.skip(f"CPC {cpc.name} does not have any adapters with "
268-
f"family: {test_family} ")
276+
skip_log(zhmc_logger,
277+
f"CPC {cpc.name} does not have any adapters with "
278+
f"family: {test_family} ")
269279

270280
tmp_part = None
271281
try:
@@ -393,8 +403,9 @@ def test_adapter_list_assigned_part(dpm_mode_cpcs, test_family):
393403
assigned_fcp_adapters.append(adapter)
394404

395405
if not assigned_fcp_adapters:
396-
pytest.skip(f"CPC {cpc.name} does not have FCP adapters "
397-
"assigned to partitions")
406+
skip_log(zhmc_logger,
407+
f"CPC {cpc.name} does not have FCP adapters "
408+
"assigned to partitions")
398409

399410
test_adapters = pick_test_resources(assigned_fcp_adapters)
400411
for test_adapter in test_adapters:
@@ -476,8 +487,9 @@ def test_adapter_list_assigned_part(dpm_mode_cpcs, test_family):
476487
assigned_crypto_adapters.append(adapter)
477488

478489
if not assigned_crypto_adapters:
479-
pytest.skip(f"CPC {cpc.name} does not have crypto adapters "
480-
"assigned to partitions")
490+
skip_log(zhmc_logger,
491+
f"CPC {cpc.name} does not have crypto adapters "
492+
"assigned to partitions")
481493

482494
test_adapters = pick_test_resources(assigned_crypto_adapters)
483495
for test_adapter in test_adapters:
@@ -560,17 +572,19 @@ def base_adapter_id(adapter_id, family):
560572
return f'{base_pchid:03x}'
561573

562574

563-
def test_adapter_list_sibling_adapters(all_cpcs):
575+
def test_adapter_list_sibling_adapters(zhmc_logger, all_cpcs):
564576
"""
565577
Test Adapter.list_sibling_adapters().
566578
"""
567579
if not all_cpcs:
568-
pytest.skip("HMC definition does not include any CPCs")
580+
skip_log(zhmc_logger,
581+
"HMC definition does not include any CPCs")
569582

570583
for cpc in all_cpcs:
571584
if not cpc.dpm_enabled and se_version_info(cpc) < [2, 16]:
572-
pytest.skip(f"CPC with SE {cpc.prop('se-version')} in classic "
573-
"mode does not support Adapter objects")
585+
skip_log(zhmc_logger,
586+
f"CPC with SE {cpc.prop('se-version')} in classic "
587+
"mode does not support Adapter objects")
574588

575589
adapters = cpc.adapters.list()
576590

@@ -683,30 +697,34 @@ def test_adapter_list_sibling_adapters(all_cpcs):
683697
"desc, input_kwargs, exp_props, exp_exc_type, run",
684698
LIST_PERMITTED_ADAPTERS_TESTCASES)
685699
def test_adapter_list_permitted(
686-
desc, input_kwargs, exp_props, exp_exc_type, run, all_cpcs):
700+
zhmc_logger, desc, input_kwargs, exp_props, exp_exc_type, run,
701+
all_cpcs):
687702
# pylint: disable=unused-argument
688703
"""
689704
Test Console.list_permitted_adapters() without filtering, but with
690705
different variations of returned properties.
691706
"""
692707
if not all_cpcs:
693-
pytest.skip("HMC definition does not include any CPCs")
708+
skip_log(zhmc_logger,
709+
"HMC definition does not include any CPCs")
694710

695711
console = all_cpcs[0].manager.console
696712
session = console.manager.session
697713
client = console.manager.client
698714
hd = session.hmc_definition
699715

700716
if hd.mock_file:
701-
skip_warn("zhmcclient mock does not support 'List Permitted Adapters' "
702-
"operation")
717+
skip_log(zhmc_logger,
718+
"zhmcclient mock does not support 'List Permitted Adapters' "
719+
"operation")
703720

704721
if run == 'pdb':
705722
# pylint: disable=forgotten-debug-statement
706723
pdb.set_trace()
707724

708725
if not run:
709-
skip_warn("Testcase is disabled in testcase definition")
726+
skip_log(zhmc_logger,
727+
"Testcase is disabled in testcase definition")
710728

711729
# Prepare what the managed CPCs support and from which CPCs adapters
712730
# are expected.
@@ -727,11 +745,13 @@ def test_adapter_list_permitted(
727745
cpc_by_name[cpc.name] = cpc
728746

729747
if 'full_properties' in input_kwargs and not supports_full_properties:
730-
skip_warn("The managed CPCs do not support full_properties=True in "
731-
"list_permitted_adapters()")
748+
skip_log(zhmc_logger,
749+
"The managed CPCs do not support full_properties=True in "
750+
"list_permitted_adapters()")
732751
if 'additional_properties' in input_kwargs and not supports_add_properties:
733-
skip_warn("The managed CPCs do not support additional_properties=True "
734-
"in list_permitted_adapters()")
752+
skip_log(zhmc_logger,
753+
"The managed CPCs do not support additional_properties=True "
754+
"in list_permitted_adapters()")
735755

736756
if exp_exc_type:
737757

0 commit comments

Comments
 (0)