Skip to content
/ f90tw Public

Fortran wrappers for a limitted subset of the Boost.Test and googletest frameworks functionality.

License

Notifications You must be signed in to change notification settings

loudove/f90tw

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

f90tw

f90tw project provides fortran wrappers for a limited subset of the boost and google test frameworks functionality. At the same time, offers a rather simple mechanism for setting up and managing test suites in fortran projects. All the way down, f90tw implementation follows a preprocessor-based approach. The motivation was to utilize already available test frameworks and assertions implementation with minimal effort.

Build

You will need to obtain the repository from github and follow the usual cmake build steps. It is assumed that a) c/c++ and fortran compilers are available and, b) you have installed boost and gtest packages. In short, clone the project from github, enter the project's directory and issue the usual cmake build commands. On linux boxes, the flow of commands looks like:

% git clone https://github.com/loudove/f90tw
% cd f90tw
% mkdir build
% cd build
% cmake -DBOOSTFWK=OFF -DGTESTFWK=ON ..
% make

Using the cmake options BOOSTFWK and GTESTFWK you can select the framework to be used. BOOSTFWK is ON by default. Moreover, options TESTS and EXAMPLES controls the build of f90tw tests and examples.

There is not specific installation directory. After a successful build, the module files and the libraries will be located under the <build>/f90tw/ directory (or <build>/f90tw/<conf> on windows). The actual source files of the modules will be located in the <build>/f90tw directory with the names assertions_boost.f90 and assertion_gtest.f90 for the boost and gtest frameworks respectively. You can use fprettify to format them properly in order to inspect them.

If TESTS or EXAMPLES option are ON, the corresponding target executable will be placed in corresponding build folder (<build>/tests/<conf> and <build>/examples/<conf> respectively).

Use

A fortran module with the interface of the fortran wrappers and the corresponding libraries with the actual functionality are provided for each test framework:

  • Boost: assertions_boost module (implementable in assertions_boost.fpp), libf90tw_boost.a library (implemented in boost_assertions.cpp). After a successful build a "readable" code for the module can be found in <build>/f90tw/assertions_boost.f90.
  • Gtest: assertions_gtest module (implemented in assertions_gtest.fpp), libf90tw_gtest.a library (implemented in gtest_assertions.cpp). Also in this case, after a successful build a "readable" code for the module will be located in <build>/f90tw/ftest_boost.f90.

If you include f90tw in your cmake project, the variables f90tw_INCLUDE_DIR (pointing to the heads directory) and f90tw_MODULE_DIR (pointing to the modules and libraries directory) are defined to help you access f90tw functionality. You can find hinds of f90tw use with cmake in examples/CMakeLists.txt. The variables FPP_EXE (preprocessor), FPP_ID (preprocessor id), FPP_OPTIONS (preprocessor options) and FPP_SWITCH (preprocessor options's switch) are also exposed allowing improved flexibility.

To facilitate the setup of simple tests, additional functionality is provided and demonstrated in the accompanying examples found in the example directory. A detailed walk-through of the implementation of the examples can be found here.

Assuming that you want to test the functionality of a fortran module named example, implemented in example.f90. The test can be implemented with a pair of files, using either preprocessor macros or directives.

  • Boost: this is an example of preprocessor macros approach. A fortran module, (test_example_boost.fpp), with the subroutines implementing the actual tests and its c/c++ pair, test_example_boost.cpp, implementing the boost tests wrapping their fortran counterparts.
  • Gtest: this is an example of process directives approach.Also in this case, a fortran module test_example_gtest.fpp implements the tests and test_example_gtest.cpp their c/c++ wrappers. PLEASE NOTE that these files should be compiled/preprocessed by setting the USE GTEST preprocessor definition in order to avoid problems.

Preprocessor macros

In the fortran code file, we first include the header "f90tw_test.h" and then, we implemented the test module with the help of f90tw preprocessor macros:

  • TESTMODULE( MODULENAME, MODULETOTEST): (optional) prepares the initial statements of the module(module declaration, use of the module to be tested and set implicit none).

    • MODULENAME: the name of the module
    • MODULETOTEST: the name of the module to test
  • TESTCONTAINS: (optional) expands to fortran contain statement. It is separated from TESTMODULE macro to allow for the declaration of module resources common to all tests.

  • TESTCODE( TESTTYPE, TESTSUITENAME, TESTNAME, SUBNAME, ... ): prepares the specific test.

    • TESTTYPE: the framework macro to be used for test declaration
    • TESTSUITENAME: the name of the test suite
    • TESTNAME: the name of the test
    • SUBNAME: the name of the fortran subroutine to be implemented
    • ... : the rest of the arguments which are essentially, the fortran source code implementing the test. PLEASE NOTE that each code line should be terminated with ";". The use of pound character ("#") in fortran string renders preprocessing impossible, while, in order to avoid similar catastrophic errors, the string concatenation operator (//) should be replaced with the F90CONCAT macro and the line continuation operator (&) with the F90LNCONT macro. Moreover, F90SPOT macro expands to the filename:line string, while F90SPOTMSG(MSG) macro appends the MSG string to it. You can simplify the implementation by just calling a fortran method implemented elsewhere. This approach is maybe preferable since you will avoid the drawbacks of preprocessing relevant to code's clarity and debugging.
  • ENDTESTMODULE(MODULENAME) : (optional) module end statement.

    • MODULENAME: the name of the module (the same with the one used with with TESTMODULE macro).

Using this approach, the c++ implementation becomes rather fast and easy since it is based on preprocessing the same fortran file, with different definitions of the macros resulting automatically in a) the declarations of the fortran test methods and b) the framework tests which essentially wrap these methods. A more detailed description of the fortran and c/c++ files is provided here.

Directives

An alternative approach is to implement the test using standard fortran (see test_example_gtest.f90) and the !$f90tw directive ([!cC]\$[fF]90[tT][wW]] in regular expression) to indicate the test cases i.e. the subroutines to be wrapped. Essentially, the lines with the directives will be extracted and included in the c/c++ counterpart ((see test_example_gtest.cpp)) in order to create the test suite. A more detailed description of the fortran and c/c++ files is provided here.

Assertions tests

In addition to the assertion wrappers for boost.test and gtest, a method for accessing f90tw version is available:

  • f90tw_version(major, minor, patch)
    • major : major version
    • minor : minor version
    • patch : patch version

Boost.test assertions tests

The following subset of boost.test framework is supported with <level> = (WARN|CHECK|REQUIRE) :

Fortran (F90_<C/C++>) operator argumens type
F90_BOOST_<level>_<operator> MESSAGE (*) logical(KIND=(C_BOOL|4)),
integer(KIND=C_INT)
F90_BOOST_<level>_<operator> BITWISE_EQUAL (*) integer(KIND=C_INT)
F90_BOOST_<level>_<operator> (EQUAL|NE) logical(KIND=(C_BOOL|4)),
integer(KIND=C_INT),
real(KIND=C_FLOAT),
real(KIND=C_DOUBLE)
F90_BOOST_<level>_<operator> (CLOSE|CLOSE_FRACTION) (*) real(KIND=C_FLOAT),
real(KIND=C_DOUBLE)
F90_BOOST_<level>_<operator> SMALL real(KIND=C_FLOAT),
real(KIND=C_DOUBLE)
F90_BOOST_<level>_<operator> (GE|GT|LE|LT) integer(KIND=C_INT),
real(KIND=C_FLOAT),
real(KIND=C_DOUBLE)
F90_BOOST_TEST_MESSAGE - character(KIND=C_CHAR,LEN=*)
F90_BOOST_TEST_ERROR - character(KIND=C_CHAR,LEN=*)
F90_BOOST_TEST_FAIL - character(KIND=C_CHAR,LEN=*)
F90_BOOST_TEST_CHECKPOINT - character(KIND=C_CHAR,LEN=*)
F90_BOOST_TEST_INFO - character(KIND=C_CHAR,LEN=*)
F90_BOOST_TEST_INFO_SCOPE - character(KIND=C_CHAR,LEN=*)
F90_BOOST_TEST_CONTEXT - character(KIND=C_CHAR,LEN=*)
F90_BOOST_TEST_PASSPOINT - character(KIND=C_CHAR,LEN=*)

For more details please check the Boost.Test documentation.

Gtest assertions tests

The following subset of gtest framework is supported with <level> : (ASSERT|EXPECT) :

Fortran (F90_<C/C++>) operator argumens type
F90_<level>_<operator> (EQ|NE) logical(KIND=(C_BOOL|4)),
integer(KIND=C_INT),
real(KIND=C_FLOAT),
real(KIND=C_DOUBLE)
F90_<level>_<operator> (GT|GE|LT|LE) integer(KIND=C_INT),
real(KIND=C_FLOAT),
real(KIND=C_DOUBLE)
F90_<level>_FLOAT_EQ (*) - real(KIND=C_FLOAT)
F90_<level>_DOUBLE_EQ (*) - real(KIND=C_DOUBLE)
F90_<level>_NEAR (*) - real(KIND=C_FLOAT),
real(KIND=C_DOUBLE)
F90_<level>_<operator> (TRUE|FALSE) (*) logical(KIND=(C_BOOL|4))
F90_<level>_<operator> (STREQ|STRNE|
STRCASEEQ|STRCASENE)
character(KIND=C_CHAR,LEN=*)

In the gtest case, all the assertion methods can be used with a message as the last argument (of type character(KIND=C_CHAR,LEN=*) ) in order to overwrite the default assertion message.

For more details please check the gtest documentation.

About

Fortran wrappers for a limitted subset of the Boost.Test and googletest frameworks functionality.

Resources

License

Stars

Watchers

Forks

Packages

No packages published