在我看来,断言机制并不是 Fortran 单元测试的主要关注点。如您链接的答案中所述,Fortran 存在多个单元测试框架,例如 funit 和 FRUIT。
但是,我认为,主要问题是依赖关系的解决。您可能有一个包含许多相互依赖的模块的大型项目,并且您的测试应该涵盖使用许多其他模块的模块之一。因此,您需要找到这些依赖项并相应地构建单元测试。一切都归结为编译可执行文件,断言的优势非常有限,因为无论如何您都需要定义测试并自己进行比较。
我们正在使用 Waf 构建我们的 Fortran 应用程序,它带有一个单元 testing utility itself。现在,我不知道这是否可以供您使用,但唯一的要求是 Python,它应该可以在几乎任何平台上使用。一个缺点是,测试依赖于一个返回码,这在 Fortran 中不容易获得,至少在 Fortran 2008 之前不能以可移植的方式获得,它建议在返回码中提供停止码。所以我修改了我们项目中成功的检查。我希望测试写一些字符串,而不是检查返回码,并在输出中检查:
def summary(bld):
"""
Get the test results from last line of output::
Fortran applications can not return arbitrary return codes in
a standarized way, instead we use the last line of output to
decide the outcome of a test: It has to state "PASSED" to count
as a successful test.
Otherwise it is considered as a failed test. Non-Zero return codes
that might still happen are also considered as failures.
Display an execution summary:
def build(bld):
bld(features='cxx cxxprogram test', source='main.c', target='app')
from waflib.extras import utest_results
bld.add_post_fun(utest_results.summary)
"""
from waflib import Logs
import sys
lst = getattr(bld, 'utest_results', [])
# Check for the PASSED keyword in the last line of stdout, to
# decide on the actual success/failure of the test.
nlst = []
for (f, code, out, err) in lst:
ncode = code
if not code:
if sys.version_info[0] > 2:
lines = out.decode('ascii').splitlines()
else:
lines = out.splitlines()
if lines:
ncode = lines[-1].strip() != 'PASSED'
else:
ncode = True
nlst.append([f, ncode, out, err])
lst = nlst
我还按照惯例添加了测试,在构建脚本中只需要提供一个目录,并且该目录中以 _test.f90 结尾的所有文件都将被假定为单元测试,我们将尝试构建并运行它们:
def utests(bld, use, path='utests'):
"""
Define the unit tests from the programs found in the utests directory.
"""
from waflib import Options
for utest in bld.path.ant_glob(path + '/*_test.f90'):
nprocs = search_procs_in_file(utest.abspath())
if int(nprocs) > 0:
bld(
features = 'fc fcprogram test',
source = utest,
use = use,
ut_exec = [Options.options.mpicmd, '-n', nprocs,
utest.change_ext('').abspath()],
target = utest.change_ext(''))
else:
bld(
features = 'fc fcprogram test',
source = utest,
use = use,
target = utest.change_ext(''))
您可以在Aotus library 中找到类似定义的单元测试。在wscript 中使用了哪些通过:
from waflib.extras import utest_results
utest_results.utests(bld, 'aotus')
然后也可以从单元测试中仅构建子集,例如通过运行
./waf build --target=aot_table_test
在奥图斯。我们的测试覆盖面有点少,但我认为这个基础设施展览会实际上相当不错。测试可以简单地利用项目中的所有模块,并且可以轻松编译。
现在我不知道这是否适合你,但我会更多地考虑在你的构建环境中集成你的测试,而不是关于断言的东西。在每个模块中都有一个测试例程绝对是一个好主意,然后可以很容易地从测试程序中调用它。我会尝试为您要测试的每个模块设置一个可执行文件,其中每个模块当然可以包含多个测试。