Commit 004105c7 authored by Mike Ryan's avatar Mike Ryan

#31: Implemented extractor tests.

parent 1ec7f933
Pipeline #49324134 passed with stage
in 2 minutes and 8 seconds
......@@ -18,8 +18,6 @@ class Csv extends CountableExtractorBase
public function extractAll(): iterable
{
$csv = $this->loadCsv();
// @todo configure the header
$csv->setHeaderOffset(0);
/** @var DataRecord $recordClass */
$recordClass = $this->configuration['record_class'];
foreach ($csv->getRecords() as $record) {
......@@ -45,7 +43,10 @@ class Csv extends CountableExtractorBase
*/
protected function loadCsv() : Reader
{
return Reader::createFromPath($this->configuration['csv_file_path'], 'r');
$csv = Reader::createFromPath($this->configuration['csv_file_path'], 'r');
// @todo configure the header
$csv->setHeaderOffset(0);
return $csv;
}
/**
......
......@@ -32,6 +32,8 @@ class DBAL extends CountableExtractorBase
} catch (DBALException $e) {
// @todo
}
$this->connection->close();
unset($this->connection);
}
/**
......
......@@ -51,7 +51,7 @@ abstract class ExtractorBase implements Extractor
*/
public function getProperties(): array
{
return $this->configuration[self::CONFIGURATION_PROPERTIES];
return $this->configuration[self::CONFIGURATION_PROPERTIES] ?? [];
}
/**
......@@ -59,6 +59,6 @@ abstract class ExtractorBase implements Extractor
*/
public function getKeyProperties(): array
{
return $this->configuration[self::CONFIGURATION_KEY_PROPERTIES];
return $this->configuration[self::CONFIGURATION_KEY_PROPERTIES] ?? [];
}
}
<?php
namespace Soong\Tests\Contracts\Extractor;
/**
* Base class for testing CountableExtractor implementations.
*
* Adds count() testing to ExtractorTestBase.
*/
abstract class CountableExtractorTestBase extends ExtractorTestBase
{
/**
* Test count().
*
* @dataProvider extractAllDataProvider
*
* @param array $configuration
* Extractor configuration.
* @param mixed $expected
* Expected set of data records returned.
*/
public function testCount(array $configuration, $expected)
{
$extractor = ($this->extractorClass)::create($configuration);
$this->assertEquals(count($expected), $extractor->count());
}
}
<?php
namespace Soong\Tests\Contracts\Extractor;
use PHPUnit\Framework\TestCase;
use Soong\Contracts\Extractor\Extractor;
/**
* Base class for testing Extractor implementations.
*
* To test an extractor class, extend this class and implement setUp(),
* assigning the fully-qualified class name to extractorClass:
*
* @code
* protected function setUp() : void
* {
* $this->extractorClass = '\Soong\Extractor\Array';
* }
* @endcode
*
* And implement a data provider, where each row of data provided contains a
* configuration array for the extractor, and the expected records to be
* extracted expressed as an array:
*
* @code
* public function extractAllDataProvider()
* {
* $dataSet1 = [
* [
* 'field1' => 'value1',
* 'field2' => 'value2',
* ...
* ],
* ...
* ];
* // Put the above data where the extractor will retrieve it from.
* $configuration1 = [
* 'data_record_class' => 'Soong\Data\Record',
* 'key_properties' => [
* 'field1' => ['type' => 'string'],
* ],
* ];
* return [
* 'set one' => [$configuration1, $dataSet1],
* ...
* ];
* }
* @endcode
*/
abstract class ExtractorTestBase extends TestCase
{
/**
* Fully-qualified name of a Extractor implementation.
*
* @var Extractor $extractorClass
*/
protected $extractorClass;
/**
* Test extractAll().
*
* @dataProvider extractAllDataProvider
*
* @param array $configuration
* Extractor configuration.
* @param array $expected
* Expected set of data records returned.
*/
public function testExtractAll(array $configuration, array $expected)
{
$extractor = ($this->extractorClass)::create($configuration);
reset($expected);
foreach ($extractor->extractAll() as $record) {
$this->assertEquals(current($expected), $record->toArray());
next($expected);
}
}
/**
* Test getProperties() and getKeyProperties().
*
* @dataProvider propertyDataProvider
*
* @param array $configuration
* Extractor configuration.
* @param array $expectedProperties
* Expected set of property metadata returned.
* @param array $expectedKeyProperties
* Expected set of key property metadata returned.
*/
public function testGetProperties(array $configuration, array $expectedProperties, array $expectedKeyProperties)
{
$extractor = ($this->extractorClass)::create($configuration);
$this->assertEquals($expectedProperties, $extractor->getProperties());
$this->assertEquals($expectedKeyProperties, $extractor->getKeyProperties());
}
}
<?php
namespace Soong\Tests\Extractor;
use Soong\Tests\Contracts\Extractor\CountableExtractorTestBase;
/**
* Tests the \Soong\Extractor\ArrayExtractor class.
*/
class ArrayExtractorTest extends CountableExtractorTestBase
{
/**
* Specify the class we're testing.
*/
protected function setUp() : void
{
$this->extractorClass = '\Soong\Extractor\ArrayExtractor';
}
/**
* Basic test data.
*
* @return array
*/
private function data() : array
{
return [
[
'positive integer' => 11,
'negative integer' => -23,
'numeric string' => '563',
'zero' => 0,
'empty string' => '',
'non-empty string' => 'a string',
'float' => 1.2345,
'null' => null,
'empty array' => [],
'non-empty array' => [1, 2, 'five'],
'keyed array' => ['a' => 'b', 'c' => 'd'],
'object' => new \stdClass(),
'true' => true,
'false' => false,
],
];
}
/**
* Key property configuration.
*
* @return array
*/
private function keyProperties() : array
{
return [
'positive integer' => [
'type' => 'integer',
]
];
}
/**
* Basic extractor configuration for testing.
*
* @return array
*/
private function configuration() : array
{
return [
// @todo replace with mock
'data_record_class' => 'Soong\Data\Record',
'key_properties' => $this->keyProperties(),
'data' => $this->data(),
];
}
/**
* Test extraction of various types of values
*
* @return array
*/
public function extractAllDataProvider() : array
{
return [
'set one' => [$this->configuration(), $this->data()],
];
}
/**
* Test retrieval of property metadata.
*
* @return array
*/
public function propertyDataProvider() : array
{
$properties = array_keys($this->data()[0]);
return [
'set one' => [$this->configuration(), $properties, $this->keyProperties()],
];
}
}
<?php
namespace Soong\Tests\Extractor;
use Soong\Tests\Contracts\Extractor\CountableExtractorTestBase;
/**
* Tests the \Soong\Extractor\Csv class.
*/
class CsvExtractorTest extends CountableExtractorTestBase
{
/**
* Specify the class we're testing.
*/
protected function setUp() : void
{
$this->extractorClass = '\Soong\Extractor\Csv';
}
/**
* Basic test data.
*
* @return array
*/
private function data() : array
{
return [
[
'positive integer' => 11,
'negative integer' => -23,
'numeric string' => '563',
'zero' => 0,
'empty string' => '',
'non-empty string' => 'a string',
'float' => 1.2345,
'null' => null,
],
];
}
/**
* Key property configuration.
*
* @return array
*/
private function keyProperties() : array
{
return [
'positive integer' => [
'type' => 'integer',
]
];
}
/**
* Basic extractor configuration for testing.
*
* @return array
*/
private function configuration() : array
{
return [
// @todo replace with mock
'record_class' => 'Soong\Data\Record',
'csv_file_path' => __DIR__ . '/../test_data/test.csv',
'key_properties' => $this->keyProperties(),
];
}
/**
* Test extraction of various types of values
*
* @return array
*/
public function extractAllDataProvider() : array
{
return [
'set one' => [$this->configuration(), $this->data()],
];
}
/**
* Test retrieval of property metadata.
*
* @return array
*/
public function propertyDataProvider() : array
{
$properties = array_keys($this->data()[0]);
return [
'set one' => [$this->configuration(), $properties, $this->keyProperties()],
];
}
}
<?php
namespace Soong\Tests\Extractor;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DriverManager;
use Doctrine\DBAL\Schema\Table;
use Soong\Tests\Contracts\Extractor\CountableExtractorTestBase;
/**
* Tests the \Soong\Extractor\DBAL class.
*/
class DBALExtractorTest extends CountableExtractorTestBase
{
/**
* @var Connection
*/
private $connection;
private $tableName = 'soong_dbal_test';
/**
* Specify the class we're testing.
*/
protected function setUp() : void
{
$this->extractorClass = '\Soong\Extractor\DBAL';
}
/**
* Basic test data.
*
* @return array
*/
private function data() : array
{
return [
[
'positive' => 11,
'negative' => -23,
'numeric' => '563',
'zero' => 0,
'emptystring' => '',
'string' => 'a string',
'float' => 1.2345,
'nullfield' => null,
],
];
}
/**
* Key property configuration.
*
* @return array
*/
private function keyProperties() : array
{
return [
'positive' => [
'type' => 'integer',
]
];
}
/**
* Basic extractor configuration for testing.
*
* @return array
*/
private function configuration() : array
{
return [
// @todo replace with mock
'data_record_class' => 'Soong\Data\Record',
'connection' => [
'url' => 'sqlite:///'. __DIR__ . '/../test_data/soong_test_db.sqlite'
],
'query' => 'SELECT * FROM ' . $this->tableName,
'key_properties' => $this->keyProperties(),
];
}
/**
* Test extraction of various types of values
*
* @return array
*/
public function extractAllDataProvider() : array
{
return [
'set one' => [$this->configuration(), $this->data()],
];
}
/**
* Test retrieval of property metadata.
*
* @return array
*/
public function propertyDataProvider() : array
{
$properties = [];
return [
'set one' => [$this->configuration(), $properties, $this->keyProperties()],
];
}
}
"positive integer","negative integer","numeric string","zero","empty string","non-empty string","float","null"
11,-23,"563",0,"","a string",1.2345,
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment