Debugging, Testing & Documentation
Compiler warnings (-Wall -Wextra -pedantic -std=f2018), fortitude (fast linter), flint, camfort, fprettify, findent, LFortran's semantic checks, NAG compiler's strict checking.
34.1 Debug builds
-fcheck=bounds catches out-of-bounds indexing; -finit-real=snan exposes uninitialized reals.
-fsanitize=address,undefined (gfortran) for memory errors; Valgrind for leaks.
Debuggers: gdb (break, run, print a(1:5), bt), lldb, Intel gdb, TotalView/DDT for parallel codes; VS Code debugging via the Modern Fortran extension.
gfortran -g -O0 -Wall -Wextra -Wimplicit-interface -fcheck=all -fbacktrace \
-ffpe-trap=invalid,zero,overflow -finit-real=snan -std=f2018 prog.f90
ifx -g -O0 -check all -traceback -warn all -fpe0 prog.f9034.2 Unit testing frameworks
test-drive (fpm default):
pFUnit (NASA; supports MPI and OpenMP tests), veggies/garden, Zofu, FRUIT, fortuno.
Regression tests: compare outputs against reference data with tolerances; CI with GitHub Actions (fortran-lang/setup-fortran).
Code coverage: gcov/gcovr/lcov with --coverage.
module test_math
use testdrive, only: new_unittest, unittest_type, error_type, check
use mymath, only: square
implicit none
contains
subroutine collect_tests(testsuite)
type(unittest_type), allocatable, intent(out) :: testsuite(:)
testsuite = [new_unittest("square", test_square)]
end subroutine
subroutine test_square(error)
type(error_type), allocatable, intent(out) :: error
call check(error, square(3.0) == 9.0, "square(3) should be 9")
end subroutine
end module test_math34.3 Static analysis & formatting
Compiler warnings (-Wall -Wextra -pedantic -std=f2018), fortitude (fast linter), flint, camfort, fprettify, findent, LFortran's semantic checks, NAG compiler's strict checking.
34.4 Documentation with FORD
ford project.md generates an HTML site with call graphs, module dependency graphs, and source listings. Doxygen also supports Fortran.
!> Computes the area of a circle.
!>
!> Uses the formula \( A = \pi r^2 \).
pure real(dp) function circle_area(r)
real(dp), intent(in) :: r !! radius (must be non-negative)
circle_area = pi * r**2
end function circle_area