Contributing Guide
Introduction
The Case class is the core of the CIME Case Control system. All interactions with a case are performed through this class. The variables used to create and manipulate a case are defined in XML files, and for each XML file, there is a corresponding Python class to interact with it.
XML files that are part of the CIME distribution and are intended to be read-only with respect to a case are typically named config_something.xml. The corresponding Python class is named Something and can be found in the file CIME.XML.something.py. These are referred to as the CIME config classes.
XML files that are part of a case and thus are read/write to a case are typically named env_whatever.xml. The corresponding Python modules are CIME.XML.env_whatever.py, and the classes are named EnvWhatever. These are referred to as the Case env classes.
The Case class includes an array of the Case env classes. In the configure function and its supporting functions, the case object creates and manipulates the Case env classes by reading and interpreting the CIME config classes.
Testing
CIME splits its tests into two categories: unit and sys.
The unit category covers doctests and unit tests, while the sys category covers regression tests. Tests are named accordingly (e.g., unit tests: CIME/tests/test_unit*).
How to run the tests
There are two possible methods to run these tests.
Warning
scripts_regression_tests.py is deprecated and will be removed in the future.
pytest
CIME supports running tests using pytest. By using pytest coverage reports are automatically generated. pytest supports all the same arguments as scripts_regression_tests.py, see –help for details.
To get started install pytest and pytest-cov.
pip install -r test-requirements.txt
pip install pytest pytest-cov
Examples
Running all the sys and unit tests.
pytest
Running only sys tests, sys can be replaced with unit to run only unit testing.
pytest CIME/tests/test_sys.*
Running a specific test case.
pytest CIME/tests/test_unit_case.py
A specific test can be run with the following.
pytest CIME/tests/test_unit_case.py::TestCaseSubmit::test_check_case
scripts_regression_tests.py
The scripts_regression_tests.py script is located under CIME/tests.
You can pass either the module name or the file path of a test.
Examples
Running all the sys and unit tests.
python CIME/tests/scripts_regression_tests.py
Running only sys tests, sys can be replaced with unit to run only unit testing.
python CIME/tests/scripts_regression_tests.py CIME/tests/test_sys*
Runnig a specific test case.
python CIME/tests/scripts_regression_tests.py CIME.tests.test_unit_case
A specific test can be run with the following.
python CIME/tests/scripts_regression_tests.py CIME.tests.test_unit_case.TestCaseSubmit.test_check_case
Code Quality
To ensure code quality we require all code to be linted by pylint and formatted using black. We run a few other tools to check XML formatting, ending files with newlines and trailing white spaces.
To ensure consistency when running these checks we require the use of [pre-commit](https://pre-commit.com/).
Our GitHub actions will lint and check the format of each PR but will not automatically fix any issues. It’s up to the developer to resolve linting and formatting issues. We encourage installing pre-commit’s [Git hooks](#installing-git-hook-scripts) that will run these checks before code can be committed.
Installing pre-commit
pip install pre-commit
Running pre-commit
pre-commit run -a
Installing git hook scripts
If you install these scripts then pre-commit will automatically run on git commit.
pre-commit install
Docker container
CIME provides a container that the CI uses to run all the testing. This container
can also be used to test locally providing a reproducible environment. The
compiler is GNU and the MPI implementation is OpenMPI.
The image can be pulled from ghcr.io.
docker pull ghcr.io/esmci/cime:latest
or can be built locally. The build context needs to be set to the root of the CIME repository.
docker build -t ghcr.io/esmci/cime:latest -f docker/Dockerfile .
Running
The container does not provide any source, as such you will need to bind
mount the model+cime directory and define which model is being used. The
following example assumes the model is checked out in $SRC_PATH.
docker run -it --rm --hostname docker -e CIME_MODEL=e3sm -v ${SRC_PATH}:/root/model -v ./storage:/root/storage -v ./inputdata:/root/inputdata -w /root/E3SM/cime ghcr.io/esmci/cime:latest bash
This example will drop into a shell where CIME commands or tests can be run. The options are broken down below.
--hostname dockeris required to tell CIME which machine definition to use.-e CIME_MODEL=e3smdefines the model.-v ${SRC_PATH}:/root/E3SMpasses through the model source.-v ./inputdata:/root/inputdatapersistent input data.-v ./storage:/root/storagepersistent cases, baselines, timings, etc.-w /root/E3SM/cimeset the current working directory to CIME’s root.ghcr.io/esmci/cime:latestcontainer image.bashthe command to run in the container.
You can even run CIME or testing without a shell.
docker run -it --rm --hostname docker -e CIME_MODEL=e3sm -v ${SRC_PATH}:/root/model -v ./storage:/root/storage -w /root/E3SM/cime ghcr.io/esmci/cime:latest pytest CIME/tests/test_unit*
docker run -it --rm --hostname docker -e CIME_MODEL=e3sm -v ${SRC_PATH}:/root/model -v ./storage:/root/storage -w /root/E3SM/cime ghcr.io/esmci/cime:latest ./scripts/create_test SMS.f19_g16.S