[UP]


Manual Reference Pages  - M_debug (3)

NAME

M_debug(3fm) - [M_debug] a collection of Fortran routines for supporting code development by providing error processing, debugging procedures and unit testing. (LICENSE:PD)

CONTENTS

Synopsis
Quote
Description
Examples
Author
License

SYNOPSIS

use M_debug, only : unit_check, unit_check_start, unit_check_good, unit_check_bad, unit_check_done use M_debug, only : unit_check_limit, unit_check_keep_going, unit_check_command use M_debug, only : unit_check_msg use M_debug, only : debug use M_debug, only : fstop use M_debug, only : stderr use M_debug, only : assert

QUOTE

Do not let your victories go to your head, nor let your failures go to your heart.

DESCRIPTION

The M_debug(3fm) Fortran module provides procedures and variables useful for providing error processing, debugging capabilities, and unit testing.
o allows for a user-defined command to be called to collect results or mail failure alerts, ...
o supports easily composing a message from up to nine scalar intrinsic values and different message levels
o allows stopping on first failure or continuing

    SET MODES

unit_check_keep_going
  logical variable that can be used to turn off program termination on errors.
unit_check_level
  An integer that can be used to specify different debug levels
unit_check_command
  name of command to execute. Defaults to the name "goodbad".

    UNIT TESTS

unit_check_start(3f)
  start tests of a procedure and optionally call
                             command NAME start ..."
unit_check(3f)
  if expression is false optionally call
                             command NAME bad
and stop program (by default)
unit_check_done(3f)
  call
                             command NAME good
if no failures else call command NAME bad
unit_check_good(3f)
  call command command NAME good
unit_check_bad(3f)
  call command command NAME bad and stop program by default
unit_check_msg(3f)
  write message

    BASIC DEBUGGING

fstop(3f)
  calls ’STOP VALUE’ passing in a value (1-32), with optional message
pdec(3f)
  write ASCII Decimal Equivalent (ADE) numbers vertically beneath string
stderr(3f)
  Write message on stderr
debug logical variable that can be tested by routines as a flag to process debug statements.
For unit testing, the existence of a command called "goodbad" is initially assumed. This is generally a script that makes entries for each unit in an SQLite data file which is then used to create CSV and HTML reports on the status of each unit. A sample goodbad(1) 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 goodbad(1) command can be changed as desired to write CSV files or simple logs or to notify developers with e-mail as desired.

    RELATED FUNCTIONS

The routines in M_debug(3f) are often combined with the M_hashkeys(3fm) routines and various math and statistical routines to quickly create unit tests.

Comparisons of real values can be done with a tolerance with M_Compare_Float_Numbers(3fm), for example.

The intrinsics ANY(3f) and ALL(3f) are particularly useful in calls to unit_check(3f).

EXAMPLES

Sample program

    !!program demo_unit_tests
    module M_demo
    private
    public one !! regular routines
    public two !! regular routines
    public test_suite_M_demo !! special name for use with test_suite(1bash).
    contains

!! regular routines subroutine one() end subroutine one

subroutine two() end subroutine two

!! unit test subroutine test_suite_M_demo use M_debug, only: unit_check_start, unit_check use M_debug, only: unit_check_good, unit_check_bad, unit_check_done use M_debug, only: unit_check_msg implicit none integer :: i, j, k integer,allocatable :: array(:) integer :: arr(4)=[21,51,14,45] integer :: a=21, b=51, c=14, d=45 ! TEST-DRIVEN DEVELOPMENT ! optional set-up perform initialization operations common to all tests within a module i=1 j=2 k=3 array=[10,20,30,40,50,60,70] call test_one() call test_two() ! optional tear-down perform finalization operations common to all tests within a module contains

subroutine test_one() ! register an entry for specified name ("one") in database with status of zero (0) call unit_check_start(’one’)

! if mask test fails, can ! * produce a SUCCESS: or FAIL: message and stop program ! * change database status for specified entry to -1 and stop program, else continue ! * produce a SUCCESS: or FAIL: message and keep going ! * produce a FAIL: message if test fails but no SUCCESS: message if test passes call unit_check(’one’,i.gt.0,msg=’I > 0’)

! using ANY(3f) and ALL(3f) call unit_check(’one’,all([i,j,k].gt.0), ’testing if everyone greater than zero’) ! display message built of scalars as well call unit_check(’one’,all(.not.[i,j,k].eq.4),’for set ’,i,j,k,’testing if no one is equal to four’)

! for tests that are hard to reduce to a logical test just call unit_check_bad(3f) if fail if(i+j+k.lt.1)then call unit_check_bad(’one’) endif

call unit_check_done(’one’,’checks on "one" ended’) end subroutine test_one

subroutine test_two ! use of all(3f), any(3f), merge(3f) can be useful ! if you know what these would produce ! write(*,*)[’A’,’X’,’X’,’X’,’X’,’B’].eq.’B’ ! this would return an array, the last element having the value T, else F ! write(*,*)all([’A’,’X’,’X’,’X’,’X’,’X’].eq.’X’) ! this would return F ! write(*,*)any([’A’,’X’,’X’,’X’,’X’,’X’].eq.’B’) ! this would return F ! write(*,*)any([’A’,’X’,’X’,’X’,’X’,’B’].eq.’B’) ! this would return T ! write(*,*).not.all(array.lt.100) ! write(*,*)all(array.lt.100) ! write(*,*)all([a,b,c,d].eq.[21,51,14,45]) ! compare a list. This would return T ! write(*,*)all(arr.eq.[21,51,14,45]) ! compare an array. This would return T ! you know how valuable ANY(3f) and ALL(3f) will be call unit_check_start(’two’,’check on "two" passed’) call unit_check(’two’, 1.gt.0 .and. abs(10.10000-10.10001).lt.0.0001,msg=’two looks good’) call unit_check_done(’two’,’checks on "two" ended’) end subroutine test_two

end subroutine test_suite_M_demo

end module M_demo

program demo_M_debug use M_demo, only: test_suite_M_demo use M_debug, only: unit_check_command, unit_check_keep_going,unit_check_level unit_check_command=’’ unit_check_keep_going=.true. unit_check_level=0 call test_suite_M_demo end program demo_M_debug

Expected output:

    unit_check:       one                  SUCCESS:I > 0
    unit_check:       one                  SUCCESS:testing if everyone greater than zero
    unit_check:       one                  SUCCESS:for set 1 2 3 testing if no one is equal to four
    unit_check_done:  one                  PASSED   GOOD:3  BAD:0

unit_check: two SUCCESS:two looks good unit_check_done: two PASSED GOOD:1 BAD:0

AUTHOR

John S. Urban

LICENSE

Public Domain


M_debug (3) October 17, 2020
Generated by manServer 1.08 from e3a63132-8dc4-4756-8a34-e2598eb9fe51 using man macros.