F2PY 测试套件#
F2PY 的测试套件位于目录中numpy/f2py/tests
。其目的是确保 Fortran 语言功能正确翻译为 Python。例如,用户可以在 Fortran 中指定数组的起始和结束索引。此行为会转换为生成的 CPython 库,其中数组严格从 0 索引开始。
测试套件的目录如下所示:
./tests/
├── __init__.py
├── src
│ ├── abstract_interface
│ ├── array_from_pyobj
│ ├── // ... several test folders
│ └── string
├── test_abstract_interface.py
├── test_array_from_pyobj.py
├── // ... several test files
├── test_symbolic.py
└── util.py
以 开头的文件test_
包含对 f2py 各个方面的测试,从解析 Fortran 文件到检查模块的文档。src
目录包含我们进行测试的 Fortran 源文件。util.py
包含用于在测试期间使用临时位置构建和导入 Fortran 模块的实用程序函数。
添加测试#
F2PY 当前的测试套件早于之前pytest
,因此不使用固定装置。相反,测试文件包含继承F2PyTest
自util.py
.
1 cmd = [sys.executable, script, "build_ext", "-i"]
2 p = subprocess.Popen(cmd,
3 stdout=subprocess.PIPE,
4 stderr=subprocess.STDOUT)
5 out, err = p.communicate()
6 if p.returncode != 0:
7 raise RuntimeError("Running distutils build failed: %s\n%s" %
8 (cmd[4:], asstr(out)))
9 finally:
10 os.chdir(cwd)
此类有许多用于解析和编译测试源文件的辅助函数。它的子类可以重写它的sources
数据成员以提供它们自己的源文件。然后,该超类将在创建对象时编译添加的源文件,并将它们的函数附加到self.module
数据成员中。因此,子类将能够通过调用 来访问源文件中指定的 fortran 函数
self.module.[fortran_function_name]
。
例子#
考虑以下子例程,包含在名为add-test.f
subroutine addb(k)
real(8), intent(inout) :: k(:)
k=k+1
endsubroutine
subroutine addc(w,k)
real(8), intent(in) :: w(:)
real(8), intent(out) :: k(size(w))
k=w+1
endsubroutine
第一个例程addb只是获取一个数组并将其元素增加 1。第二个子例程addc分配一个新数组k,其元素比输入数组w的元素大1。
测试可以按如下方式实施:
class TestAdd(util.F2PyTest):
sources = [util.getpath("add-test.f")]
def test_module(self):
k = np.array([1, 2, 3], dtype=np.float64)
w = np.array([1, 2, 3], dtype=np.float64)
self.module.subb(k)
assert np.allclose(k, w + 1)
self.module.subc([w, k])
assert np.allclose(k, w + 1)
我们重写sources
数据成员以提供源文件。创建类对象时,将编译源文件并将子例程附加到模块数据成员。该test_module
函数调用子例程并测试其结果。