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,因此不使用固定装置。相反,测试文件包含继承F2PyTestutil.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函数调用子例程并测试其结果。