Goddard-Fortran-Ecosystem / pFUnit

Parallel Fortran Unit Testing Framework
Other
173 stars 45 forks source link
fortran mpi object-oriented unit-testing-framework

pFUnit 4.0

pFUnit is a unit testing framework enabling JUnit-like testing of serial and MPI-parallel software written in Fortran. Limited support for OpenMP is also provided in the form of managing exceptions in a thread-safe manner.

pFUnit uses several advanced Fortran features, especially object oriented capabilities, to offer a convenient, lightweight mechanism for Fortran developers to create and run software tests that specify the desired behavior for a given piece of code.

This framework was originally created by developers from NASA and NGC TASC.

Table of contents

  1. Prerequisites
  2. Obtaining pFUnit
  3. What's in the directory?
  4. Building and installing pFUnit
  5. Using pFUnit in your application
  6. Command line options
  7. Incompatibilities with pFUnit 3
  8. Acknowledgments
  9. Revisions

Prerequisites

pFUnit is has been ported to Linux and Apple OS X. Users have also contributed support for Windows/CYGWIN, but please note that updates are not regularly verified in that environment.

Due to the heavy use of F2003 object oriented features and a smattering of F2008 features, only relatively recent Fortran compilers are able to correctly build pFUnit. The list below is not comprehensive, and earlier compilers may work for some user code.

Doxygen was used to generate documention for pFUnit 3, but is not being maintained. My intent instead is to leverage the GitHub wiki to better maintain features.

Note that support for Python 2.7 my soon disappear.

Obtaining pFUnit

The best way to obtain pFUnit is to clone the git repository from GitHub as follows:

git clone https://github.com/Goddard-Fortran-Ecosystem/pFUnit.git

This will create the directory pFUnit in the current working directory.

You can download the latest version as a tarball from the release page, and extract it like:

$ tar zxf ./pFUnit-*.tar.gz

which will place the pFUnit files into a directory called pFUnit-<version>, where <version> is the version number.

For other ways to acquire the code visit

https://github.com/Goddard-Fortran-Ecosystem/pFUnit/

or contact the pFUnit team.

*Note: pFUnit uses 3 other open source packages via git submodules. These are automatically downloaded during the build process if not detected. But this means that a default pFUnit clone must be built in an environment connected to the internet. If the --recursive option is used for the clone, then an internet connection should not be necessary.

The other consequence of this is that the GitHub autogenerated release tar balls do not contain the submodules at all. I generally try to provide comprehensive tar balls alongside the GitHub generated ones, but it is apparently impossible to delete the automatic ones.*

What's in the directory?

In the top level of the pFUnit distribution you will see the following files.

Building and installing pFUnit

pFUnit is now exclusively built and installed via CMake. Very little needs to be done to configure the build, however some care must be taken so that CMake detects the Fortran compiler that you want to use:

Note that pFUnit 4.0 handles MPI support differently than for 3.0. Previously one explicitly built and installed pFUnit separately for serial and parallel configurations. 4.0 instead builds and installs both with a separate library for the MPI features. E.g., a serial application now links to libfunit.a, while a parallel application links to libpfunit.a and libfunit.a.

CMake options:

The process for building pFUnit using CMake is as follows. In the top directory of the distribution make a new directory to support the build, then change to that directory and run cmake (pointing back to the source) to generate the required makefiles.

$ mkdir build
$ cd build
$ cmake ..
$ make tests
$ make install

By default, pFUnit will put the installation in a subdirectory called installed inside the build directory. This unusual default (from a CMake perspective) is due to the fact that many/most pFUnit users lack elevated priviliges for installing in the usual places. Most users will want to explicitly override the default with CMake's -DCMAKE_INSTALL_PREFIX=...

Note that cmake allows a few variants on the internal structure of the install, and future versions of pFUnit are likely to switch to a different variant. (find_package(pFUnit) should continue to work, but there may be issues with the search order for users with conflicting installs.)

Using pFUnit

Please see https://github.com/Goddard-Fortran-Ecosystem/pFUnit_demos for more details.

Using pFUnit in a CMake project

First, one must tell CMake where to find your installation of pFUnit. Typically this looks like:

$ cmake .. -DCMAKE_PREFIX_PATH=<path-to-pfunit-install>

Next, within your CMakeLists.txt, enable pFUnit with the lines:

find_package(PFUNIT REQUIRED)
enable_testing()

Then, for each test suite, use the add_pfunit_ctest macro. E.g.,

add_pfunit_ctest (my_tests
  TEST_SOURCES ${test_srcs}
  LINK_LIBRARIES sut # your application library
  )

The make step should then produce a test executable. In the example above it would be my_tests. To run:

$ ./my_tests

Using pFUnit in a GNU make project

Somewher in your Makefile you should add the lines

include $(PFUNIT_DIR)/PFUNIT-4.0/include/PFUNIT.mk
FFLAGS += $(PFUNIT_EXTRA_FFLAGS)

Note that the path to PFUNIT.mk may change in the future.

Then, for each test suite, specify a set of make variables prefixed by your test suite name, and invoke the make_pfunit_test function. E.g.:

my_tests_TESTS := test_square.pf
my_tests_REGISTRY :=
my_tests_OTHER_SOURCES :=
my_tests_OTHER_LIBRARIES := -L. -lsut
my_tests_OTHER_INCS :=

$(eval $(call make_pfunit_test,my_tests))

Then to build and execute:

make all
./my_tests

Command Line Options

The executable test program provides several command line options, when "include/driver.F90" is used, as it is automatically when using the pFUnit preprocessor.

-h or --help                    Prints this help message
-d or -debug or --verbose       Provide debugging information.  Useful when a test crashes.
-f or --filter <pattern>        Only run tests that match the specified substring
-h or --help                    Print help message.
-o or --output <outputfile>     Direct pFUnit messages to a file.
-r or --runner <runner>         Specify a non default test runner. (Advanced)
-s or -skip  <n>                Used internally.

For example to run all tests whose names start with "test_ABC":

$ ./tests.x -f  test_ABC

Incompatibilities with pFUnit 3

Note: this list is known to be incomplete - a work in progress

Acknowledgments

Thanks to the following for their review and comments: B. Van Aartsen, T. Clune.

REVISIONS TO THIS DOCUMENT