M_framework__verify(3f) - [M_framework__verify::INTRO] unit test framework (LICENSE:PD)
Synopsis
Quote
Description
Procedures
Examples
Author
License
Module procedures
use M_framework, only : unit_test, unit_test_start, & unit_test_end, unit_test_stop, & unit_test_msg, unit_test_mode, & unit_test_system, & unit_test_expectedModule values
use M_framework, only : unit_test_level, unit_test_flags
Do not let your victories go to your head, nor let your failures go to your heart.
The M_framework(3f) module is a collection of Fortran routines for supporting code development by providing logging, error processing, debugging, comparison and unit testing procedures.The M_framework__verify(3f) module specifically brings together a few procedures for creating unit testing. It ...
o allows for a user-defined command to be called to collect results or produce mail alerts, or other custom bookkeeping operations. o supports easily composing a message from up to twenty scalar intrinsic values and different strings o allows stopping on failure or continuing o provides for a non-zero exit code if any tests fail o is designed for with integration with the fpm (Fortran Package Manager) "test" subcommand. If default modes need changed it can be done via the unit_test_mode(3f) procedure or as command line options.
messages by default are writing to stderr, but may be written to any list of LUNs of preassigned or open files.
Some of the most common options are
call unit_test_mode(command,keep_going,level,luns=[K,L,M,N,...])keep_going logical variable that can be used to turn on or off program termination on errors. luns array of Fortran LUNs to write messages to level An integer that can be used to specify different debug levels command name of optional command to execute for a start, check, or finish.
The unit test procedures are
unit_test_start() start tests of a procedure unit_test() report if expression is false or true and if .false. stop program when keep_going=.false. unit_test_end() ends test of a procedure unit_test_msg() write message unit_test_stop() stop program with exit value of 0 if no failures else with an exit value of 1 unit_test_system() execute system command, recursively if requested.The unit test short-cut procedures are
unit_test_expected() report if two values are equalFor custom unit testing reports, a command can be given that will be passed information on the command line in NAMELIST format.
This command is generally a script that makes entries for each unit, perhaps in an SQLite data file for example.
It might also send an email if a test fails in batch environments.
It could also convert the information to CSV for use in spreadsheets, or generate an HTML report, for example.
A sample command written in the bash(1) shell and using the sqlite3(1) command should be included in this distribution as an example.
The flexibility introduced by calling an external script or program is that the command can be changed as desired without changing the test programs.
The routines in M_framework__verify(3f) are often combined with other small modules such as Comparisons of real values can be done with a tolerance with M_Compare_Float_Numbers(3f) and M_framework__approx(3f). M_hashkeys(3f) routines and various math and statistical routines can be helpful to quickly create unit tests.
The intrinsics ANY(3f) and ALL(3f) are particularly useful in calls to unit_test(3f).
Sample program
!! program demo_M_framework__verify module M_framework__verify_demo private public one ! some regular routine public two ! some regular routine containsExpected output:subroutine one(array) integer,intent(out),allocatable :: array(:) array=[21,51,14,45] end subroutine one
subroutine two(array) integer,intent(inout),allocatable :: array(:) array=2*array end subroutine two
end module M_framework__verify_demo
program demo_M_framework__verify use M_framework, only: unit_test_start, unit_test, & & unit_test_end, unit_test_msg, unit_test_stop, & & unit_test_system, unit_test_mode use M_framework__verify_demo, only: one, two ! set-up call unit_test_mode(command=,flags=[0],keep_going=.true.) ! call a test procedure for each routine to test call test_one() call test_two() ! tear-down call unit_test_stop() contains
subroutine test_one() integer,allocatable :: results(:) integer,parameter :: expected(*)=[21,51,14,45] call unit_test_start(one) call one(results) call unit_test(one,all(expected>0), & & testing if everyone greater than zero) call unit_test(one,all(expected==results), & & testing if all values are expected) call unit_test_end(one,checks on "one" ended) end subroutine test_one
subroutine test_two integer,allocatable :: results(:) integer,parameter :: expected(*)=[2,20,200] results=[1,10,100] call two(results) call unit_test_start(two,check procedure "two" ) call unit_test(two, all(expected == results) .and. & & all(expected > 0) .and. maxval(expected) <201,msg=long expression) call unit_test_end(two,checks on "two" ended) end subroutine test_two
end program demo_M_framework__verify
check_start: one START : check: one SUCCESS : testing if everyone greater than zero check: one SUCCESS : testing if all values are expected check_end: one PASSED : GOOD: 2 BAD: 0 DURATION:00000001 check_start: two START : check: two SUCCESS : long expression check_end: two PASSED : GOOD: 1 BAD: 0 DURATION:00000000 check_stop: TALLY PASSED : GOOD: 3 BAD: 0 DURATION:00000001
John S. Urban
Public Domain
Nemo Release 3.1 | M_framework__verify (3) | February 23, 2025 |