This repository has been archived by the owner on May 6, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 40
/
Copy pathswig.testing.html
93 lines (91 loc) · 17.2 KB
/
swig.testing.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
<h1><span class="yiyi-st" id="yiyi-19">Testing the numpy.i Typemaps</span></h1>
<blockquote>
<p>原文:<a href="https://docs.scipy.org/doc/numpy/reference/swig.testing.html">https://docs.scipy.org/doc/numpy/reference/swig.testing.html</a></p>
<p>译者:<a href="https://github.com/wizardforcel">飞龙</a> <a href="http://usyiyi.cn/">UsyiyiCN</a></p>
<p>校对:(虚位以待)</p>
</blockquote>
<div class="section" id="introduction">
<h2><span class="yiyi-st" id="yiyi-20">Introduction</span></h2>
<p><span class="yiyi-st" id="yiyi-21">为<code class="docutils literal"><span class="pre">numpy.i</span></code> <a class="reference external" href="http://www.swig.org">SWIG</a>接口文件编写测试是一种组合性头痛。</span><span class="yiyi-st" id="yiyi-22">目前,支持12种不同的数据类型,每种类型具有74个不同的参数签名,支持“开箱即用”的总共888个类型映射。</span><span class="yiyi-st" id="yiyi-23">这些类型映射中的每一个反过来可能需要几个单元测试,以便验证正确和不正确输入的预期行为。</span><span class="yiyi-st" id="yiyi-24">目前,这将导致在<code class="docutils literal"><span class="pre">进行</span> <span class="pre">测试</span></code>时在<code class="docutils literal"><span class="pre">numpy/tools/swig</span></code></span></p>
<p><span class="yiyi-st" id="yiyi-25">为了促进这种许多类似的单元测试,采用一些高级编程技术,包括C和<a class="reference external" href="http://www.swig.org">SWIG</a>宏以及Python继承。</span><span class="yiyi-st" id="yiyi-26">本文档的目的是描述用于验证<code class="docutils literal"><span class="pre">numpy.i</span></code>类型映射是否按预期工作的测试基础结构。</span></p>
</div>
<div class="section" id="testing-organization">
<h2><span class="yiyi-st" id="yiyi-27">Testing Organization</span></h2>
<p><span class="yiyi-st" id="yiyi-28">支持三个独立的测试框架,分别用于一维,二维和三维数组。</span><span class="yiyi-st" id="yiyi-29">对于一维数组,有两个C ++文件,一个头和一个源,命名为:</span></p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">Vector</span><span class="o">.</span><span class="n">h</span>
<span class="n">Vector</span><span class="o">.</span><span class="n">cxx</span>
</pre></div>
</div>
<p><span class="yiyi-st" id="yiyi-30">其包含用于具有一维数组作为函数参数的各种函数的原型和代码。</span><span class="yiyi-st" id="yiyi-31">文件:</span></p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">Vector</span><span class="o">.</span><span class="n">i</span>
</pre></div>
</div>
<p><span class="yiyi-st" id="yiyi-32">is a <a class="reference external" href="http://www.swig.org">SWIG</a> interface file that defines a python module <code class="docutils literal"><span class="pre">Vector</span></code> that wraps the functions in <code class="docutils literal"><span class="pre">Vector.h</span></code> while utilizing the typemaps in <code class="docutils literal"><span class="pre">numpy.i</span></code> to correctly handle the C arrays.</span></p>
<p><span class="yiyi-st" id="yiyi-33"><code class="docutils literal"><span class="pre">Makefile</span></code>调用<code class="docutils literal"><span class="pre">swig</span></code>以生成<code class="docutils literal"><span class="pre">Vector.py</span></code>和<code class="docutils literal"><span class="pre">Vector_wrap.cxx</span></code>,并执行<code class="docutils literal"><span class="pre">setup.py</span></code>脚本,它编译<code class="docutils literal"><span class="pre">Vector_wrap.cxx</span></code>并将扩展模块<code class="docutils literal"><span class="pre">_Vector.so</span></code>或<code class="docutils literal"><span class="pre">_Vector.dylib</span></code>平台。</span><span class="yiyi-st" id="yiyi-34">此扩展模块和代理文件<code class="docutils literal"><span class="pre">Vector.py</span></code>都放置在<code class="docutils literal"><span class="pre">build</span></code>目录下的子目录中。</span></p>
<p><span class="yiyi-st" id="yiyi-35">实际测试使用一个名为的Python脚本:</span></p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">testVector</span><span class="o">.</span><span class="n">py</span>
</pre></div>
</div>
<p><span class="yiyi-st" id="yiyi-36">它使用标准的Python库模块<code class="docutils literal"><span class="pre">unittest</span></code>,它对每个支持的数据类型执行<code class="docutils literal"><span class="pre">Vector.h</span></code>中定义的每个函数的几个测试。</span></p>
<p><span class="yiyi-st" id="yiyi-37">二维数组以完全相同的方式测试。</span><span class="yiyi-st" id="yiyi-38">以上描述适用,但使用<code class="docutils literal"><span class="pre">Matrix</span></code>替换<code class="docutils literal"><span class="pre">Vector</span></code>。</span><span class="yiyi-st" id="yiyi-39">对于三维测试,将<code class="docutils literal"><span class="pre">Tensor</span></code>替换为<code class="docutils literal"><span class="pre">Vector</span></code>。</span><span class="yiyi-st" id="yiyi-40">对于四维测试,用<code class="docutils literal"><span class="pre">SuperTensor</span></code>替换<code class="docutils literal"><span class="pre">Vector</span></code>。</span><span class="yiyi-st" id="yiyi-41">对于平面原位数组测试,用<code class="docutils literal"><span class="pre">Flat</span></code>替换<code class="docutils literal"><span class="pre">Vector</span></code>。</span><span class="yiyi-st" id="yiyi-42">对于以下描述,我们将引用<code class="docutils literal"><span class="pre">Vector</span></code>测试,但相同的信息适用于<code class="docutils literal"><span class="pre">Matrix</span></code>,<code class="docutils literal"><span class="pre">Tensor</span></code>和<code class="docutils literal"><span class="pre">SuperTensor</span></code></span></p>
<p><span class="yiyi-st" id="yiyi-43">命令<code class="docutils literal"><span class="pre">make</span> <span class="pre">test</span></code>将确保所有测试软件都已构建,然后运行所有三个测试脚本。</span></p>
</div>
<div class="section" id="testing-header-files">
<h2><span class="yiyi-st" id="yiyi-44">Testing Header Files</span></h2>
<p><span class="yiyi-st" id="yiyi-45"><code class="docutils literal"><span class="pre">Vector.h</span></code>是一个C ++头文件,它定义了一个名为<code class="docutils literal"><span class="pre">TEST_FUNC_PROTOS</span></code>的C宏,它接受两个参数:<code class="docutils literal"><span class="pre">TYPE</span></code>,这是一个数据类型名称<code class="docutils literal"><span class="pre">unsigned</span> <span class="pre">int</span></code>;和<code class="docutils literal"><span class="pre">SNAME</span></code>,这是相同数据类型的短名称,不含空格,例如<code class="docutils literal"><span class="pre">uint</span></code>。</span><span class="yiyi-st" id="yiyi-46">此宏定义了几个具有前缀<code class="docutils literal"><span class="pre">SNAME</span></code>的函数原型,并且至少有一个参数是类型<code class="docutils literal"><span class="pre">TYPE</span></code>的数组。</span><span class="yiyi-st" id="yiyi-47">具有返回参数的函数返回<code class="docutils literal"><span class="pre">TYPE</span></code>值。</span></p>
<p><span class="yiyi-st" id="yiyi-48"><code class="docutils literal"><span class="pre">numpy.i</span></code>支持的所有数据类型都将实现<code class="docutils literal"><span class="pre">TEST_FUNC_PROTOS</span></code>:</span></p>
<blockquote>
<div><ul class="simple">
<li><span class="yiyi-st" id="yiyi-49"><code class="docutils literal"><span class="pre">签名</span> <span class="pre">char</span></code></span></li>
<li><span class="yiyi-st" id="yiyi-50"><code class="docutils literal"><span class="pre">无符号</span> <span class="pre">char</span></code></span></li>
<li><span class="yiyi-st" id="yiyi-51"><code class="docutils literal"><span class="pre">short</span></code></span></li>
<li><span class="yiyi-st" id="yiyi-52"><code class="docutils literal"><span class="pre">无符号</span> <span class="pre">短</span></code></span></li>
<li><span class="yiyi-st" id="yiyi-53"><code class="docutils literal"><span class="pre">int</span></code></span></li>
<li><span class="yiyi-st" id="yiyi-54"><code class="docutils literal"><span class="pre">无符号</span> <span class="pre">int</span></code></span></li>
<li><span class="yiyi-st" id="yiyi-55"><code class="docutils literal"><span class="pre">long</span></code></span></li>
<li><span class="yiyi-st" id="yiyi-56"><code class="docutils literal"><span class="pre">无符号</span> <span class="pre">长</span></code></span></li>
<li><span class="yiyi-st" id="yiyi-57"><code class="docutils literal"><span class="pre">long</span> <span class="pre">long</span></code></span></li>
<li><span class="yiyi-st" id="yiyi-58"><code class="docutils literal"><span class="pre">无符号</span> <span class="pre">长</span> <span class="pre">长</span></code></span></li>
<li><span class="yiyi-st" id="yiyi-59"><code class="docutils literal"><span class="pre">float</span></code></span></li>
<li><span class="yiyi-st" id="yiyi-60"><code class="docutils literal"><span class="pre">double</span></code></span></li>
</ul>
</div></blockquote>
</div>
<div class="section" id="testing-source-files">
<h2><span class="yiyi-st" id="yiyi-61">Testing Source Files</span></h2>
<p><span class="yiyi-st" id="yiyi-62"><code class="docutils literal"><span class="pre">Vector.cxx</span></code>是一个C ++源文件,用于实现<code class="docutils literal"><span class="pre">Vector.h</span></code>中指定的每个函数原型的可编译代码。</span><span class="yiyi-st" id="yiyi-63">它定义具有相同参数的C宏<code class="docutils literal"><span class="pre">TEST_FUNCS</span></code>,其工作方式与<code class="docutils literal"><span class="pre">TEST_FUNC_PROTOS</span></code>在<code class="docutils literal"><span class="pre">Vector.h</span></code>中相同。</span><span class="yiyi-st" id="yiyi-64"><code class="docutils literal"><span class="pre">TEST_FUNCS</span></code>针对上述12种数据类型中的每一种实现。</span></p>
</div>
<div class="section" id="testing-swig-interface-files">
<h2><span class="yiyi-st" id="yiyi-65">Testing SWIG Interface Files</span></h2>
<p><span class="yiyi-st" id="yiyi-66"><code class="docutils literal"><span class="pre">Vector.i</span></code>是一个定义python模块<code class="docutils literal"><span class="pre">Vector</span></code>的<a class="reference external" href="http://www.swig.org">SWIG</a>接口文件。</span><span class="yiyi-st" id="yiyi-67">它遵循本章中所述的使用<code class="docutils literal"><span class="pre">numpy.i</span></code>的约定。</span><span class="yiyi-st" id="yiyi-68">它定义了具有单个参数<code class="docutils literal"><span class="pre">TYPE</span></code>的<a class="reference external" href="http://www.swig.org">SWIG</a>宏<code class="docutils literal"><span class="pre">%apply_numpy_typemaps</span></code>。</span><span class="yiyi-st" id="yiyi-69">它使用<a class="reference external" href="http://www.swig.org">SWIG</a>指令<code class="docutils literal"><span class="pre">%apply</span></code>将提供的类型映射应用于<code class="docutils literal"><span class="pre">Vector.h</span></code>中的参数签名。</span><span class="yiyi-st" id="yiyi-70">然后对由<code class="docutils literal"><span class="pre">numpy.i</span></code>支持的所有数据类型实现此宏。</span><span class="yiyi-st" id="yiyi-71">然后,它会在<code class="docutils literal"><span class="pre">Vector.h</span></code>中包含所有的函数原型,<code class="docutils literal"><span class="pre">%include</span> <span class="pre">“Vector.h”使用<code class="docutils literal"><span class="pre">numpy.i</span></code>中的类型映射。</span></code></span></p>
</div>
<div class="section" id="testing-python-scripts">
<h2><span class="yiyi-st" id="yiyi-72">Testing Python Scripts</span></h2>
<p><span class="yiyi-st" id="yiyi-73">在<code class="docutils literal"><span class="pre">make</span></code>用于构建测试扩展模块后,可以运行<code class="docutils literal"><span class="pre">testVector.py</span></code>来执行测试。</span><span class="yiyi-st" id="yiyi-74">与使用<code class="docutils literal"><span class="pre">unittest</span></code>以促进单元测试的其他脚本一样,<code class="docutils literal"><span class="pre">testVector.py</span></code>定义继承自<code class="docutils literal"><span class="pre">unittest.TestCase</span></code>的类:</span></p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">VectorTestCase</span><span class="p">(</span><span class="n">unittest</span><span class="o">.</span><span class="n">TestCase</span><span class="p">):</span>
</pre></div>
</div>
<p><span class="yiyi-st" id="yiyi-75">但是,这个类不是直接运行的。</span><span class="yiyi-st" id="yiyi-76">相反,它用作几个其他Python类的基类,每个特定于特定数据类型。</span><span class="yiyi-st" id="yiyi-77"><code class="docutils literal"><span class="pre">VectorTestCase</span></code>类存储两个用于键入信息的字符串:</span></p>
<blockquote>
<div><dl class="docutils">
<dt><span class="yiyi-st" id="yiyi-78"><strong>self.typeStr</strong></span></dt>
<dd><span class="yiyi-st" id="yiyi-79">与<code class="docutils literal"><span class="pre">Vector.h</span></code>和<code class="docutils literal"><span class="pre">Vector.cxx</span></code>中使用的<code class="docutils literal"><span class="pre">SNAME</span></code>前缀之一匹配的字符串。</span><span class="yiyi-st" id="yiyi-80">例如,<code class="docutils literal"><span class="pre">"double"</span></code>。</span></dd>
<dt><span class="yiyi-st" id="yiyi-81"><strong>self.typeCode</strong></span></dt>
<dd><span class="yiyi-st" id="yiyi-82">表示numpy中的数据类型的短(通常为单字符)字符串,对应于<code class="docutils literal"><span class="pre">self.typeStr</span></code>。</span><span class="yiyi-st" id="yiyi-83">例如,如果<code class="docutils literal"><span class="pre">self.typeStr</span></code>是<code class="docutils literal"><span class="pre">"double"</span></code>,则<code class="docutils literal"><span class="pre">self.typeCode</span></code>应为<code class="docutils literal"><span class="pre">"d"</span></code>。</span></dd>
</dl>
</div></blockquote>
<p><span class="yiyi-st" id="yiyi-84">由<code class="docutils literal"><span class="pre">VectorTestCase</span></code>类定义的每个测试通过访问<code class="docutils literal"><span class="pre">Vector</span></code>模块的字典来提取它试图测试的python函数:</span></p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">length</span> <span class="o">=</span> <span class="n">Vector</span><span class="o">.</span><span class="n">__dict__</span><span class="p">[</span><span class="bp">self</span><span class="o">.</span><span class="n">typeStr</span> <span class="o">+</span> <span class="s2">"Length"</span><span class="p">]</span>
</pre></div>
</div>
<p><span class="yiyi-st" id="yiyi-85">在双精度测试的情况下,这将返回python函数<code class="docutils literal"><span class="pre">Vector.doubleLength</span></code>。</span></p>
<p><span class="yiyi-st" id="yiyi-86">然后,我们为每个支持的数据类型定义一个新的测试用例类,其短定义如下:</span></p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">doubleTestCase</span><span class="p">(</span><span class="n">VectorTestCase</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">methodName</span><span class="o">=</span><span class="s2">"runTest"</span><span class="p">):</span>
<span class="n">VectorTestCase</span><span class="o">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">methodName</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">typeStr</span> <span class="o">=</span> <span class="s2">"double"</span>
<span class="bp">self</span><span class="o">.</span><span class="n">typeCode</span> <span class="o">=</span> <span class="s2">"d"</span>
</pre></div>
</div>
<p><span class="yiyi-st" id="yiyi-87">将这12个类中的每一个收集到<code class="docutils literal"><span class="pre">unittest.TestSuite</span></code>中,然后执行。</span><span class="yiyi-st" id="yiyi-88">错误和失败被汇总在一起并作为退出参数返回。</span><span class="yiyi-st" id="yiyi-89">任何非零结果表明至少一个测试未通过。</span></p>
</div>