Skip to content

Commit

Permalink
Merge pull request #494 from peverwhee/testing_updates
Browse files Browse the repository at this point in the history
Testing updates
  • Loading branch information
peverwhee authored Oct 12, 2023
2 parents c2c2aa0 + 1bacf44 commit eac8bb8
Show file tree
Hide file tree
Showing 18 changed files with 187 additions and 215 deletions.
17 changes: 17 additions & 0 deletions .github/workflows/capgen_unit_tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
name: Capgen Unit Tests

on:
workflow_dispatch:
pull_request:
branches: [feature/capgen, main]

jobs:
unit_tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: update repos and install dependencies
run: sudo apt-get update && sudo apt-get install -y build-essential gfortran cmake python3 git
- name: Run unit tests
run: cd test && ./run_fortran_tests.sh

39 changes: 30 additions & 9 deletions .github/workflows/python.yaml
Original file line number Diff line number Diff line change
@@ -1,28 +1,49 @@
name: Python package

on: [push]
on:
workflow_dispatch:
pull_request:
branches: [feature/capgen, main]

jobs:
build:

runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.7]
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install flake8 pytest
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
pip install pytest
- name: Test with pytest
if: github.repository == 'NCAR/ccpp-framework' # Only run on main repo
run: |
export PYTHONPATH=$(pwd)/scripts:$(pwd)/scripts/parse_tools
pytest
pytest -v
doctest:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']

steps:
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install pytest
- name: Doctest
run: |
export PYTHONPATH=$(pwd)/scripts:$(pwd)/scripts/parse_tools
pytest -v scripts/ --doctest-modules
4 changes: 1 addition & 3 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -1,4 +1,2 @@
[pytest]
addopts = -ra -q --ignore=tests/test_capgen.py
testpaths =
tests
addopts = -ra --ignore=scripts/metadata2html.py --ignore-glob=test/**/test_reports.py
27 changes: 9 additions & 18 deletions scripts/code_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
class CodeBlock(object):
"""Class to store a block of code and a method to write it to a file
>>> CodeBlock([]) #doctest: +ELLIPSIS
<__main__.CodeBlock object at 0x...>
<code_block.CodeBlock object at 0x...>
>>> CodeBlock(['hi mom']) #doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
ParseInternalError: Each element of <code_list> must contain exactly two items, a code string and a relative indent
Expand All @@ -24,14 +24,21 @@ class CodeBlock(object):
Traceback (most recent call last):
ParseInternalError: Each element of <code_list> must contain exactly two items, a code string and a relative indent
>>> CodeBlock([('hi mom', 1)]) #doctest: +ELLIPSIS
<__main__.CodeBlock object at 0x...>
<code_block.CodeBlock object at 0x...>
>>> from fortran_tools import FortranWriter
>>> outfile_name = "__code_block_temp.F90"
>>> outfile = FortranWriter(outfile_name, 'w', 'test file', 'test_mod')
>>> CodeBlock([('hi mom', 1)]).write(outfile, 1, {})
>>> CodeBlock([('hi {greet} mom', 1)]).write(outfile, 1, {}) #doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
ParseInternalError: 'greet' missing from <var_dict>
>>> CodeBlock([('hi {{greet}} mom', 1)]).write(outfile, 1, {})
>>> CodeBlock([('{greet} there mom', 1)]).write(outfile, 1, {'greet':'hi'})
>>> outfile.__exit__()
False
>>> import os
>>> os.remove(outfile_name)
"""

__var_re = re.compile(r"[{][ ]*([A-Za-z][A-Za-z0-9_]*)[ ]*[}]")
Expand Down Expand Up @@ -110,19 +117,3 @@ def write(self, outfile, indent_level, var_dict):
# end for

###############################################################################
if __name__ == "__main__":
# pylint: disable=ungrouped-imports
import doctest
import os
import sys
from fortran_tools import FortranWriter
# pylint: enable=ungrouped-imports
outfile_name = "__code_block_temp.F90"
with FortranWriter(outfile_name, 'w', 'test file', 'test_mod') as outfile:
fail, _ = doctest.testmod()
# end with
if os.path.exists(outfile_name):
os.remove(outfile_name)
# end if
sys.exit(fail)
# end if
16 changes: 4 additions & 12 deletions scripts/fortran_tools/parse_fortran.py
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,10 @@ def parse_fortran_var_decl(line, source, run_env):
'(8)'
>>> _VAR_ID_RE.match("foo(::,a:b,a:,:b)").group(2)
'(::,a:b,a:,:b)'
>>> from framework_env import CCPPFrameworkEnv
>>> _DUMMY_RUN_ENV = CCPPFrameworkEnv(None, ndict={'host_files':'', \
'scheme_files':'', \
'suites':''})
>>> parse_fortran_var_decl("integer :: foo", ParseSource('foo.F90', 'module', ParseContext()), _DUMMY_RUN_ENV)[0].get_prop_value('local_name')
'foo'
>>> parse_fortran_var_decl("integer :: foo = 0", ParseSource('foo.F90', 'module', ParseContext()), _DUMMY_RUN_ENV)[0].get_prop_value('local_name')
Expand Down Expand Up @@ -828,15 +832,3 @@ def parse_fortran_var_decl(line, source, run_env):
########################################################################

########################################################################

if __name__ == "__main__":
# pylint: disable=ungrouped-imports
import doctest
# pylint: enable=ungrouped-imports
from framework_env import CCPPFrameworkEnv
_DUMMY_RUN_ENV = CCPPFrameworkEnv(None, ndict={'host_files':'',
'scheme_files':'',
'suites':''})
fail, _ = doctest.testmod()
sys.exit(fail)
# end if
18 changes: 5 additions & 13 deletions scripts/metadata_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -504,14 +504,18 @@ def table_start(cls, line):

class MetadataSection(ParseSource):
"""Class to hold all information from a metadata header
>>> from framework_env import CCPPFrameworkEnv
>>> _DUMMY_RUN_ENV = CCPPFrameworkEnv(None, {'host_files':'', \
'scheme_files':'', \
'suites':''})
>>> MetadataSection("footable", "scheme", _DUMMY_RUN_ENV, \
parse_object=ParseObject("foobar.txt", \
["name = footable", "type = scheme", "module = foo", \
"[ im ]", "standard_name = horizontal_loop_extent", \
"long_name = horizontal loop extent, start at 1", \
"units = index | type = integer", \
"dimensions = () | intent = in"])) #doctest: +ELLIPSIS
<__main__.MetadataSection foo / footable at 0x...>
<metadata_table.MetadataSection foo / footable at 0x...>
>>> MetadataSection("footable", "scheme", _DUMMY_RUN_ENV, \
parse_object=ParseObject("foobar.txt", \
["name = footable", "type = scheme", "module = foobar", \
Expand Down Expand Up @@ -1310,15 +1314,3 @@ def is_scalar_reference(test_val):
return check_fortran_ref(test_val, None, False) is not None

########################################################################

if __name__ == "__main__":
# pylint: enable=ungrouped-imports
import doctest
import sys
# pylint: disable=ungrouped-imports
from framework_env import CCPPFrameworkEnv
_DUMMY_RUN_ENV = CCPPFrameworkEnv(None, {'host_files':'',
'scheme_files':'',
'suites':''})
fail, _ = doctest.testmod()
sys.exit(fail)
12 changes: 2 additions & 10 deletions scripts/metavar.py
Original file line number Diff line number Diff line change
Expand Up @@ -1379,11 +1379,11 @@ class VarDictionary(OrderedDict):
>>> VarDictionary('bar', _MVAR_DUMMY_RUN_ENV, variables={})
VarDictionary(bar)
>>> VarDictionary('baz', _MVAR_DUMMY_RUN_ENV, variables=Var({'local_name' : 'foo', 'standard_name' : 'hi_mom', 'units' : 'm s-1', 'dimensions' : '()', 'type' : 'real', 'intent' : 'in'}, ParseSource('vname', 'scheme', ParseContext()), _MVAR_DUMMY_RUN_ENV)) #doctest: +ELLIPSIS
VarDictionary(baz, [('hi_mom', <__main__.Var hi_mom: foo at 0x...>)])
VarDictionary(baz, [('hi_mom', <metavar.Var hi_mom: foo at 0x...>)])
>>> print("{}".format(VarDictionary('baz', _MVAR_DUMMY_RUN_ENV, variables=Var({'local_name' : 'foo', 'standard_name' : 'hi_mom', 'units' : 'm s-1', 'dimensions' : '()', 'type' : 'real', 'intent' : 'in'}, ParseSource('vname', 'scheme', ParseContext()), _MVAR_DUMMY_RUN_ENV))))
VarDictionary(baz, ['hi_mom'])
>>> VarDictionary('qux', _MVAR_DUMMY_RUN_ENV, variables=[Var({'local_name' : 'foo', 'standard_name' : 'hi_mom', 'units' : 'm s-1', 'dimensions' : '()', 'type' : 'real', 'intent' : 'in'}, ParseSource('vname', 'scheme', ParseContext()), _MVAR_DUMMY_RUN_ENV)]) #doctest: +ELLIPSIS
VarDictionary(qux, [('hi_mom', <__main__.Var hi_mom: foo at 0x...>)])
VarDictionary(qux, [('hi_mom', <metavar.Var hi_mom: foo at 0x...>)])
>>> VarDictionary('boo', _MVAR_DUMMY_RUN_ENV).add_variable(Var({'local_name' : 'foo', 'standard_name' : 'hi_mom', 'units' : 'm s-1', 'dimensions' : '()', 'type' : 'real', 'intent' : 'in'}, ParseSource('vname', 'scheme', ParseContext()), _MVAR_DUMMY_RUN_ENV), _MVAR_DUMMY_RUN_ENV)
>>> VarDictionary('who', _MVAR_DUMMY_RUN_ENV, variables=[Var({'local_name' : 'foo', 'standard_name' : 'hi_mom', 'units' : 'm s-1', 'dimensions' : '()', 'type' : 'real', 'intent' : 'in'}, ParseSource('vname', 'scheme', ParseContext()), _MVAR_DUMMY_RUN_ENV)]).prop_list('local_name')
Expand Down Expand Up @@ -1980,11 +1980,3 @@ def new_internal_variable_name(self, prefix=None, max_len=63):
_MVAR_DUMMY_RUN_ENV)])

###############################################################################
if __name__ == "__main__":
# pylint: disable=ungrouped-imports
import doctest
import sys
# pylint: enable=ungrouped-imports
fail, _ = doctest.testmod()
sys.exit(fail)
# end if
11 changes: 1 addition & 10 deletions scripts/parse_tools/parse_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class ParseObject(ParseContext):
"""ParseObject is a simple class that keeps track of an object's
place in a file and safely produces lines from an array of lines
>>> ParseObject('foobar.F90', []) #doctest: +ELLIPSIS
<__main__.ParseObject object at 0x...>
<parse_tools.parse_object.ParseObject object at 0x...>
>>> ParseObject('foobar.F90', []).filename
'foobar.F90'
>>> ParseObject('foobar.F90', ["##hi mom",], line_start=1).curr_line()
Expand Down Expand Up @@ -164,12 +164,3 @@ def __del__(self):
# end try

########################################################################

if __name__ == "__main__":
# pylint: disable=ungrouped-imports
import doctest
import sys
# pylint: enable=ungrouped-imports
fail, _ = doctest.testmod()
sys.exit(fail)
# end if
14 changes: 3 additions & 11 deletions scripts/parse_tools/parse_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,10 @@ def __getitem__(self, index):
class ParseContext():
"""A class for keeping track of a parsing position
>>> ParseContext(32, "source.F90") #doctest: +ELLIPSIS
<__main__.ParseContext object at 0x...>
<parse_tools.parse_source.ParseContext object at 0x...>
>>> ParseContext("source.F90", 32)
Traceback (most recent call last):
CCPPError: ParseContext linenum must be an int
parse_tools.parse_source.CCPPError: ParseContext linenum must be an int
>>> ParseContext(32, 90) #doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
CCPPError: ParseContext filenum must be a string
Expand Down Expand Up @@ -375,7 +375,7 @@ class ParseSource():
"""
A simple object for providing source information
>>> ParseSource("myname", "mytype", ParseContext(13, "foo.F90")) #doctest: +ELLIPSIS
<__main__.ParseSource object at 0x...>
<parse_tools.parse_source.ParseSource object at 0x...>
>>> ParseSource("myname", "mytype", ParseContext(13, "foo.F90")).ptype
'mytype'
>>> ParseSource("myname", "mytype", ParseContext(13, "foo.F90")).name
Expand Down Expand Up @@ -406,11 +406,3 @@ def context(self):
return self.__context

########################################################################

if __name__ == "__main__":
# pylint: disable=ungrouped-imports
import doctest
# pylint: enable=ungrouped-imports
fail, _ = doctest.testmod()
sys.exit(fail)
# end if
18 changes: 2 additions & 16 deletions scripts/parse_tools/xml_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ def call_command(commands, logger, silent=False):
###############################################################################
"""
Try a command line and return the output on success (None on failure)
>>> _LOGGER = init_log('xml_tools')
>>> set_log_to_null(_LOGGER)
>>> call_command(['ls', 'really__improbable_fffilename.foo'], _LOGGER) #doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
CCPPError: Execution of 'ls really__improbable_fffilename.foo' failed:
Expand Down Expand Up @@ -350,19 +352,3 @@ def write(self, file, encoding="us-ascii", xml_declaration=None,
# end with

##############################################################################

if __name__ == "__main__":
_LOGGER = init_log('xml_tools')
set_log_to_null(_LOGGER)
try:
# First, run doctest
# pylint: disable=ungrouped-imports
import doctest
# pylint: enable=ungrouped-imports
fail, _ = doctest.testmod()
sys.exit(fail)
except CCPPError as cerr:
print("{}".format(cerr))
sys.exit(fail)
# end try
# end if
Loading

0 comments on commit eac8bb8

Please sign in to comment.