flibs/ftnunit - Unit testing
TABLE OF CONTENTS
SYNOPSIS
DESCRIPTION
ROUTINES
GENERATING TESTS FROM A TABLE
TODO
RELATED WORK
COPYRIGHT
JUnit is a well-known facility for defining and running unit tests in Java programs. The ftnunit framework was inspired by that facility. It is not as good-looking as JUnit, by no means:
program myprog ... ! ! The routine runtests will check if unit tests are requested ! If not, it will return immediately. This way we make sure ! the unit tests remain part of the program. ! ! The routine test_all runs all unit tests ! (see the dataproc_testing module) ! call runtests( test_all ) ! ! Ordinary processing ! ... end program |
subroutine test_all call test( test_no_file, "Read non-existent file" ) call test( test_empty_file, "Read an empty file" ) call test( test_invalid_file, "Read an invalid file" ) call test( test_ordinary_file, "Read an ordinary file" ) end subroutine test_all |
subroutine test_no_file integer :: nodata real :: vmean, vmin, vmax call ftnunit_remove_file( 'no_such_file' ) call write_name( 'no_such_file' ) call open_files call process_data( nodata, vmean, vmax, vmin ) call assert_true( nodata == 0, "No data read" ) end subroutine test_no_file |
Test: Read non-existent file Test: Read an empty file Test: Read an invalid file forrtl: severe (59): list-directed I/O syntax error, unit 11, file c:\arjen\flibs\tests\ftnunit\invalid_file Image PC Routine Line Source test_ftnunit.exe 004151B9 Unknown Unknown Unknown test_ftnunit.exe 00415017 Unknown Unknown Unknown test_ftnunit.exe 004141F4 Unknown Unknown Unknown test_ftnunit.exe 00414629 Unknown Unknown Unknown test_ftnunit.exe 00409C05 Unknown Unknown Unknown test_ftnunit.exe 004095FB Unknown Unknown Unknown test_ftnunit.exe 0040144B Unknown Unknown Unknown test_ftnunit.exe 00401FE9 Unknown Unknown Unknown test_ftnunit.exe 00401A2C Unknown Unknown Unknown test_ftnunit.exe 00401BB3 Unknown Unknown Unknown test_ftnunit.exe 0040294A Unknown Unknown Unknown test_ftnunit.exe 0040232E Unknown Unknown Unknown test_ftnunit.exe 0044A1E9 Unknown Unknown Unknown test_ftnunit.exe 00433519 Unknown Unknown Unknown kernel32.dll 7C816D4F Unknown Unknown Unknown Incrementally linked image--PC correlation disabled. Test: Read an ordinary file Number of failed assertions: 0 Number of runs needed to complete the tests: 3 |
The module ftnunit contains the following subroutines and functions:
abs( v1 - v2 ) < margin * (abs(v1)+abs(v2)) / 2 |
The Tcl program "gentabletest.tcl" reads the test specifications from an input file and generates a complete Fortran program. The ideas from Bil Kleb's "Toward Scientific Numerical Modeling" ftp://ftp.rta.nato.int/PubFullText/RTO/MP/RTO-MP-AVT-147/RTO-MP-AVT-147-P-17-Kleb.pdf were used for the set-up.
To do: provide a detailed description. For the moment: see example.tbl, including below.
! Example of generating test code via a table ! ------------------------------------------- ! The routine to be tested determines the minimum oxygen concentration ! in a river, based on the Streeter-Phelps model: ! ! dBOD/dt = -k * BOD ! ! dO2/dt = -k * BOD + ka * (O2sat-O2) / H ! ! where ! BOD - biological oxygen demand (mg O2/l) ! O2 - oxygen concentration (mg O2/l) ! O2sat - saturation concentration of oxygen (mg O2/l) ! k - decay rate of BOD (1/day) ! ka - reareation rate of oxygen (m/day) ! H - depth of the river ! ! We need boundary (initial) conditions for BOD and oxygen and ! the equations describe the concentrations of BOD and oxygen in a ! packet of water as it flows along the river. ! ! Note: ! It is a very simple model, it is not meant as a realistic ! representation. ! ! The routine simply continues the solution until a minimum is found. ! The results are: oxymin and time ! ! ! The keyword DECLARATIONS introduces the declarations we need for the ! complete generated code ! DECLARATIONS use streeter_phelps real :: bod, oxy real :: k, ka, h, oxysat, dt, oxymin, time ! ! The keyword CODE introduces the code fragment required to run the ! routine or routines. The results and possible checking of error ! conditions are separated. ! CODE call compute_min_oxygen( bod, oxy, k, ka, h, oxysat, dt, oxymin, time ) ! ! The keyword RESULT indicates which arguments/variables hold the ! interesting results. Specify one name per line (you can not currently ! use array elements) and the allowed margin (taken as absolute, if ! followed by "%" as a percentage) ! RESULT oxymin 0.001 ! Minimum oxygen concentration time 0.01% ! Time the minimum is reached ! ! The keyword ERROR is used for a code fragment that checks if the ! routine has correctly found an error in the input (that is, some ! parameter value is out of range). The code is invoked when any of ! result variables in a table entry has the keyword ERROR instead of ! a proper value. ! Use the subroutine "error" to indicate the correctly reported error ! condition. ! ERROR if ( time == -999.0 ) then call error endif ! ! The keyword RANGES specifies that the variables are to be taken ! from a uniform or a normal distribution. The generated program will ! simply select values at random and run the code with them. The report ! consists of the detailed output as well as a summary. ! RANGES oxy 10.0 2.0 Uniform ! Name of the variable, the mean and the margin (uniform) ! Normal: mean and standard deviation followed by Normal ! Note: all parameters must be given! ! ! The keyword TABLE indicates the beginning of a table of input data and ! expected values. The first (non-comment) line contains the names of ! the variables as used in the code fragments and all others are the ! values expected. ! ! There are two special values: ! ? - indicating an unknown value for result variables and a "do not ! care" value for input variables ! It is useful to generate a table that does contain the (computed) ! results (see the file table.out) or to indicate situations ! where one or more input variables are out of range and this ! should lead to an error ! ERROR - indicating that the entry should cause the routine to be ! tested to flag an error condition. ! TABLE dt oxy bod oxysat h k ka oxymin time 0.1 10 1 10 10 0.1 1.0 10.0 2.0 1.0 10 1 10 10 0.1 1.0 ? ? ! ! This case is unacceptable: time step must be positive 0.0 ? ? ? ? ? ? ? ERROR 1.0 0. 10 10 10 0.1 1.0 ? ? |
The following things are still left to do:
There are at least two similar initiatives with regard to a unit testing framework for Fortran:
Copyright © 2006 Arjen Markus <arjenmarkus@sourceforge.net>