diff --git a/.github/workflows/capgen_unit_tests.yaml b/.github/workflows/capgen_unit_tests.yaml new file mode 100644 index 00000000..c2d52ee8 --- /dev/null +++ b/.github/workflows/capgen_unit_tests.yaml @@ -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 + diff --git a/.github/workflows/python.yaml b/.github/workflows/python.yaml index c630c438..3775a985 100644 --- a/.github/workflows/python.yaml +++ b/.github/workflows/python.yaml @@ -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 diff --git a/pytest.ini b/pytest.ini index 83323d6a..d08180f1 100644 --- a/pytest.ini +++ b/pytest.ini @@ -1,4 +1,2 @@ [pytest] -addopts = -ra -q --ignore=tests/test_capgen.py -testpaths = - tests \ No newline at end of file +addopts = -ra --ignore=scripts/metadata2html.py --ignore-glob=test/**/test_reports.py \ No newline at end of file diff --git a/scripts/code_block.py b/scripts/code_block.py index 96dc30e9..ccd3f209 100644 --- a/scripts/code_block.py +++ b/scripts/code_block.py @@ -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...> + >>> CodeBlock(['hi mom']) #doctest: +IGNORE_EXCEPTION_DETAIL Traceback (most recent call last): ParseInternalError: Each element of must contain exactly two items, a code string and a relative indent @@ -24,7 +24,10 @@ class CodeBlock(object): Traceback (most recent call last): ParseInternalError: Each element of must contain exactly two items, a code string and a relative indent >>> CodeBlock([('hi mom', 1)]) #doctest: +ELLIPSIS - <__main__.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 @@ -32,6 +35,10 @@ class CodeBlock(object): ParseInternalError: 'greet' missing from >>> 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_]*)[ ]*[}]") @@ -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 diff --git a/scripts/fortran_tools/parse_fortran.py b/scripts/fortran_tools/parse_fortran.py index 2310e13f..9aa4de7a 100644 --- a/scripts/fortran_tools/parse_fortran.py +++ b/scripts/fortran_tools/parse_fortran.py @@ -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') @@ -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 diff --git a/scripts/metadata_table.py b/scripts/metadata_table.py index 5ccf34b3..49f4ffb1 100755 --- a/scripts/metadata_table.py +++ b/scripts/metadata_table.py @@ -504,6 +504,10 @@ 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", \ @@ -511,7 +515,7 @@ class MetadataSection(ParseSource): "long_name = horizontal loop extent, start at 1", \ "units = index | type = integer", \ "dimensions = () | intent = in"])) #doctest: +ELLIPSIS - <__main__.MetadataSection foo / footable at 0x...> + >>> MetadataSection("footable", "scheme", _DUMMY_RUN_ENV, \ parse_object=ParseObject("foobar.txt", \ ["name = footable", "type = scheme", "module = foobar", \ @@ -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) diff --git a/scripts/metavar.py b/scripts/metavar.py index 64067dd1..dc088fdc 100755 --- a/scripts/metavar.py +++ b/scripts/metavar.py @@ -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', )]) >>> 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', )]) >>> 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') @@ -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 diff --git a/scripts/parse_tools/parse_object.py b/scripts/parse_tools/parse_object.py index f141b298..2c5f72f5 100644 --- a/scripts/parse_tools/parse_object.py +++ b/scripts/parse_tools/parse_object.py @@ -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...> + >>> ParseObject('foobar.F90', []).filename 'foobar.F90' >>> ParseObject('foobar.F90', ["##hi mom",], line_start=1).curr_line() @@ -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 diff --git a/scripts/parse_tools/parse_source.py b/scripts/parse_tools/parse_source.py index f96bbb2d..38a72953 100644 --- a/scripts/parse_tools/parse_source.py +++ b/scripts/parse_tools/parse_source.py @@ -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...> + >>> 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 @@ -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...> + >>> ParseSource("myname", "mytype", ParseContext(13, "foo.F90")).ptype 'mytype' >>> ParseSource("myname", "mytype", ParseContext(13, "foo.F90")).name @@ -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 diff --git a/scripts/parse_tools/xml_tools.py b/scripts/parse_tools/xml_tools.py index 414ffc5a..120ab645 100644 --- a/scripts/parse_tools/xml_tools.py +++ b/scripts/parse_tools/xml_tools.py @@ -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: @@ -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 diff --git a/scripts/var_props.py b/scripts/var_props.py index 69b6b766..15613567 100755 --- a/scripts/var_props.py +++ b/scripts/var_props.py @@ -198,7 +198,7 @@ def default_kind_val(prop_dict, context=None): >>> default_kind_val({'local_name':'foo'}) #doctest: +ELLIPSIS Traceback (most recent call last): ... - parse_source.CCPPError: No type to find default kind for foo + parse_source.CCPPError: No type to find default kind for foo >>> default_kind_val({}) #doctest: +ELLIPSIS Traceback (most recent call last): ... @@ -206,7 +206,7 @@ def default_kind_val(prop_dict, context=None): >>> default_kind_val({'local_name':'foo'}, context=ParseContext(linenum=3, filename='foo.F90')) #doctest: +ELLIPSIS Traceback (most recent call last): ... - parse_source.CCPPError: No type to find default kind for foo, at foo.F90:4 + parse_source.CCPPError: No type to find default kind for foo, at foo.F90:4 >>> default_kind_val({}, context=ParseContext(linenum=3, filename='foo.F90')) #doctest: +ELLIPSIS Traceback (most recent call last): ... @@ -515,25 +515,25 @@ def __is_horizontal_loop_dimension(hdim): class VariableProperty: """Class to represent a single property of a metadata header entry >>> VariableProperty('local_name', str) #doctest: +ELLIPSIS - <__main__.VariableProperty object at ...> + >>> VariableProperty('standard_name', str) #doctest: +ELLIPSIS - <__main__.VariableProperty object at ...> + >>> VariableProperty('long_name', str) #doctest: +ELLIPSIS - <__main__.VariableProperty object at ...> + >>> VariableProperty('units', str) #doctest: +ELLIPSIS - <__main__.VariableProperty object at ...> + >>> VariableProperty('dimensions', list) #doctest: +ELLIPSIS - <__main__.VariableProperty object at ...> + >>> VariableProperty('type', str) #doctest: +ELLIPSIS - <__main__.VariableProperty object at ...> + >>> VariableProperty('kind', str) #doctest: +ELLIPSIS - <__main__.VariableProperty object at ...> + >>> VariableProperty('state_variable', str, valid_values_in=['True', 'False', '.true.', '.false.' ], optional_in=True, default_in=False) #doctest: +ELLIPSIS - <__main__.VariableProperty object at ...> + >>> VariableProperty('intent', str, valid_values_in=['in', 'out', 'inout']) #doctest: +ELLIPSIS - <__main__.VariableProperty object at ...> + >>> VariableProperty('optional', str, valid_values_in=['True', 'False', '.true.', '.false.' ], optional_in=True, default_in=False) #doctest: +ELLIPSIS - <__main__.VariableProperty object at ...> + >>> VariableProperty('local_name', str).name 'local_name' >>> VariableProperty('standard_name', str).ptype == str @@ -763,31 +763,41 @@ class VarCompatObj: character(len=) # Test that we can create a standard VarCompatObj object + >>> from parse_tools import init_log, set_log_to_null + >>> _DOCTEST_LOGGING = init_log('var_props') + >>> set_log_to_null(_DOCTEST_LOGGING) + >>> _DOCTEST_RUNENV = CCPPFrameworkEnv(_DOCTEST_LOGGING, \ + ndict={'host_files':'', \ + 'scheme_files':'', \ + 'suites':''}, \ + kind_types=["kind_phys=REAL64", \ + "kind_dyn=REAL32", \ + "kind_host=REAL64"]) >>> VarCompatObj("var_stdname", "real", "kind_phys", "m", [], \ "var1_lname", "var_stdname", "real", "kind_phys", \ "m", [], "var2_lname", _DOCTEST_RUNENV) #doctest: +ELLIPSIS - <__main__.VarCompatObj object at 0x...> + # Test that a 2-D var with no horizontal transform works >>> VarCompatObj("var_stdname", "real", "kind_phys", "m", \ ['horizontal_dimension'], "var1_lname", "var_stdname", \ "real", "kind_phys", "m", ['horizontal_dimension'], \ "var2_lname", _DOCTEST_RUNENV) #doctest: +ELLIPSIS - <__main__.VarCompatObj object at 0x...> + # Test that a 2-D var with a horizontal transform works >>> VarCompatObj("var_stdname", "real", "kind_phys", "m", \ ['horizontal_dimension'], "var1_lname", "var_stdname", \ "real", "kind_phys", "m", ['horizontal_loop_extent'], \ "var2_lname", _DOCTEST_RUNENV) #doctest: +ELLIPSIS - <__main__.VarCompatObj object at 0x...> + # Test that a 2-D var with unit conversion m->km works >>> VarCompatObj("var_stdname", "real", "kind_phys", "m", \ ['horizontal_dimension'], "var1_lname", "var_stdname", \ "real", "kind_phys", "km", ['horizontal_dimension'], \ "var2_lname", _DOCTEST_RUNENV) #doctest: +ELLIPSIS - <__main__.VarCompatObj object at 0x...> + # Test that a 2-D var with unit conversion m->km works and that it # produces the correct forward transformation @@ -1012,6 +1022,26 @@ def _get_kind_convstrs(self, var1_kind, var2_kind, run_env): If a conversion is required, return a tuple with the two kinds, i.e., (var1_kind, var2_kind). + # Initial setup + >>> from parse_tools import init_log, set_log_to_null + >>> _DOCTEST_LOGGING = init_log('var_props') + >>> set_log_to_null(_DOCTEST_LOGGING) + >>> _DOCTEST_RUNENV = CCPPFrameworkEnv(_DOCTEST_LOGGING, \ + ndict={'host_files':'', \ + 'scheme_files':'', \ + 'suites':''}, \ + kind_types=["kind_phys=REAL64", \ + "kind_dyn=REAL32", \ + "kind_host=REAL64"]) + >>> _DOCTEST_CONTEXT1 = ParseContext(linenum=3, filename='foo.F90') + >>> _DOCTEST_CONTEXT2 = ParseContext(linenum=5, filename='bar.F90') + >>> _DOCTEST_VCOMPAT = VarCompatObj("var_stdname", "real", "kind_phys", \ + "m", [], "var1_lname", "var_stdname", \ + "real", "kind_phys", "m", [], \ + "var2_lname", _DOCTEST_RUNENV, \ + v1_context=_DOCTEST_CONTEXT1, \ + v2_context=_DOCTEST_CONTEXT2) + # Try some kind conversions >>> _DOCTEST_VCOMPAT._get_kind_convstrs('kind_phys', 'kind_dyn', \ _DOCTEST_RUNENV) @@ -1046,6 +1076,26 @@ def _get_unit_convstrs(self, var1_units, var2_units): for transforming a variable in to / from a variable in . + # Initial setup + >>> from parse_tools import init_log, set_log_to_null + >>> _DOCTEST_LOGGING = init_log('var_props') + >>> set_log_to_null(_DOCTEST_LOGGING) + >>> _DOCTEST_RUNENV = CCPPFrameworkEnv(_DOCTEST_LOGGING, \ + ndict={'host_files':'', \ + 'scheme_files':'', \ + 'suites':''}, \ + kind_types=["kind_phys=REAL64", \ + "kind_dyn=REAL32", \ + "kind_host=REAL64"]) + >>> _DOCTEST_CONTEXT1 = ParseContext(linenum=3, filename='foo.F90') + >>> _DOCTEST_CONTEXT2 = ParseContext(linenum=5, filename='bar.F90') + >>> _DOCTEST_VCOMPAT = VarCompatObj("var_stdname", "real", "kind_phys", \ + "m", [], "var1_lname", "var_stdname", \ + "real", "kind_phys", "m", [], \ + "var2_lname", _DOCTEST_RUNENV, \ + v1_context=_DOCTEST_CONTEXT1, \ + v2_context=_DOCTEST_CONTEXT2) + # Try some working unit transforms >>> _DOCTEST_VCOMPAT._get_unit_convstrs('m', 'mm') ('1.0E+3{kind}*{var}', '1.0E-3{kind}*{var}') @@ -1098,20 +1148,40 @@ def _get_dim_transforms(self, var1_dims, var2_dims): The reverse dimension transformation is a permutation of the indices of the second variable to the first. + # Initial setup + >>> from parse_tools import init_log, set_log_to_null + >>> _DOCTEST_LOGGING = init_log('var_props') + >>> set_log_to_null(_DOCTEST_LOGGING) + >>> _DOCTEST_RUNENV = CCPPFrameworkEnv(_DOCTEST_LOGGING, \ + ndict={'host_files':'', \ + 'scheme_files':'', \ + 'suites':''}, \ + kind_types=["kind_phys=REAL64", \ + "kind_dyn=REAL32", \ + "kind_host=REAL64"]) + >>> _DOCTEST_CONTEXT1 = ParseContext(linenum=3, filename='foo.F90') + >>> _DOCTEST_CONTEXT2 = ParseContext(linenum=5, filename='bar.F90') + >>> _DOCTEST_VCOMPAT = VarCompatObj("var_stdname", "real", "kind_phys", \ + "m", [], "var1_lname", "var_stdname", \ + "real", "kind_phys", "m", [], \ + "var2_lname", _DOCTEST_RUNENV, \ + v1_context=_DOCTEST_CONTEXT1, \ + v2_context=_DOCTEST_CONTEXT2) + # Test simple permutations >>> _DOCTEST_VCOMPAT._get_dim_transforms(['horizontal_dimension', \ 'vertical_layer_dimension'], \ ['vertical_layer_dimension', \ 'horizontal_dimension']) \ #doctest: +ELLIPSIS - <__main__.DimTransform object at 0x...> + >>> _DOCTEST_VCOMPAT._get_dim_transforms(['horizontal_dimension', \ 'vertical_layer_dimension', \ 'xdim'], \ ['vertical_layer_dimension', \ 'horizontal_dimension', \ 'xdim']) #doctest: +ELLIPSIS - <__main__.DimTransform object at 0x...> + >>> _DOCTEST_VCOMPAT._get_dim_transforms(['horizontal_dimension', \ 'vertical_layer_dimension', \ 'xdim'], \ @@ -1119,7 +1189,7 @@ def _get_dim_transforms(self, var1_dims, var2_dims): 'horizontal_dimension', \ 'vertical_layer_dimension']) \ #doctest: +ELLIPSIS - <__main__.DimTransform object at 0x...> + # Test some mismatch sets >>> _DOCTEST_VCOMPAT._get_dim_transforms(['horizontal_dimension', \ @@ -1323,30 +1393,3 @@ def __bool__(self): return self.equiv ############################################################################### -if __name__ == "__main__": - # pylint: disable=ungrouped-imports - import doctest - import sys - from parse_tools import init_log, set_log_to_null - # pylint: enable=ungrouped-imports - _DOCTEST_LOGGING = init_log('var_props') - set_log_to_null(_DOCTEST_LOGGING) - _DOCTEST_RUNENV = CCPPFrameworkEnv(_DOCTEST_LOGGING, - ndict={'host_files':'', - 'scheme_files':'', - 'suites':''}, - kind_types=["kind_phys=REAL64", - "kind_dyn=REAL32", - "kind_host=REAL64"]) - _DOCTEST_CONTEXT1 = ParseContext(linenum=3, filename='foo.F90') - _DOCTEST_CONTEXT2 = ParseContext(linenum=5, filename='bar.F90') - _DOCTEST_VCOMPAT = VarCompatObj("var_stdname", "real", "kind_phys", - "m", [], "var1_lname", "var_stdname", - "real", "kind_phys", "m", [], - "var2_lname", _DOCTEST_RUNENV, - v1_context=_DOCTEST_CONTEXT1, - v2_context=_DOCTEST_CONTEXT2) - OPTIONS = doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE - fail, _ = doctest.testmod(optionflags=OPTIONS) - sys.exit(fail) -# end if diff --git a/test/advection_test/cld_ice.F90 b/test/advection_test/cld_ice.F90 index a7da57e5..9c1e769a 100644 --- a/test/advection_test/cld_ice.F90 +++ b/test/advection_test/cld_ice.F90 @@ -19,7 +19,7 @@ MODULE cld_ice !> \section arg_table_cld_ice_run Argument Table !! \htmlinclude arg_table_cld_ice_run.html !! - subroutine cld_ice_run(ncol, timestep, temp, qv, ps, cld_ice_array, & + subroutine cld_ice_run(ncol, timestep, temp, qv, ps, cld_ice_array, & errmsg, errflg) integer, intent(in) :: ncol diff --git a/test/run_doctest.sh b/test/run_doctest.sh deleted file mode 100755 index aeecb133..00000000 --- a/test/run_doctest.sh +++ /dev/null @@ -1,35 +0,0 @@ -#! /bin/bash - -root=$( dirname $( cd $( dirname ${0}); pwd -P ) ) -scripts=${root}/scripts - -perr() { - # Print error message ($2) on error ($1) - if [ ${1} -ne 0 ]; then - echo "ERROR: ${2}" - if [ $# -gt 2 ]; then - exit ${3} - else - exit 1 - fi - fi -} - -cd ${scripts} -perr $? "Cannot cd to scripts directory, '${scripts}'" - -errcnt=0 - -export PYTHONPATH="${scripts}:${PYTHONPATH}" -# Find all python scripts that have doctest -for pyfile in $(find . -name \*.py); do - if [ -f "${pyfile}" ]; then - if [ $(grep -c doctest ${pyfile}) -ne 0 ]; then - python3 ${pyfile} - res=$? - errcnt=$((errcnt + res)) - fi - fi -done - -exit ${errcnt} diff --git a/test/run_tests.sh b/test/run_fortran_tests.sh similarity index 58% rename from test/run_tests.sh rename to test/run_fortran_tests.sh index 97001d30..8b0f5bcb 100755 --- a/test/run_tests.sh +++ b/test/run_fortran_tests.sh @@ -38,33 +38,23 @@ if [ $res -ne 0 ]; then fi # Run var_action test -./var_action_test/run_test -res=$? -errcnt=$((errcnt + res)) -if [ $res -ne 0 ]; then - echo "Failure running var_action test" -fi - -# Run doctests -./run_doctest.sh -res=$? -errcnt=$((errcnt + res)) -if [ $res -ne 0 ]; then - echo "${errcnt} doctest failures" -fi - -for test in `ls unit_tests/test_*.py`; do - echo "Running unit test, ${test}" - python3 ${test} - res=$? - errcnt=$((errcnt + res)) - if [ $res -ne 0 ]; then - echo "Failure, '${res}', running unit test, ${test}" - fi -done +# TODO: Re-enable after feature fully implemented. +# ./var_action_test/run_test +# res=$? +# errcnt=$((errcnt + res)) +# if [ $res -ne 0 ]; then +# echo "Failure running var_action test" +# fi +echo "Skipping var_action_test/run_test until feature is fully implemented" if [ $errcnt -eq 0 ]; then echo "All tests PASSed!" else - echo "${errcnt} tests FAILed" + if [ $errcnt -eq 1 ]; then + echo "${errcnt} test FAILed" + else + echo "${errcnt} tests FAILed" + fi + #Exit with non-zero exit code + exit 1 fi diff --git a/test/unit_tests/test_metadata_scheme_file.py b/test/unit_tests/test_metadata_scheme_file.py index 52f62aa1..28b2ee50 100644 --- a/test/unit_tests/test_metadata_scheme_file.py +++ b/test/unit_tests/test_metadata_scheme_file.py @@ -40,7 +40,7 @@ Command line arguments: none - Usage: python test_metadata_scheme_file.py # run the unit tests + Usage: python3 test_metadata_scheme_file.py # run the unit tests ----------------------------------------------------------------------- """ import sys @@ -283,5 +283,5 @@ def test_CCPPeq1_var_missing_in_meta(self): # pylint: enable=invalid-name -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() diff --git a/test/unit_tests/test_metadata_table.py b/test/unit_tests/test_metadata_table.py index d9791879..3a01f98b 100755 --- a/test/unit_tests/test_metadata_table.py +++ b/test/unit_tests/test_metadata_table.py @@ -8,7 +8,7 @@ Command line arguments: none - Usage: python test_metadata_table.py # run the unit tests + Usage: python3 test_metadata_table.py # run the unit tests ----------------------------------------------------------------------- """ import sys @@ -394,5 +394,6 @@ def test_invalid_table_properties_type(self): emsg = "Invalid metadata table type, 'banana', at " self.assertTrue(emsg in str(context.exception)) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() + diff --git a/test/unit_tests/test_var_transforms.py b/test/unit_tests/test_var_transforms.py index 05087d13..ae71008f 100644 --- a/test/unit_tests/test_var_transforms.py +++ b/test/unit_tests/test_var_transforms.py @@ -432,5 +432,6 @@ def test_valid_dim_transforms(self): expected = f"{v5_lname}({lind_str}) = {v4_lname}({rind_str})" self.assertEqual(rev_stmt, expected) -if __name__ == '__main__': +if __name__ == "__main__": unittest.main() + diff --git a/tests/test_metadata_parser.py b/tests/test_metadata_parser.py index 0f7d18d6..febc3d93 100644 --- a/tests/test_metadata_parser.py +++ b/tests/test_metadata_parser.py @@ -51,7 +51,7 @@ def test_MetadataTable_parse_table(tmpdir): assert len(metadata_header.sections()) == 1 metadata_section = metadata_header.sections()[0] assert metadata_section.name == "" - assert metadata_section.type == "scheme" + assert metadata_section.ptype == "scheme" (im_data,) = metadata_section.variable_list() assert isinstance(im_data, Var) assert im_data.get_dimensions() == []