如何对接口在子模块中定义的函数进行单元测试



在我看来,子模块的一个很好的特性是,您可以在子模块中创建辅助函数,而程序员的成本很小;您不会触发编译级联,不会使名称空间或文档混乱,并且可以立即清楚地知道该函数可以在何处使用,不可以在何处使用。它们就像private函数的更好版本。

然而,子模块中的函数不能是used。虽然这是预期的工作,但这似乎也阻止了函数被单元测试。我所知道的两个单元测试框架,pFUnit和fruit,都需要use语法来操作。

有一些(我有点不优雅)的解决方法与private函数在如何访问私有变量在fortran模块中讨论相同的问题?,但这些解决方案似乎都不适用于子模块中的函数,至少在不否定将这些函数放在子模块中的所有好处的情况下。

那么这个问题有什么解决办法吗?

引入submodule概念的主要目的是避免在模块文件中只引入了一个不破坏接口的小更改时出现长时间的重新编译级联。这是通过分离过程的接口并将它们放在父模块中,而将实现保留在子模块中来实现的。

子模块本身被允许拥有子模块,这对于非常大的子模块非常有用项目。我所看到的子模块级别的数量通常不超过两个(也就是说,一个模块的子模块本身有子模块),但没有限制。每个模块或子模块都是树的根,树的其他节点是它的后代,可以通过主机关联访问它。其他子模块没有这样的访问权限,这有助于独立开发大型模块的部分。此外,没有任何机制可以从其他地方访问子模块中声明的任何内容-正如您所说,它实际上是私有的。

因此,总而言之,如果您需要任何级别的任何子模块中的任何内容被程序的任何其他部分访问,则必须在子模块的原始父模块中声明。据我所知,没有其他方法可以访问任何子模块中的任何东西,其接口或声明未在原始父模块中给出。

一旦你把过程接口和变量/类型声明放在父模块中,你就可以在程序的任何地方use它们,即使过程实现可以隐藏在父模块的子模块中。

我几乎没有使用子模块的经验(所以不确定这是否有用),但只是扩展我上面的评论…

!! parent_mod.f90 (public things)
module parent_mod
implicit none
type myint_t
integer :: n = 100
contains
procedure :: add, show
endtype
interface
module subroutine add( x )
class(myint_t) :: x
end
module subroutine show( x )
class(myint_t) :: x
end
endinterface
end
!! parent_helper.f90 (private things to be used by parent_impl.f90
!! and possibly by unit tests)
module parent_helper
use parent_mod, only: myint_t
implicit none
contains
subroutine debug_show( x )
type(myint_t) :: x
print *, "debug: x = ", x
end
end
!! parent_impl.f90  (implementation)
submodule (parent_mod) parent_impl
implicit none
contains
module procedure add
x% n = x% n + 1
end
module procedure show
use parent_helper, only: debug_show
call debug_show( x )
end
end
!! main.f90
program main
use parent_mod, only: myint_t
implicit none
type(myint_t) :: a
call a% add()
call a% show()  !! 101
call a% add()
call a% show()  !! 102
block
use parent_helper
call debug_show( a )  !! 102
endblock
end
!! build
$ gfortran-10 -fcheck=all -Wall -Wextra parent_mod.f90 parent_helper.f90 parent_impl.f90 main.f90

这是否可能有助于避免重新编译parent_mod ?F90(即使当parent_helper或parent_impl被修改)?(我注意到模块名"parent"在这里没有意义……XD)

最新更新