Skip to content

Commit

Permalink
Merge pull request #2 from phillipsdata/tests
Browse files Browse the repository at this point in the history
Unit tests
  • Loading branch information
clphillips committed Feb 23, 2016
2 parents 78f480c + 04f2b7d commit b72e5ef
Show file tree
Hide file tree
Showing 10 changed files with 499 additions and 4 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
vendor
composer.lock
.DS_Store
/nbproject/
/build/
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Csv

[![Build Status](https://travis-ci.org/phillipsdata/csv.svg?branch=master)](https://travis-ci.org/phillipsdata/csv) [![Coverage Status](https://coveralls.io/repos/phillipsdata/csv/badge.svg)](https://coveralls.io/r/phillipsdata/csv)

A CSV reader and writer with no external dependencies, that allows just in time
formatting and filtering, and operates on files as well as streams.

Expand Down
8 changes: 4 additions & 4 deletions src/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ public static function writer(
$enclosure = '"',
$escape = '\\'
) {
$file = static::fileObject($filename, 'w')
->setCsvControl($delimiter, $enclosure, $escape);
$file = static::fileObject($filename, 'w');
$file->setCsvControl($delimiter, $enclosure, $escape);
$writer = Writer::output($file);

return $writer;
Expand All @@ -47,8 +47,8 @@ public static function reader(
$escape = '\\',
$withHeader = true
) {
$file = static::fileObject($filename)
->setCsvControl($delimiter, $enclosure, $escape);
$file = static::fileObject($filename);
$file->setCsvControl($delimiter, $enclosure, $escape);
$reader = Reader::input($file, $withHeader);

return $reader;
Expand Down
49 changes: 49 additions & 0 deletions tests/Unit/FactoryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php
namespace PhillipsData\Csv\Tests\Unit;

use PhillipsData\Csv\Factory;
use PHPUnit_Framework_TestCase;

/**
* @coversDefaultClass \PhillipsData\Csv\Factory
*/
class FactoryTest extends PHPUnit_Framework_TestCase
{
/**
* @covers ::writer
* @covers ::fileObject
* @uses \PhillipsData\Csv\AbstractCsv
* @uses \PhillipsData\Csv\Writer
*/
public function testWriter()
{
$file = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Fixtures'
. DIRECTORY_SEPARATOR . 'non-existent-file.csv';

$this->assertInstanceOf(
'\PhillipsData\Csv\Writer',
Factory::writer($file)
);
$this->assertFileExists($file);

unlink($file);
}

/**
* @covers ::reader
* @covers ::fileObject
* @uses \PhillipsData\Csv\AbstractCsv
* @uses \PhillipsData\Csv\Reader
*/
public function testReader()
{
$file = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Fixtures'
. DIRECTORY_SEPARATOR . 'with-header.csv';

$this->assertInstanceOf(
'\PhillipsData\Csv\Reader',
Factory::reader($file)
);
$this->assertFileExists($file);
}
}
4 changes: 4 additions & 0 deletions tests/Unit/Fixtures/with-broken-header.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
"Heading 1","Heading 2"
"Cell 1","Cell 2","Cell 3"
"Cell 4","Cell 5","Cell 6"
"Cell 7","Cell 8","Cell 9"
4 changes: 4 additions & 0 deletions tests/Unit/Fixtures/with-header.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
"Heading 1","Heading 2","Heading 3"
"Cell 1","Cell 2","Cell 3"
"Cell 4","Cell 5","Cell 6"
"Cell 7","Cell 8","Cell 9"
3 changes: 3 additions & 0 deletions tests/Unit/Fixtures/without-header.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"Cell 1","Cell 2","Cell 3"
"Cell 4","Cell 5","Cell 6"
"Cell 7","Cell 8","Cell 9"
36 changes: 36 additions & 0 deletions tests/Unit/Map/MapIteratorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php
namespace PhillipsData\Csv\Tests\Unit\Map;

use PHPUnit_Framework_TestCase;
use PhillipsData\Csv\Map\MapIterator;
use ArrayIterator;

/**
* @coversDefaultClass \PhillipsData\Csv\Map\MapIterator
*/
class MapIteratorTest extends PHPUnit_Framework_TestCase
{
/**
* @covers ::__construct
* @covers ::current
*/
public function testCurrent()
{
$iterator = new ArrayIterator(['a', 'b', 'c']);

$actual = 0;
$map_iterator = new MapIterator(
$iterator,
function ($line) use (&$actual) {
$actual++;
return $line;
}
);

$expected = 0;
foreach ($map_iterator as $line) {
$expected++;
}
$this->assertEquals($expected, $actual);
}
}
224 changes: 224 additions & 0 deletions tests/Unit/ReaderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
<?php
namespace PhillipsData\Csv\Tests\Unit;

use PHPUnit_Framework_TestCase;
use PhillipsData\Csv\Reader;
use SplFileObject;

/**
* @coversDefaultClass \PhillipsData\Csv\Reader
*/
class ReaderTest extends PHPUnit_Framework_TestCase
{
/**
* Retrieves an instance of the Reader
*
* @return \PhillipsData\Csv\Reader
*/
private function getReader($headers = false, $headerType = 'without')
{
$filename = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'Fixtures'
. DIRECTORY_SEPARATOR . $headerType . '-header.csv';
return Reader::input(new SplFileObject($filename), $headers);
}

/**
* Data provider for attempting both with and without header CSVs
*/
public function inputProvider()
{
return array(
[false, 'without'],
[true, 'with'],
[true, 'with-broken']
);
}

/**
* @covers ::fetch
* @covers ::applyFilter
* @covers ::getAssocIterator
* @covers ::getFilterIterator
* @covers ::getFormatIterator
* @covers ::applyFormat
* @covers ::input
* @covers \PhillipsData\Csv\AbstractCsv
* @uses \PhillipsData\Csv\Map\MapIterator
*/
public function testFetch()
{
$reader = $this->getReader();
$this->assertInstanceOf(
'Iterator',
$reader->fetch()
);
}

/**
* @dataProvider inputProvider
* @covers ::input
* @covers ::fetch
* @covers ::applyFilter
* @covers ::getAssocIterator
* @covers ::getFilterIterator
* @covers ::getFormatIterator
* @covers ::applyFormat
* @covers ::setHeader
* @covers \PhillipsData\Csv\AbstractCsv
* @uses \PhillipsData\Csv\Map\MapIterator
*/
public function testFormat($headers, $headerType)
{
$reader = $this->getReader($headers, $headerType);
// Determine defaults for a line
$defaultLines = [];
foreach ($reader as $line) {
$defaultLines[] = $line;
}

// Format each CSV line
$reader->format(function ($line, $key, $iterator) {
$values = [];
foreach ($line as $cell) {
$values[] = $this->format($cell);
}

return $values;
});

// Check each cell has been formatted
foreach ($reader->fetch() as $i => $line) {
foreach ($line as $j => $cell) {
// The values should be different until formatted
$this->assertNotEquals(
$defaultLines[$i][$j],
$cell
);

// The values should be identical once formatted
$this->assertEquals(
$this->format($defaultLines[$i][$j]),
$cell
);
}
}
}

/**
* @dataProvider inputProvider
* @covers ::input
* @covers ::fetch
* @covers ::applyFilter
* @covers ::getAssocIterator
* @covers ::getFilterIterator
* @covers ::getFormatIterator
* @covers ::applyFormat
* @covers ::setHeader
* @covers \PhillipsData\Csv\AbstractCsv
* @uses \PhillipsData\Csv\Map\MapIterator
*/
public function testFilter($headers, $headerType)
{
$reader = $this->getReader($headers, $headerType);

$index = 1;
if ($headers) {
$index = 'Heading 2';
}

$reader->filter(function ($line) use ($index) {
// Only return values where the second column contains even numbers
return (preg_match('/[02468]+/', $line[$index]));
});

// Check that the CSV contains only the matching rows
foreach ($reader->fetch() as $i => $line) {
// Verify only rows where second column contains even numbers
$this->assertTrue((boolean) preg_match('/[02468]+/', $line[$index]));
}
}

/**
* Checks formatting when the CSV has fewer headings than columns
*
* @covers ::getAssocIterator
* @covers ::input
* @covers ::fetch
* @covers ::getFilterIterator
* @covers ::getFormatIterator
* @covers ::applyFormat
* @covers ::applyfilter
* @covers ::setHeader
* @covers \PhillipsData\Csv\AbstractCsv
* @uses \PhillipsData\Csv\Map\MapIterator
*/
public function testFormatHeaders()
{
$reader = $this->getReader(true, 'with-broken');

// Determine defaults for a line
$defaultLines = [];
foreach ($reader as $line) {
$defaultLines[] = $line;
}

// Format each CSV line
$reader->format(function ($line, $key, $iterator) {
$values = [];
foreach ($line as $cell) {
$values[] = $this->format($cell);
}

return $values;
});

// Add another formatter
$reader->format(function ($line, $key, $iterator) {
$values = [];
foreach ($line as $cell) {
$values[] = $this->formatHyphens($cell);
}

return $values;
});

// Check each cell has been formatted
foreach ($reader->fetch() as $i => $line) {
foreach ($line as $j => $cell) {
// The values should be different until formatted
$this->assertNotEquals(
$defaultLines[$i][$j],
$cell
);

$formattedCell = $this->format($defaultLines[$i][$j]);
$formattedCell = $this->formatHyphens($formattedCell);

// The values should be identical once formatted
$this->assertEquals(
$formattedCell,
$cell
);
}
}
}

/**
* @param string $text Text to format
* @return string The formatted text
*/
private function format($text)
{
return strtoupper($text);
}

/**
*
* @param string $text Text to format
* @return string The formatted text;
*/
private function formatHyphens($text)
{
return '-' . $text . '-';
}
}
Loading

0 comments on commit b72e5ef

Please sign in to comment.