fortplot_testing.f90 Source File


Source Code

module fortplot_testing
    !! Testing utilities module with proper error handling
    use fortplot_errors, only: fortplot_error_t, SUCCESS, ERROR_INVALID_INPUT
    implicit none
    
    private
    public :: assert_file_exists, assert_equals, assert_true
    public :: test_result_t
    
    !> Test result type for better test management
    type :: test_result_t
        logical :: passed = .true.
        character(len=256) :: message = ""
        integer :: error_count = 0
    contains
        procedure :: fail
        procedure :: get_status
    end type test_result_t
    
contains

    subroutine assert_file_exists(filename, test_result)
        character(len=*), intent(in) :: filename
        type(test_result_t), intent(inout), optional :: test_result
        logical :: exists
        
        inquire(file=filename, exist=exists)
        if (.not. exists) then
            if (present(test_result)) then
                call test_result%fail("File '" // trim(filename) // "' does not exist")
            else
                write(*, '(A,A,A)') "ASSERTION FAILED: File '", trim(filename), "' does not exist"
                ! Legacy behavior: continue with error output instead of stop
            end if
        end if
    end subroutine assert_file_exists
    
    subroutine assert_equals(actual, expected, tolerance, message, test_result)
        use iso_fortran_env, only: wp => real64
        real(wp), intent(in) :: actual, expected
        real(wp), intent(in), optional :: tolerance
        character(len=*), intent(in), optional :: message
        type(test_result_t), intent(inout), optional :: test_result
        real(wp) :: tol
        character(len=100) :: msg
        character(len=256) :: error_msg
        
        tol = 1e-6_wp
        if (present(tolerance)) tol = tolerance
        
        msg = "Values not equal"
        if (present(message)) msg = message
        
        if (abs(actual - expected) > tol) then
            write(error_msg, '(A," - Expected: ",G0,", Actual: ",G0)') trim(msg), expected, actual
            if (present(test_result)) then
                call test_result%fail(error_msg)
            else
                write(*, '(A,A)') "ASSERTION FAILED: ", trim(error_msg)
                ! Legacy behavior: continue with error output instead of stop
            end if
        end if
    end subroutine assert_equals
    
    subroutine assert_true(condition, message, test_result)
        logical, intent(in) :: condition
        character(len=*), intent(in), optional :: message
        type(test_result_t), intent(inout), optional :: test_result
        character(len=100) :: msg
        
        msg = "Condition is false"
        if (present(message)) msg = message
        
        if (.not. condition) then
            if (present(test_result)) then
                call test_result%fail(msg)
            else
                write(*, '(A,A)') "ASSERTION FAILED: ", trim(msg)
                ! Legacy behavior: continue with error output instead of stop
            end if
        end if
    end subroutine assert_true
    
    !> Mark test as failed with error message
    subroutine fail(this, message)
        class(test_result_t), intent(inout) :: this
        character(len=*), intent(in) :: message
        
        this%passed = .false.
        this%error_count = this%error_count + 1
        if (len_trim(this%message) == 0) then
            this%message = trim(message)
        else
            this%message = trim(this%message) // "; " // trim(message)
        end if
    end subroutine fail
    
    !> Get test status as integer code
    function get_status(this) result(status)
        class(test_result_t), intent(in) :: this
        integer :: status
        
        if (this%passed) then
            status = SUCCESS
        else
            status = ERROR_INVALID_INPUT  ! Generic error for test failures
        end if
    end function get_status

end module fortplot_testing