1
0
mirror of https://github.com/kellyjonbrazil/jc.git synced 2025-06-21 00:19:42 +02:00

Feature: generic fixtures tests (#529)

* add generic test runners

* extract generic test runners

* beautify messages, remove unused return value

* add template and info do CONTRIBUTING

* typo

---------

Co-authored-by: Kelly Brazil <kellyjonbrazil@gmail.com>
This commit is contained in:
Muescha
2024-02-04 21:02:35 +01:00
committed by Kelly Brazil
parent d209780a9d
commit 962632ac1f
5 changed files with 117 additions and 91 deletions

View File

@ -33,8 +33,18 @@ actively welcome your pull requests:
file. file.
4. If you've added code that should be tested, add tests. All new parsers should 4. If you've added code that should be tested, add tests. All new parsers should
have several sample outputs and tests. have several sample outputs and tests.
- Templates: Use the [tests/templates/_test_foo.py](https://github.com/kellyjonbrazil/jc/blob/master/tests/templates/_test_foo.py) - Templates:
or [tests/templates/_test_foo_s.py (streaming)](https://github.com/kellyjonbrazil/jc/tree/master/tests/templates) files as a template - [tests/templates/_test_foo.py](https://github.com/kellyjonbrazil/jc/blob/master/tests/templates/_test_foo.py) as a template for a test.
- [tests/templates/_test_foo_s.py (streaming)](https://github.com/kellyjonbrazil/jc/tree/master/tests/templates/_test_foo_s.py) as a template for a streaming test.
- [tests/templates/_test_foo_simple.py](https://github.com/kellyjonbrazil/jc/tree/master/tests/templates/_test_foo_simple.py) as a template if you only have test with fixtures.
Execute these steps for standard tests:
- Save this file as `text_{parser_name}.py` since the helper methods extract parser names from the filename.
- Organize fixtures in `text/fixtures` for optimal structure.
- Format fixtures as follows (using double dashes):
- `{parser_name}--{some_test_description}.out` for command output.
- `{parser_name}--{some_test_description}.json` for expected JSON after parsing.
- Fixtures: Tests typically consist of an input file and an expected output - Fixtures: Tests typically consist of an input file and an expected output
JSON file. Add the data files to the appropriate folder under [tests/fixtures](https://github.com/kellyjonbrazil/jc/tree/master/tests/fixtures) JSON file. Add the data files to the appropriate folder under [tests/fixtures](https://github.com/kellyjonbrazil/jc/tree/master/tests/fixtures)
5. Documentation is auto-generated from docstrings, so ensure they are clear and 5. Documentation is auto-generated from docstrings, so ensure they are clear and

View File

@ -0,0 +1,28 @@
import unittest
from tests import utils_for_test as test_utils
# Execute these steps for standard tests:
# - Save this file as `text_{parser_name}.py` since the helper methods extract parser names from the filename.
# - Organize fixtures in `text/fixtures` for optimal structure.
# - Format fixtures as follows (using double dashes):
# - `{parser_name}--{some_test_description}.out` for command output.
# - `{parser_name}--{some_test_description}.json` for expected JSON after parsing.
class MyTests(unittest.TestCase):
def test_path_nodata(self):
"""
Test 'my_parser_name' with no data
"""
test_utils.run_no_data(self, __file__, {})
def test_all_fixtures(self):
"""
Test 'my_parser_name' with various fixtures
"""
test_utils.run_all_fixtures(self, __file__)
if __name__ == '__main__':
unittest.main()

View File

@ -1,59 +1,21 @@
import os
import json
import unittest import unittest
from typing import Dict
from jc.parsers.path import parse
THIS_DIR = os.path.dirname(os.path.abspath(__file__)) from tests import utils_for_test as test_utils
FIXTURES_DIR = 'fixtures/generic/'
def open_file(name, ext):
return open(get_path(name, ext), 'r', encoding='utf-8')
def get_path(name, ext):
return os.path.join(THIS_DIR, name + '.' + ext)
class MyTests(unittest.TestCase): class MyTests(unittest.TestCase):
f_in: Dict = {}
f_json: Dict = {}
fixtures = {
'path--one': 'fixtures/generic/path--one',
'path--long': 'fixtures/generic/path--long',
'path--windows': 'fixtures/generic/path--windows',
'path--with-spaces': 'fixtures/generic/path--with-spaces',
}
@classmethod
def setUpClass(cls):
for file, filepath in cls.fixtures.items():
with open_file(filepath, 'out') as in_file, \
open_file(filepath, 'json') as json_file:
cls.f_in[file] = in_file.read()
cls.f_json[file] = json.loads(json_file.read())
def test_path_nodata(self): def test_path_nodata(self):
""" """
Test 'path' with no data Test 'path' with no data
""" """
self.assertEqual(parse('', quiet=True), {}) test_utils.run_no_data(self, __file__, {})
def test_path(self): def test_all_fixtures(self):
""" """
Test 'path' with various logs Test 'path' with various logs
""" """
for file in self.fixtures: test_utils.run_all_fixtures(self, __file__)
with self.subTest("fixture: " + file):
self.assertEqual(
parse(self.f_in[file], quiet=True),
self.f_json[file],
"Should be equal for test files: {0}.*".format(file)
)
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -1,62 +1,23 @@
import os
import json
import unittest import unittest
from typing import Dict
from jc.parsers.path_list import parse
THIS_DIR = os.path.dirname(os.path.abspath(__file__)) from tests import utils_for_test as test_utils
FIXTURES_DIR = 'fixtures/generic/'
def open_file(name, ext):
return open(get_path(name, ext), 'r', encoding='utf-8')
def get_path(name, ext):
return os.path.join(THIS_DIR, name + '.' + ext)
class MyTests(unittest.TestCase): class MyTests(unittest.TestCase):
f_in: Dict = {}
f_json: Dict = {}
fixtures = {
'path_list--one': 'fixtures/generic/path_list--one',
'path_list--two': 'fixtures/generic/path_list--two',
'path_list--long': 'fixtures/generic/path_list--long',
'path_list--windows': 'fixtures/generic/path_list--windows',
'path_list--windows-long': 'fixtures/generic/path_list--windows-long',
'path_list--windows-environment': 'fixtures/generic/path_list--windows-environment',
'path_list--with-spaces': 'fixtures/generic/path_list--with-spaces',
}
@classmethod
def setUpClass(cls):
for file, filepath in cls.fixtures.items():
with open_file(filepath, 'out') as in_file, \
open_file(filepath, 'json') as json_file:
cls.f_in[file] = in_file.read()
cls.f_json[file] = json.loads(json_file.read())
def test_path_nodata(self): def test_path_nodata(self):
""" """
Test 'path' with no data Test 'path_list' with no data
""" """
self.assertEqual(parse('', quiet=True), []) # self.assertEqual(parse('', quiet=True), [])
test_utils.run_no_data(self, __file__, [])
def test_path(self): def test_all_fixtures(self):
""" """
Test 'path' with various logs Test 'path_list' with various logs
""" """
for file in self.fixtures:
with self.subTest("fixture: " + file): test_utils.run_all_fixtures(self, __file__)
self.assertEqual(
parse(self.f_in[file], quiet=True),
self.f_json[file],
"Should be equal for test files: {0}.*".format(file)
)
if __name__ == '__main__': if __name__ == '__main__':

65
tests/utils_for_test.py Normal file
View File

@ -0,0 +1,65 @@
"""jc - JSON test utils"""
import inspect
import json
import os
from pathlib import Path
import jc
def open_file(file_path, ext):
return open(Path(file_path).with_suffix(ext), 'r', encoding='utf-8')
def get_base_dir(file_path):
THIS_DIR = os.path.dirname(os.path.abspath(file_path))
return THIS_DIR
def get_parser_name():
# Get the calling file name from the stack
stack = inspect.stack()
calling_frame = stack[1]
calling_file_path = calling_frame[1]
return get_parser_name_from_path(calling_file_path)
def get_parser_name_from_path(parser_path):
return Path(parser_path).stem[len('test_'):]
def get_fixtures(base_dir, parser_name):
fixtures = {x.stem: str(x.with_suffix('')) for x in
(list(Path(base_dir).glob(f"**/{parser_name}--*.*")))}
return fixtures
def run_no_data(self, test_parser_path, expected):
parser_name = get_parser_name_from_path(test_parser_path)
# expected = jc.get_parser(parser_name).info.default_no_data
with self.subTest(f"'no data test' for parser '{parser_name}': "):
self.assertEqual(jc.parse(parser_name, '', quiet=True), expected)
def run_all_fixtures(self, test_parser_path):
parser_name = get_parser_name_from_path(test_parser_path)
base_dir = get_base_dir(test_parser_path)
print()
print(f"'run all fixtures' for parser '{parser_name}':")
for file, file_path in get_fixtures(base_dir, parser_name).items():
print(f"- test '{parser_name}' parser with fixture: '{file}'")
with self.subTest(f"fixture: '{file}'"):
with open_file(file_path, '.out') as in_file, \
open_file(file_path, '.json') as json_file:
f_in = in_file.read()
f_json = json.loads(json_file.read())
self.assertEqual(
jc.parse(parser_name, f_in, quiet=True),
f_json,
f"Should be equal for test files: '{file}.*'"
)