1
0

Compare commits

...

2 Commits

Author SHA1 Message Date
53b8701997 Ruff
Some checks failed
Run Python tests (through Pytest) / Test (push) Successful in 24s
Verify Python project can be installed, loaded and have version checked / Test (push) Failing after 21s
2025-02-28 09:59:52 +01:00
a1175cfc2e Update desc 2025-02-28 09:59:22 +01:00
3 changed files with 99 additions and 48 deletions

View File

@ -1,39 +1,57 @@
"""# Standardize test format """# Standardize test format
Tool for standardizing Java tests. Tool for standardizing Partisia's Java tests.
Is capable of migrating from Javadoc based property specification to the
`@DisplayName` specification and back.
""" """
import re import re
PATTERN_JAVADOC = r'/\*\*(?P<javadoc>.*(\n\s*\*.*)*?)\s*\*/' PATTERN_JAVADOC = r'/\*\*(?P<javadoc>.*(\n\s*\*.*)*?)\s*\*/'
PATTERN_DISPLAY_NAME_EXPRESSION = r'\s*(?:"[^"]*?")(?:\s*\+\s*"[^"]*?")*\s*' PATTERN_DISPLAY_NAME_EXPRESSION = r'\s*(?:"[^"]*?")(?:\s*\+\s*"[^"]*?")*\s*'
PATTERN_DISPLAY_NAME = r'@DisplayName\((?P<display>'+PATTERN_DISPLAY_NAME_EXPRESSION+r')\)' PATTERN_DISPLAY_NAME = (
r'@DisplayName\((?P<display>' + PATTERN_DISPLAY_NAME_EXPRESSION + r')\)'
)
TEST_PATTERN: re.Pattern = re.compile( TEST_PATTERN: re.Pattern = re.compile(
r'' r''
+ r'(?:' + PATTERN_JAVADOC + r'\s*)?' + r'(?:'
+ r'@(?P<annotation>Test|BeforeEach|ParameterizedTest)\s*' + PATTERN_JAVADOC
+ r'(?:'+PATTERN_DISPLAY_NAME+r'\s*)?' + r'\s*)?'
+ r'(?P<visibility>public\s+|private\s+)?void\s+(?P<name>\w+)\(', + r'@(?P<annotation>Test|BeforeEach|ParameterizedTest)\s*'
re.IGNORECASE) + r'(?:'
+ PATTERN_DISPLAY_NAME
+ r'\s*)?'
+ r'(?P<visibility>public\s+|private\s+)?void\s+(?P<name>\w+)\(',
re.IGNORECASE,
)
END_SYMBOLS = '.?!' END_SYMBOLS = '.?!'
IGNORABLE_WORDS_IN_NAME = frozenset({ IGNORABLE_WORDS_IN_NAME = frozenset(
'', {
'a', '',
'the', 'a',
'is', 'the',
'are', 'is',
}) 'are',
},
)
def format_test_prefix(name: str, description: str, annotation:
str,visibility:str, with_javadoc: bool, def format_test_prefix(
with_display_name: bool) -> str: name: str,
description: str,
annotation: str,
visibility: str,
with_javadoc: bool,
with_display_name: bool,
) -> str:
indent = '' indent = ''
str_builder = [] str_builder = []
if with_javadoc: if with_javadoc:
str_builder += ['/** ',description,' */','\n'] str_builder += ['/** ', description, ' */', '\n']
str_builder += [indent, '@', annotation] str_builder += [indent, '@', annotation]
if with_display_name: if with_display_name:
str_builder += ['\n', indent, '@DisplayName("'] str_builder += ['\n', indent, '@DisplayName("']
@ -42,9 +60,10 @@ def format_test_prefix(name: str, description: str, annotation:
str_builder += ['\n', indent] str_builder += ['\n', indent]
if visibility: if visibility:
str_builder += [visibility, ' '] str_builder += [visibility, ' ']
str_builder += ['void ',name,'('] str_builder += ['void ', name, '(']
return ''.join(str_builder) return ''.join(str_builder)
def to_camel_case_word(word: str, first: bool = False) -> str | None: def to_camel_case_word(word: str, first: bool = False) -> str | None:
if word.lower() in IGNORABLE_WORDS_IN_NAME: if word.lower() in IGNORABLE_WORDS_IN_NAME:
return None return None
@ -52,8 +71,15 @@ def to_camel_case_word(word: str, first: bool = False) -> str | None:
word = word.lower() word = word.lower()
return (word[0].lower() if first else word[0].upper()) + word[1:] return (word[0].lower() if first else word[0].upper()) + word[1:]
def to_camel_case(description: str) -> str: def to_camel_case(description: str) -> str:
description = description.replace(',',' ').replace('.',' ').replace('"', ' ').replace('+', ' ').strip(' \t.') description = (
description.replace(',', ' ')
.replace('.', ' ')
.replace('"', ' ')
.replace('+', ' ')
.strip(' \t.')
)
words = description.split(' ') words = description.split(' ')
words[0] = to_camel_case_word(words[0], first=True) words[0] = to_camel_case_word(words[0], first=True)
@ -66,10 +92,14 @@ def to_camel_case(description: str) -> str:
return ''.join(words) return ''.join(words)
def from_camel_case(name: str) -> str:
return re.sub(r'(^|[A-Z])[a-z]*', lambda x: ' '+x.group(0).capitalize(), name).strip()
def parse_javadoc_to_description(text: str| None): def from_camel_case(name: str) -> str:
return re.sub(
r'(^|[A-Z])[a-z]*', lambda x: ' ' + x.group(0).capitalize(), name,
).strip()
def parse_javadoc_to_description(text: str | None):
if text is None: if text is None:
return '' return ''
text = re.sub(r'\n\s*\*', ' ', text).strip() text = re.sub(r'\n\s*\*', ' ', text).strip()
@ -77,7 +107,7 @@ def parse_javadoc_to_description(text: str| None):
return text return text
def parse_display_name_to_description(text: str|None): def parse_display_name_to_description(text: str | None):
if text is None: if text is None:
return '' return ''
@ -88,28 +118,35 @@ def parse_display_name_to_description(text: str|None):
return text return text
def replace_test_pattern(match: re.Match, with_javadoc: bool, with_display_name: bool) -> str: def replace_test_pattern(
match: re.Match, with_javadoc: bool, with_display_name: bool,
) -> str:
javadoc = parse_javadoc_to_description(match.group('javadoc')) javadoc = parse_javadoc_to_description(match.group('javadoc'))
annotation = match.group('annotation').strip() annotation = match.group('annotation').strip()
visibility = (match.group('visibility') or '').strip() visibility = (match.group('visibility') or '').strip()
name = match.group('name').strip() name = match.group('name').strip()
display = parse_display_name_to_description(match.group('display')) display = parse_display_name_to_description(match.group('display'))
description = display or javadoc or from_camel_case(name) description = display or javadoc or from_camel_case(name)
return format_test_prefix(to_camel_case(description), return format_test_prefix(
description, annotation, visibility, to_camel_case(description),
with_javadoc=with_javadoc, description,
with_display_name=with_display_name) annotation,
visibility,
with_javadoc=with_javadoc,
with_display_name=with_display_name,
)
IMPORT_DISPLAY_NAME = 'import org.junit.jupiter.api.DisplayName;' IMPORT_DISPLAY_NAME = 'import org.junit.jupiter.api.DisplayName;'
def standardize_java_text(text: str, with_javadoc: bool, with_display_name: bool): def standardize_java_text(text: str, with_javadoc: bool, with_display_name: bool):
text = TEST_PATTERN.sub(lambda m: replace_test_pattern(m, with_javadoc, with_display_name), text) text = TEST_PATTERN.sub(
lambda m: replace_test_pattern(m, with_javadoc, with_display_name), text,
)
if '@DisplayName' in text and IMPORT_DISPLAY_NAME not in text: if '@DisplayName' in text and IMPORT_DISPLAY_NAME not in text:
lines = text.split('\n') lines = text.split('\n')
lines.insert(1, IMPORT_DISPLAY_NAME) lines.insert(1, IMPORT_DISPLAY_NAME)

View File

@ -1,13 +1,16 @@
import pathlib
import argparse import argparse
import pathlib
from . import standardize_java_text from . import standardize_java_text
def test_files(repo: pathlib.Path) -> list[pathlib.Path]: def test_files(repo: pathlib.Path) -> list[pathlib.Path]:
return list(repo.rglob('*.java')) return list(repo.rglob('*.java'))
def standardize_in_file(path: pathlib.Path, inline: bool, with_javadoc: bool,
with_display_name: bool): def standardize_in_file(
path: pathlib.Path, inline: bool, with_javadoc: bool, with_display_name: bool,
):
with open(path) as f: with open(path) as f:
text = f.read() text = f.read()
@ -21,6 +24,7 @@ def standardize_in_file(path: pathlib.Path, inline: bool, with_javadoc: bool,
else: else:
print(text_updated) print(text_updated)
def argument_parser(): def argument_parser():
argparser = argparse.ArgumentParser() argparser = argparse.ArgumentParser()
argparser.add_argument('repo', type=pathlib.Path) argparser.add_argument('repo', type=pathlib.Path)
@ -29,11 +33,18 @@ def argument_parser():
argparser.add_argument('--displayname', action='store_true') argparser.add_argument('--displayname', action='store_true')
return argparser return argparser
def main(): def main():
args = argument_parser().parse_args() args = argument_parser().parse_args()
for path in test_files(args.repo): for path in test_files(args.repo):
standardize_in_file(path, inline=args.i, with_javadoc=args.javadoc, with_display_name=args.displayname) standardize_in_file(
path,
inline=args.i,
with_javadoc=args.javadoc,
with_display_name=args.displayname,
)
if __name__ == '__main__': if __name__ == '__main__':
main() main()

View File

@ -1,7 +1,4 @@
from standardize_test_format import standardize_java_text
from standardize_test_format import standardize_java_text, PATTERN_JAVADOC
import re
INPUT_1 = """ INPUT_1 = """
package test; package test;
@ -115,22 +112,28 @@ public void zkBinderContextImplPropagatesLotOfFieldsDirectlyFromUnderlyingZkBind
def test_1(): def test_1():
assert standardize_java_text(INPUT_1.strip(),False,True) == OUTPUT_1.strip() assert standardize_java_text(INPUT_1.strip(), False, True) == OUTPUT_1.strip()
def test_2(): def test_2():
assert standardize_java_text(INPUT_2.strip(),False,True) == OUTPUT_2.strip() assert standardize_java_text(INPUT_2.strip(), False, True) == OUTPUT_2.strip()
def test_3(): def test_3():
assert standardize_java_text(INPUT_3.strip(),False,True) == OUTPUT_3.strip() assert standardize_java_text(INPUT_3.strip(), False, True) == OUTPUT_3.strip()
def test_4(): def test_4():
assert standardize_java_text(INPUT_4.strip(),False,True) == OUTPUT_4.strip() assert standardize_java_text(INPUT_4.strip(), False, True) == OUTPUT_4.strip()
def test_5(): def test_5():
assert standardize_java_text(INPUT_5.strip(),False,True) == OUTPUT_5.strip() assert standardize_java_text(INPUT_5.strip(), False, True) == OUTPUT_5.strip()
def test_5b(): def test_5b():
assert standardize_java_text(INPUT_5B.strip(),False,True) == OUTPUT_5.strip() assert standardize_java_text(INPUT_5B.strip(), False, True) == OUTPUT_5.strip()
def test_5c(): def test_5c():
assert standardize_java_text(INPUT_5C.strip(),False,True) == OUTPUT_5.strip() assert standardize_java_text(INPUT_5C.strip(), False, True) == OUTPUT_5.strip()