Skip to content

Commit

Permalink
Added feature tests (#3)
Browse files Browse the repository at this point in the history
* Added feature tests

* Added filter to test configuration

* Explicitly added configuration file
  • Loading branch information
vladvildanov authored Feb 6, 2024
1 parent 8e0f9b5 commit 16137d5
Show file tree
Hide file tree
Showing 11 changed files with 318 additions and 8 deletions.
40 changes: 38 additions & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ concurrency:
cancel-in-progress: true

jobs:
tests:
unit_tests:
name: Unit tests
runs-on: ubuntu-latest
strategy:
Expand All @@ -32,7 +32,7 @@ jobs:
dependency-versions: highest

- name: Run unit tests
run: vendor/bin/phpunit --testsuite Unit --coverage-clover build/logs/clover.xml --coverage-filter ./src
run: vendor/bin/phpunit -c phpunit.xml.dist --testsuite Unit --coverage-clover build/logs/clover.xml --coverage-filter ./src

- name: Upload codecov coverage
uses: codecov/codecov-action@v3
Expand All @@ -42,3 +42,39 @@ jobs:
verbose: true
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

feature_tests:
name: Feature tests
runs-on: ubuntu-latest

services:
redis:
image: redis/redis-stack-server:${{ matrix.redis_stack }}
options: --health-cmd="redis-cli ping" --health-interval=10s --health-timeout=5s --health-retries=3
ports:
- 6379:6379

strategy:
fail-fast: false
matrix:
redis_stack:
- latest
- edge

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Setup PHP with Composer and extensions
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
coverage: xdebug

- name: Install Composer dependencies
uses: ramsey/composer-install@v2
with:
dependency-versions: highest

- name: Run feature tests
run: vendor/bin/phpunit -c phpunit.xml.dist --testsuite Feature
5 changes: 5 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
"Vladvildanov\\PredisVl\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Vladvildanov\\PredisVl\\": "tests/"
}
},
"authors": [
{
"name": "vladvildanov",
Expand Down
16 changes: 16 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,27 @@
<testsuite name="Unit">
<directory>tests/Unit/</directory>
</testsuite>
<testsuite name="Feature">
<directory>tests/Feature/</directory>
</testsuite>
</testsuites>

<source>
<include>
<directory>./src</directory>
</include>
</source>

<coverage>
<report>
<clover outputFile="build/logs/clover.xml"/>
</report>
</coverage>

<php>
<!-- Redis -->
<const name="REDIS_SERVER_HOST" value="127.0.0.1" />
<const name="REDIS_SERVER_PORT" value="6379" />
<const name="REDIS_SERVER_DBNUM" value="0" />
</php>
</phpunit>
48 changes: 48 additions & 0 deletions tests/Feature/FeatureTestCase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

namespace Vladvildanov\PredisVl\Feature;

use PHPUnit\Framework\TestCase;
use Predis\Client;

abstract class FeatureTestCase extends TestCase
{
/**
* Returns a named array with default values for connection parameters.
*
* @return array Default connection parameters
*/
protected function getDefaultParametersArray(): array
{
return [
'scheme' => 'tcp',
'host' => constant('REDIS_SERVER_HOST'),
'port' => constant('REDIS_SERVER_PORT'),
'database' => constant('REDIS_SERVER_DBNUM'),
];
}

/**
* Creates Redis client with default or given configuration.
*
* @param array|null $parameters
* @param array|null $options
* @param bool|null $flushDB
* @return Client
*/
protected function getClient(?array $parameters = null, ?array $options = null, ?bool $flushDB = true): Client
{
$parameters = array_merge(
$this->getDefaultParametersArray(),
$parameters ?: []
);

$client = new Client($parameters, $options);

if ($flushDB) {
$client->flushdb();
}

return $client;
}
}
205 changes: 205 additions & 0 deletions tests/Feature/Index/SearchIndexTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
<?php

namespace Vladvildanov\PredisVl\Feature\Index;

use Vladvildanov\PredisVl\Feature\FeatureTestCase;
use Predis\Client;
use Vladvildanov\PredisVl\Index\SearchIndex;
use Vladvildanov\PredisVl\VectorHelper;

class SearchIndexTest extends FeatureTestCase
{
/**
* @var Client
*/
private Client $client;

/**
* @var array
*/
private array $hashSchema;

/**
* @var array
*/
private array $jsonSchema;

protected function setUp(): void
{
$this->client = $this->getClient();
$this->hashSchema = [
'index' => [
'name' => 'foobar',
'prefix' => 'foo:',
],
'fields' => [
'id' => [
'type' => 'text',
'alias' => 'foo',
],
'count' => [
'type' => 'numeric',
],
'id_embeddings' => [
'type' => 'vector',
'algorithm' => 'flat',
'dims' => 3,
'datatype' => 'float32',
'distance_metric' => 'cosine',
]
]
];
$this->jsonSchema = [
'index' => [
'name' => 'foobar',
'prefix' => 'foo:',
'storage_type' => 'json'
],
'fields' => [
'$.id' => [
'type' => 'text',
'alias' => 'foo',
],
'$.count' => [
'type' => 'numeric',
],
'$.id_embeddings' => [
'type' => 'vector',
'algorithm' => 'flat',
'dims' => 3,
'datatype' => 'float32',
'distance_metric' => 'cosine',
]
]
];
}

/**
* @return void
*/
public function testCreatesHashIndexWithMultipleFields(): void
{
$index = new SearchIndex($this->client, $this->hashSchema);
$this->assertEquals('OK', $index->create());

$indexInfo = $this->client->ftinfo($this->hashSchema['index']['name']);

$this->assertEquals('foobar', $indexInfo[1]);
$this->assertEquals('HASH', $indexInfo[5][1]);
$this->assertEquals('foo:', $indexInfo[5][3][0]);
$this->assertEquals('foo', $indexInfo[7][0][3]);
$this->assertEquals('TEXT', $indexInfo[7][0][5]);
$this->assertEquals('NUMERIC', $indexInfo[7][1][5]);
$this->assertEquals('VECTOR', $indexInfo[7][2][5]);

$this->assertEquals(
'OK',
$index->load('foo:1', ['id' => '1', 'count' => 10, 'id_embeddings' => VectorHelper::toBytes([0.000001, 0.000002, 0.000003])])
);

$searchResult = $this->client->ftsearch($this->hashSchema['index']['name'], '*');

$this->assertSame('foo:1', $searchResult[1]);
$this->assertSame('1', $searchResult[2][1]);
$this->assertSame('10', $searchResult[2][3]);
$this->assertSame(VectorHelper::toBytes([0.000001, 0.000002, 0.000003]), $searchResult[2][5]);
}

/**
* @return void
*/
public function testCreatesJsonIndexWithMultipleFields(): void
{
$index = new SearchIndex($this->client, $this->jsonSchema);
$this->assertEquals('OK', $index->create());

$indexInfo = $this->client->ftinfo($this->jsonSchema['index']['name']);

$this->assertEquals('foobar', $indexInfo[1]);
$this->assertEquals('JSON', $indexInfo[5][1]);
$this->assertEquals('foo:', $indexInfo[5][3][0]);
$this->assertEquals('foo', $indexInfo[7][0][3]);
$this->assertEquals('TEXT', $indexInfo[7][0][5]);
$this->assertEquals('NUMERIC', $indexInfo[7][1][5]);
$this->assertEquals('VECTOR', $indexInfo[7][2][5]);

$this->assertEquals(
'OK',
$index->load('foo:1', '{"id":"1","count":10,"id_embeddings":[0.000001, 0.000002, 0.000003]}')
);

$searchResult = $this->client->ftsearch($this->jsonSchema['index']['name'], '*');

$this->assertSame('foo:1', $searchResult[1]);
$this->assertSame('{"id":"1","count":10,"id_embeddings":[1e-6,2e-6,3e-6]}', $searchResult[2][1]);
}

/**
* @return void
*/
public function testCreatesHashIndexWithOverride(): void
{
$index = new SearchIndex($this->client, $this->hashSchema);
$this->assertEquals('OK', $index->create());

$indexInfo = $this->client->ftinfo($this->hashSchema['index']['name']);

$this->assertEquals('foobar', $indexInfo[1]);
$this->assertEquals('HASH', $indexInfo[5][1]);
$this->assertEquals('foo:', $indexInfo[5][3][0]);
$this->assertEquals('foo', $indexInfo[7][0][3]);
$this->assertEquals('TEXT', $indexInfo[7][0][5]);
$this->assertEquals('NUMERIC', $indexInfo[7][1][5]);
$this->assertEquals('VECTOR', $indexInfo[7][2][5]);

$this->assertEquals('OK', $index->create(true));

$this->assertEquals(
'OK',
$index->load('foo:1', ['id' => '1', 'count' => 10, 'id_embeddings' => VectorHelper::toBytes([0.000001, 0.000002, 0.000003])])
);

$searchResult = $this->client->ftsearch($this->hashSchema['index']['name'], '*');

$this->assertSame('foo:1', $searchResult[1]);
$this->assertSame('1', $searchResult[2][1]);
$this->assertSame('10', $searchResult[2][3]);
$this->assertSame(VectorHelper::toBytes([0.000001, 0.000002, 0.000003]), $searchResult[2][5]);
}

/**
* @return void
*/
public function testFetchHashData(): void
{
$index = new SearchIndex($this->client, $this->hashSchema);
$this->assertEquals('OK', $index->create());

$this->assertEquals(
'OK',
$index->load('foo:1', ['id' => '1', 'count' => 10, 'id_embeddings' => VectorHelper::toBytes([0.000001, 0.000002, 0.000003])])
);

$this->assertEquals(
['id' => '1', 'count' => 10, 'id_embeddings' => VectorHelper::toBytes([0.000001, 0.000002, 0.000003])],
$index->fetch('1'));
}

/**
* @return void
*/
public function testFetchJsonData(): void
{
$index = new SearchIndex($this->client, $this->jsonSchema);
$this->assertEquals('OK', $index->create());

$this->assertEquals(
'OK',
$index->load('foo:1', '{"id":"1","count":10,"id_embeddings":[0.000001, 0.000002, 0.000003]}')
);

$this->assertEquals(
'{"id":"1","count":10,"id_embeddings":[1e-6,2e-6,3e-6]}',
$index->fetch('1'));
}
}
2 changes: 1 addition & 1 deletion tests/Unit/Enum/SearchFieldTest.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Unit\Enum;
namespace Vladvildanov\PredisVl\Unit\Enum;

use PHPUnit\Framework\TestCase;
use Predis\Command\Argument\Search\SchemaFields\NumericField;
Expand Down
2 changes: 1 addition & 1 deletion tests/Unit/FactoryTest.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Unit;
namespace Vladvildanov\PredisVl\Unit;

use PHPUnit\Framework\TestCase;
use Predis\Command\Argument\Search\CreateArguments;
Expand Down
2 changes: 1 addition & 1 deletion tests/Unit/Index/SearchIndexTest.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Unit\Index;
namespace Vladvildanov\PredisVl\Unit\Index;

use Exception;
use Mockery;
Expand Down
2 changes: 1 addition & 1 deletion tests/Unit/VectorHelperTest.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Unit;
namespace Vladvildanov\PredisVl\Unit;

use PHPUnit\Framework\TestCase;
use Vladvildanov\PredisVl\VectorHelper;
Expand Down
2 changes: 1 addition & 1 deletion tests/Unit/Vectorizer/FactoryTest.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace Unit\Vectorizer;
namespace Vladvildanov\PredisVl\Unit\Vectorizer;

use Exception;
use PHPUnit\Framework\TestCase;
Expand Down
Loading

0 comments on commit 16137d5

Please sign in to comment.