Skip to content

Cannot have parameterized and un-parameterized tests in the same file #522

@connoraird

Description

@connoraird

Description

When using the preprocessor, it is not possible to have a .pf file which contains both test parameterised and unparameterised tests. For example, if we take this .pf

module test_nagTools_module
  use funit
  use NagToolsModule
  use ConstantsModule

  implicit none

  @testParameter
  type, extends(AbstractTestParameter) :: chol_test_params
    real(dp), dimension(2,2) :: A
    real(dp), dimension(2,2) :: exp_C
    character(1) :: UPLO
    character(len=100) :: description
  contains
    procedure :: toString => chol_test_params_toString
  end type chol_test_params

  @TestCase(constructor=chol_test_params_to_chol_test_case, testParameterType=chol_test_params)
  type, extends(ParameterizedTestCase) :: chol_test_case
      type(chol_test_params) :: params
  end type chol_test_case

contains

  ! chol tests
  !-----------

  function chol_test_suite() result(params)
    type(chol_test_params):: params(2)

    real(dp), dimension(2,2) :: A, exp_C

    A(1,:) = [1.0_dp,0.0_dp]
    A(2,:) = [0.5_dp,1.0_dp]
    exp_C(1,:) = [1.0_dp,0.0_dp]
    exp_C(2,:) = [0.5_dp,sqrt(3.0_dp)/2.0_dp]

    params(1) = chol_test_params(A, exp_C, 'L', "Lower-Triangular Cholesky Factorization")

    A(1,:) = [1.0_dp,0.5_dp]
    A(2,:) = [0.0_dp,1.0_dp]
    exp_C(1,:) = [1.0_dp,0.5_dp]
    exp_C(2,:) = [0.0_dp,sqrt(3.0_dp)/2.0_dp]

    params(2) = chol_test_params(A, exp_C, 'U', "Upper-Triangular Cholesky Factorization")
  end function chol_test_suite

  @test(testParameters={chol_test_suite()})
  subroutine test_chol(this)
    class(chol_test_case), intent(inout) :: this
    ! This subroutine tests the Cholesky composition of a positive-definite matrix, given its upper- or lower-triangular form

    real(dp), dimension(2,2) :: act_C
    integer(i4b) :: info

    CALL chol( &
      this%params%A, &
      this%params%UPLO, &
      act_C, &
      info &
    )
    @assertEqual(this%params%exp_C,act_C,tolerance=1e-10,message="Lower-Triangular Cholesky Factorization")

  end subroutine test_chol

  ! inverse chol tests
  !-------------------

  @test
  subroutine test_invChol()
    ! This subroutine tests the inversion of a positive-definite matrix given its Cholesky factorization in upper- or lower-triangular form

    real(dp), dimension(2,2) :: C, act_inv, exp_inv
    integer(i4b) :: info
    character(1) :: UPLO

    ! Test lower-triangular Cholesky factor matrix inversion
    C(1,:) = [1.0_dp,0.0_dp]
    C(2,:) = [0.5_dp,sqrt(3.0_dp)/2.0_dp]
    UPLO = 'L'
    exp_inv(1,:) = [4.0_dp/3.0_dp,0.0_dp]
    exp_inv(2,:) = [-2.0_dp/3.0_dp,4.0_dp/3.0_dp]

    CALL InvChol(C,UPLO,act_inv)
    @assertEqual(exp_inv,act_inv,tolerance=1e-10,message="Lower-Triangular Cholesky Factor Inversion")

    ! Test upper-triangular Cholesky factor matrix inversion
    C(1,:) = [1.0_dp,0.5_dp]
    C(2,:) = [0.0_dp,sqrt(3.0_dp)/2.0_dp]
    UPLO = 'U'
    exp_inv(1,:) = [4.0_dp/3.0_dp,-2.0_dp/3.0_dp]
    exp_inv(2,:) = [0.0_dp,4.0_dp/3.0_dp]

    CALL InvChol(C,UPLO,act_inv)
    @assertEqual(exp_inv,act_inv,tolerance=1e-10,message="Upper-Triangular Cholesky Factor Inversion")

  end subroutine test_invChol


  ! Constructors
  !--------------

  function chol_test_params_toString(this) result(string)
    class (chol_test_params), intent(in) :: this
    character(:), allocatable :: string

    character(len=100) :: buffer

    write(buffer,'(a)') this%description
    string = trim(buffer)
  end function chol_test_params_toString

  function chol_test_params_to_chol_test_case(testParameter) result(tst)
      type (chol_test_case) :: tst
      type (chol_test_params), intent(in) :: testParameter

      tst%params = testParameter
  end function chol_test_params_to_chol_test_case

end module test_nagTools_module

We get this suite produced within the processed .F90 file

function test_nagTools_module_suite() result(suite)
   use FUnit
   use test_nagTools_module
   use Wraptest_nagTools_module
   implicit none
   type (TestSuite) :: suite

   class (Test), allocatable :: t

   type (chol_test_params), allocatable :: testParameters(:)
   type (chol_test_params) :: testParameter
   integer :: iParam, iCase
   integer, allocatable :: cases(:)

   suite = TestSuite('test_nagTools_module_suite')

   testParameters = chol_test_suite()

   do iParam = 1, size(testParameters)
      testParameter = testParameters(iParam)
   call suite%addTest(makeCustomTest('test_chol', test_chol, testParameter))
   end do

   call suite%addTest(makeCustomTest('test_invChol', test_invChol))


end function test_nagTools_module_suite

The problem here is that we are not passing testParameters to makeCustomTest for the test_invChol but makeCustom Test expects it...

   function makeCustomTest(methodName, testMethod, testParameter) result(aTest)
      type (WrapUserTestCase) :: aTest
      character(len=*), intent(in) :: methodName
      procedure(userTestMethod) :: testMethod
      type (chol_test_params), intent(in) :: testParameter
      aTest%chol_test_case = chol_test_params_to_chol_test_case(testParameter)

      aTest%testMethodPtr => testMethod
#ifdef INTEL_13
      p => aTest
      call p%setName(methodName)
#else
      call aTest%setName(methodName)
#endif
      call aTest%setTestParameter(testParameter)
   end function makeCustomTest

Possible solution

Could we update the preprocessor to make testParameters an optional argument to makeCustomTest here?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions