Skip to content

Commit

Permalink
Test Markers as Test Fields
Browse files Browse the repository at this point in the history
  • Loading branch information
jyejare committed Dec 7, 2023
1 parent 371feb4 commit e35cb66
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 1 deletion.
2 changes: 1 addition & 1 deletion betelgeuse/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -423,7 +423,7 @@ def get_requirement_field_values(config, requirement):

def update_testcase_fields(config, testcase):
"""Apply testcase fields default values and transformations."""
if testcase.docstring and not type(testcase.docstring) == str:
if testcase.docstring and not isinstance(testcase.docstring, str):
testcase.docstring = testcase.docstring.decode('utf8')

# Check if any field needs a default value
Expand Down
31 changes: 31 additions & 0 deletions betelgeuse/collector.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import os

from betelgeuse.parser import parse_docstring
from betelgeuse.parser import parse_markers
from betelgeuse.source_generator import gen_source


Expand Down Expand Up @@ -88,11 +89,20 @@ def __init__(self, function_def, parent_class=None, testmodule=None):
for decorator in self.parent_class_def.decorator_list
]
self._parse_docstring()
self._parse_markers()
self.junit_id = self._generate_junit_id()

if 'id' not in self.fields:
self.fields['id'] = self.junit_id

def _parse_markers(self):
"""Parse module, class and function markers."""
markers = [self.module_def.marker_list,
self.class_decorators,
self.decorators]
if markers:
self.fields.update({'markers': parse_markers(markers)})

def _parse_docstring(self):
"""Parse package, module, class and function docstrings."""
if self.docstring is None:
Expand Down Expand Up @@ -137,12 +147,33 @@ def is_test_module(filename):
return False


def _module_markers(module_def):
"""Extract markers applied to testcases from the test module level.
The markers list would be collected from the pytestmark global variable.
"""
markers = []
for node in module_def.body:
if isinstance(node, ast.Assign):
for target in node.targets:
if isinstance(target, ast.Name) and target.id == 'pytestmark':
if isinstance(node.value, ast.List):
for item in node.value.elts:
if isinstance(item, ast.Attribute):
markers.append(item.attr)
elif isinstance(node.value, ast.Attribute):
markers.append(node.value.attr)
return markers or None


def _get_tests(path):
"""Collect tests for the test module located at ``path``."""
tests = []
with open(path) as handler:
root = ast.parse(handler.read())
root.path = path # TODO improve how to pass the path to TestFunction
# Updating test module with module level markers
root.__dict__['marker_list'] = _module_markers(root)
for node in ast.iter_child_nodes(root):
if isinstance(node, ast.ClassDef):
[
Expand Down
28 changes: 28 additions & 0 deletions betelgeuse/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,3 +187,31 @@ def parse_docstring(docstring=None):
field_value = output
fields_dict[field_name] = field_value
return fields_dict


def parse_markers(all_markers=None):
"""Parse the markers."""
ignore_list = ['parametrize', 'skipif', 'usefixtures', 'skip_if_not_set']
resolved_markers = []

def _process_marker(marker):
# Fetching exact marker name
marker_name = marker.split('mark.')[-1] if 'mark' in marker else marker

# ignoring the marker if in ignore list
if not any(ignore_word in marker_name for ignore_word in ignore_list):
resolved_markers.append(marker_name)

for sec_marker in all_markers:
# If the marker is none
if not sec_marker:
continue
elif isinstance(sec_marker, list):
for marker in sec_marker:
_process_marker(marker)
else:
_process_marker(sec_marker)

if resolved_markers:
resolved_markers = ', '.join(resolved_markers)
return resolved_markers

0 comments on commit e35cb66

Please sign in to comment.