В документации PHPUnit есть небольшой раздел посвященный источникам данных (data provider), которые позволяют скормить тесту большой объем данных, а чуть ниже есть даже пример источника данных для CSV файла.
Конечно же, использовать полноценную электронную таблицу (spreadsheet)!
Договоримся что:
- Для каждого файла-теста существует свой файл с данными (всего один, вместо кучи CSV файлов)
- Данные внутри файла хранятся на отдельных страницах по одной для каждого теста, название страницы совпадает с названием теста (то ради чего все и затевалось)
И сразу перейдем к делу (минимум текста, максимум кода), весь код также доступен по ссылке внизу заметки:
Шаг #1: Зависимости
Нам понадобится (composer.json
):
{ "name": "PHPUnitSpreadsheetDataProvider", "require": { "php": ">=5.5.0", "phpunit/phpunit": "4.5.*", "phpoffice/phpexcel": "1.8.*" }, "autoload": { "classmap": [ "src/" ] } }
Шаг #2: Основная логика
Всё сводится к тому чтобы добавить собственный метод который будет получать данные из файла и превращать их в источник данных для тестов.
Получение:
<?php // PHPUnitTestCase.php trait PHPUnitSDP_PHPUnitTestCase { /** * @var PHPExcel_Reader_IReader|PHPExcel_Reader_Abstract */ private $_reader; /** * Возвращает пусть к ресурсу для теста. * * @param string $resource * * @return string */ protected function getTestResource($resource = null) { $path = (new ReflectionClass($this))->getFileName(); $dirname = pathinfo($path, PATHINFO_DIRNAME); $filename = pathinfo($path, PATHINFO_FILENAME); $resource = $resource ?: 'xml'; return "{$dirname}/{$filename}.{$resource}"; } /** * Возвращает данные для теста. * * @param string $test * * @return array|Iterator */ public function getTestDataProvider($test) { // Файл $position = 2; $resource = $this->getTestResource('data.ods'); // Reader? if (is_null($this->_reader)) { $this->_reader = PHPExcel_IOFactory::createReaderForFile($resource); } // Настройки $this->_reader->setReadDataOnly(true); $this->_reader->setLoadSheetsOnly($test); // Данные return new PHPUnitSDP_PHPExcelWorksheetRowIterator( $this->_reader->load($resource)->getActiveSheet(), $position); } }
Внимания заслуживают два момента (остальное, надеюсь, очевидно):
$position = 2;
— первая строка (нумерация начинается с 1) с данными, всё что до неё можно использовать для комментариев (см. пример ниже)$resource
— определяет название файла с данными, в данном случае это "ИмяТеста.data.ods
"
Превращение:
<?php // PHPExcelWorksheetRowIterator.php class PHPUnitSDP_PHPExcelWorksheetRowIterator extends PHPExcel_Worksheet_RowIterator { /** * @return array */ public function current() { $current = array(); foreach (parent::current()->getCellIterator() as $cell) { /* @var $cell PHPExcel_Cell */ $current[] = $this->getValue($cell->getCalculatedValue()); } return $current; } /** * @param mixed $value * * @return mixed */ protected function getValue($value) { switch (mb_strtolower(trim($value))) { case 'null': $value = null; break; case 'true': $value = true; break; case 'false': $value = false; break; default: /* empty */ break; } return $value; } }
Из особенностей стоит отметить возможность использования формул в ячейках, но от отдельного метода для конвертации значений отказаться все равно не получится — во-первых не для всех типов данных есть необходимые функции (тот же NULL
), во-вторых вычисление формул требует времени и ресурсов.
Шаг #3: Данные
Шаг #4: Тест
// SDPTest.php class SDPTest extends PHPUnit_Framework_TestCase { use PHPUnitSDP_PHPUnitTestCase; /** * @dataProvider getTestDataProvider * * @param number $base * @param number $exp * @param number $expected * * @return void */ public function testPow($base, $exp, $expected) { $this->assertEquals($expected, pow($base, $exp)); } /** * @dataProvider getTestDataProvider * * @param number $arg * @param number $expected * * @return void */ public function testSqrt($arg, $expected) { $this->assertEquals($expected, sqrt($arg)); } }
Вся магия заключена в аннотации @dataProvider getTestDataProvider
— перед запуском теста PHPUnit вызовет определенный ранее метод PHPUnitSDP_PHPUnitTestCase::getTestDataProvider()
с аргументом в котором содержится название теста и получит необходимый источник данных.
Шаг #5: Результат
PHPUnitSpreadsheetDataProvider> phpunit PHPUnit 4.5.0 by Sebastian Bergmann and contributors. Configuration read from PHPUnitSpreadsheetDataProvider/phpunit.xml ......F Time: 158 ms, Memory: 8.75Mb There was 1 failure: 1) SDPTest::testSqrt with data set #4 (4.0, 3.0) Failed asserting that 2.0 matches expected 3.0. PHPUnitSpreadsheetDataProvider/tests/SDPTest.php:28 phar://PHPUnitSpreadsheetDataProvider/phpunit.phar/phpunit/TextUI/Command.php:152 phar://PHPUnitSpreadsheetDataProvider/phpunit.phar/phpunit/TextUI/Command.php:104 FAILURES! Tests: 7, Assertions: 7, Failures: 1.
Заключение
Надеюсь данный рецепт кому-нибудь пригодится 🙂
Проект: yadi.sk/d/AyegnPCqf7i9Y
ссылка на оригинал статьи http://habrahabr.ru/post/252489/
Добавить комментарий