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>