Spec-Zone.ru › NumPy 1.11

Тестирование typemaps numpy.i

Введение

Написание тестов для файла интерфейса numpy.i SWIG является комбинаторной головной болью. В настоящее время поддерживается 12 различных типов данных, каждый из которых имеет 74 различные сигнатуры аргументов, что в сумме составляет 888 typemaps, поддерживаемых «из коробки». Каждый из этих typemaps, в свою очередь, может потребовать несколько модульных тестов для проверки ожидаемого поведения как для корректных, так и для некорректных входных данных. В настоящее время это приводит к выполнению более 1000 отдельных модульных тестов при запуске make test в подкаталоге numpy/tools/swig.

Для упрощения такого большого числа похожих модульных тестов используются некоторые высокоуровневые методы программирования, включая макросы C и SWIG, а также наследование в Python. Цель этого документа — описать инфраструктуру тестирования, используемую для проверки того, что typemaps numpy.i работают как ожидается.

Организация тестирования

Поддерживаются три независимых фреймворка тестирования для одномерных, двумерных и трехмерных массивов соответственно. Для одномерных массивов существуют два файла C++, заголовочный и исходный, с именами:

Vector.h
Vector.cxx

которые содержат прототипы и код для различных функций, имеющих одномерные массивы в качестве аргументов функций. Файл:

Vector.i

является файлом интерфейса SWIG, который определяет модуль python Vector, который оборачивает функции в Vector.h, используя typemaps в 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-макрос под названием TEST_FUNC_PROTOS, принимающий два аргумента: 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, который имеет те же аргументы и работает аналогично TEST_FUNC_PROTOS, что в Vector.h. TEST_FUNCS реализуется для каждого из 12 типов данных, как указано выше.

Тестирование файлов интерфейса SWIG

Vector.i — это файл интерфейса SWIG, который определяет модуль Python Vector. Он следует соглашениям для использования numpy.i, описанным в этой главе. Он определяет макрос SWIG %apply_numpy_typemaps, имеющий один аргумент TYPE. Он использует директиву SWIG %apply для применения предоставленных typemaps к сигнатурам аргументов, найденных в Vector.h. Этот макрос затем реализуется для всех поддерживаемых numpy.i типов данных. Затем он выполняет %include "Vector.h" для обертывания всех прототипов функций в Vector.h с использованием typemaps в numpy.i.

Тестирование скриптов Python

После использования make для построения модулей расширения тестирования, можно запустить testVector.py для выполнения тестов. Как и в других скриптах, использующих unittest для облегчения модульного тестирования, testVector.py определяет класс, который наследуется от unittest.TestCase.

class VectorTestCase(unittest.TestCase):

Однако этот класс не запускается напрямую. Вместо этого он служит базовым классом для нескольких других классов Python, каждый из которых специфичен для определенного типа данных. Класс VectorTestCase хранит две строки для информации о типе:

self.typeStr
Строка, которая соответствует одному из префиксов SNAME используемых в Vector.h и Vector.cxx. Например, "double".
self.typeCode
Короткая (обычно односимвольная) строка, представляющая тип данных в numpy и соответствующая self.typeStr. Например, если self.typeStr равно "double", то self.typeCode должно быть "d".

Каждый тест, определенный классом VectorTestCase, извлекает функцию Python, которую он пытается протестировать, обращаясь к словарю модуля Vector.

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, который затем выполняется. Ошибки и сбои суммируются и возвращаются в качестве аргумента выхода. Любой ненулевой результат указывает на то, что по крайней мере один тест не прошел.

© 2008–2016 NumPy Developers
Licensed under the NumPy License.
https://docs.scipy.org/doc/numpy-1.11.0/reference/swig.testing.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API