NumPy参考 >NumPy和SWIG > 测试numpy.i Typemap
为numpy.i
SWIG
接口文件编写测试是一个组合难题。目前,支持12种不同的数据类型,每种数据类型具有74个不同的参数签名,总共支持888个“即开即用”的类型映射。这些类型映射中的每一个可能反过来可能都需要进行多个单元测试,以验证正确和不正确输入的预期行为。当前,当在子目录中运行时,这将导致执行1,000多个单独的单元测试
。make test
numpy/tools/swig
为了促进许多类似的单元测试,采用了一些高级编程技术,包括C和SWIG宏以及Python继承。本文档的目的是描述用于验证类型numpy.i
映射是否按预期工作的测试基础结构。
支持三种独立的测试框架,分别针对一维,二维和三维阵列。对于一维数组,有两个C ++文件,一个标头和一个源,名为:
Vector.h
Vector.cxx
包含用于具有一维数组作为函数参数的各种函数的原型和代码。文件:
Vector.i
是一个SWIG接口文件,它定义了一个python模块Vector
,该模块在Vector.h
使用类型映射numpy.i
正确处理C数组时包装了函数。
该Makefile
调用swig
生成Vector.py
和
Vector_wrap.cxx
,并执行setup.py
脚本编译Vector_wrap.cxx
和链接在一起的扩展模块
_Vector.so
或者_Vector.dylib
,根据不同的平台上。该扩展模块和代理文件Vector.py
都放置在目录下的build
子目录中。
实际的测试是使用名为以下内容的Python脚本进行的:
testVector.py
使用标准的Python库模块unittest
,该模块Vector.h
针对支持的每种数据类型对定义的每个函数执行多次测试。
二维数组的测试方法完全相同。以上描述适用,但以Matrix
代替
Vector
。对于三维测试,替代Tensor
了
Vector
。对于四维测试,替代SuperTensor
了Vector
。对于平坦就地阵列测试中,替代Flat
为Vector
。对于下面的描述中,我们将引用
Vector
测试,但同样的信息适用于Matrix
,
Tensor
和SuperTensor
测试。
该命令将确保已构建所有测试软件,然后运行所有三个测试脚本。make test
Vector.h
是一个C ++头文件,它定义一个名为C的C宏TEST_FUNC_PROTOS
,该宏带有
两个参数:TYPE
,这是数据类型名称,例如;和是同一数据类型的缩写,没有空格,例如。该宏定义了几个函数原型,这些函数原型具有前缀
并且至少具有一个类型为type的参数
。具有返回参数的函数将返回一个
值。unsigned int
SNAME
uint
SNAME
TYPE
TYPE
TEST_FUNC_PROTOS
然后为所支持的所有数据类型实现numpy.i
:
signed char
unsigned char
short
unsigned short
int
unsigned int
long
unsigned long
long long
unsigned long long
float
double
Vector.cxx
是一个C ++源文件,它为中指定的每个函数原型实现可编译代码Vector.h
。它定义了一个C宏TEST_FUNCS
,它具有与in相同的参数并以相同的方式TEST_FUNC_PROTOS
工作Vector.h
。
TEST_FUNCS
为上述12种数据类型中的每一种实现。
Vector.i
是定义python模块的SWIG接口文件
Vector
。它遵循numpy.i
本章所述的使用约定。它定义了一个具有单个参数的SWIG宏
。它使用SWIG指令将提供的类型映射应用于中找到的参数签名。然后针对所支持的所有数据类型实现此宏
。然后,它将使用中的typemap
封装所有函数原型。%apply_numpy_typemaps
TYPE
%apply
Vector.h
numpy.i
%include "Vector.h"
Vector.h
numpy.i
在make
用于构建测试扩展模块之后,
testVector.py
可以运行以执行测试。与unittest
用于促进单元测试的其他脚本一样,
testVector.py
定义一个继承自的类
unittest.TestCase
:
class VectorTestCase(unittest.TestCase):
但是,此类不能直接运行。相反,它是其他几个python类的基类,每个python类都特定于一种特定的数据类型。该VectorTestCase
级存储打字信息两个字符串:
- self.typeStr
与
SNAME
在Vector.h
和中使用的前缀 之一匹配的字符串Vector.cxx
。例如,"double"
。- self.typeCode
一个短字符串(通常为单字符),表示numpy中的数据类型,并与相对应
self.typeStr
。例如,如果self.typeStr
为"double"
,self.typeCode
则应为"d"
。
VectorTestCase
该类定义的每个测试都通过访问Vector
模块的字典来提取它正尝试测试的python函数:
length = Vector.__dict__[self.typeStr + "Length"]
在双精度测试的情况下,这将返回python函数Vector.doubleLength
。
然后,我们为每种受支持的数据类型定义一个新的测试用例类,并使用以下简短定义:
class doubleTestCase(VectorTestCase):
def __init__(self, methodName="runTest"):
VectorTestCase.__init__(self, methodName)
self.typeStr = "double"
self.typeCode = "d"
这12个类中的每一个都收集到中unittest.TestSuite
,然后执行。错误和失败加在一起,并作为退出参数返回。任何非零结果表示至少一项测试未通过。