mirror of
https://github.com/pestphp/pest.git
synced 2026-03-06 15:57:21 +01:00
Merge pull request #303 from def-studio/matrix-datasets
Matrix datasets
This commit is contained in:
@ -51,36 +51,34 @@ final class Datasets
|
|||||||
/**
|
/**
|
||||||
* Resolves the current dataset to an array value.
|
* Resolves the current dataset to an array value.
|
||||||
*
|
*
|
||||||
* @param Traversable<int|string, mixed>|Closure|iterable<int|string, mixed>|string|null $data
|
* @param array<Closure|iterable<int|string, mixed>|string> $datasets
|
||||||
*
|
*
|
||||||
* @return array<string, mixed>
|
* @return array<string, mixed>
|
||||||
*/
|
*/
|
||||||
public static function resolve(string $description, $data): array
|
public static function resolve(string $description, array $datasets): array
|
||||||
{
|
{
|
||||||
/* @phpstan-ignore-next-line */
|
/* @phpstan-ignore-next-line */
|
||||||
if (is_null($data) || empty($data)) {
|
if (empty($datasets)) {
|
||||||
return [$description => []];
|
return [$description => []];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_string($data)) {
|
$datasets = self::processDatasets($datasets);
|
||||||
$data = self::get($data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_callable($data)) {
|
$datasetCombinations = self::getDataSetsCombinations($datasets);
|
||||||
$data = call_user_func($data);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($data instanceof Traversable) {
|
|
||||||
$data = iterator_to_array($data);
|
|
||||||
}
|
|
||||||
|
|
||||||
$dataSetDescriptions = [];
|
$dataSetDescriptions = [];
|
||||||
$dataSetValues = [];
|
$dataSetValues = [];
|
||||||
|
|
||||||
foreach ($data as $key => $values) {
|
foreach ($datasetCombinations as $datasetCombination) {
|
||||||
$values = is_array($values) ? $values : [$values];
|
$partialDescriptions = [];
|
||||||
|
$values = [];
|
||||||
|
|
||||||
$dataSetDescriptions[] = $description . self::getDataSetDescription($key, $values);
|
foreach ($datasetCombination as $dataset_data) {
|
||||||
|
$partialDescriptions[] = $dataset_data['label'];
|
||||||
|
$values = array_merge($values, $dataset_data['values']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$dataSetDescriptions[] = $description . ' with ' . implode(' / ', $partialDescriptions);
|
||||||
$dataSetValues[] = $values;
|
$dataSetValues[] = $values;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,6 +101,65 @@ final class Datasets
|
|||||||
return $namedData;
|
return $namedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<Closure|iterable<int|string, mixed>|string> $datasets
|
||||||
|
*
|
||||||
|
* @return array<array>
|
||||||
|
*/
|
||||||
|
private static function processDatasets(array $datasets): array
|
||||||
|
{
|
||||||
|
$processedDatasets = [];
|
||||||
|
|
||||||
|
foreach ($datasets as $index => $data) {
|
||||||
|
$processedDataset = [];
|
||||||
|
|
||||||
|
if (is_string($data)) {
|
||||||
|
$datasets[$index] = self::get($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_callable($datasets[$index])) {
|
||||||
|
$datasets[$index] = call_user_func($datasets[$index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($datasets[$index] instanceof Traversable) {
|
||||||
|
$datasets[$index] = iterator_to_array($datasets[$index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($datasets[$index] as $key => $values) {
|
||||||
|
$values = is_array($values) ? $values : [$values];
|
||||||
|
$processedDataset[] = [
|
||||||
|
'label' => self::getDataSetDescription($key, $values),
|
||||||
|
'values' => $values,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$processedDatasets[] = $processedDataset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $processedDatasets;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<array> $combinations
|
||||||
|
*
|
||||||
|
* @return array<array>
|
||||||
|
*/
|
||||||
|
private static function getDataSetsCombinations(array $combinations): array
|
||||||
|
{
|
||||||
|
$result = [[]];
|
||||||
|
foreach ($combinations as $index => $values) {
|
||||||
|
$tmp = [];
|
||||||
|
foreach ($result as $resultItem) {
|
||||||
|
foreach ($values as $value) {
|
||||||
|
$tmp[] = array_merge($resultItem, [$index => $value]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$result = $tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int|string $key
|
* @param int|string $key
|
||||||
* @param array<int, mixed> $data
|
* @param array<int, mixed> $data
|
||||||
@ -112,9 +169,9 @@ final class Datasets
|
|||||||
$exporter = new Exporter();
|
$exporter = new Exporter();
|
||||||
|
|
||||||
if (is_int($key)) {
|
if (is_int($key)) {
|
||||||
return \sprintf(' with (%s)', $exporter->shortenedRecursiveExport($data));
|
return \sprintf('(%s)', $exporter->shortenedRecursiveExport($data));
|
||||||
}
|
}
|
||||||
|
|
||||||
return \sprintf(' with data set "%s"', $key);
|
return \sprintf('data set "%s"', $key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -62,9 +62,9 @@ final class TestCaseFactory
|
|||||||
/**
|
/**
|
||||||
* Holds the dataset, if any.
|
* Holds the dataset, if any.
|
||||||
*
|
*
|
||||||
* @var Closure|iterable<int|string, mixed>|string|null
|
* @var array<Closure|iterable<int|string, mixed>|string>
|
||||||
*/
|
*/
|
||||||
public $dataset;
|
public $datasets = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The FQN of the test case class.
|
* The FQN of the test case class.
|
||||||
@ -155,7 +155,7 @@ final class TestCaseFactory
|
|||||||
return $testCase;
|
return $testCase;
|
||||||
};
|
};
|
||||||
|
|
||||||
$datasets = Datasets::resolve($this->description, $this->dataset);
|
$datasets = Datasets::resolve($this->description, $this->datasets);
|
||||||
|
|
||||||
return array_map($createTest, array_keys($datasets), $datasets);
|
return array_map($createTest, array_keys($datasets), $datasets);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -77,11 +77,13 @@ final class TestCall
|
|||||||
* Runs the current test multiple times with
|
* Runs the current test multiple times with
|
||||||
* each item of the given `iterable`.
|
* each item of the given `iterable`.
|
||||||
*
|
*
|
||||||
* @param \Closure|iterable<int|string, mixed>|string $data
|
* @param array<\Closure|iterable<int|string, mixed>|string> $data
|
||||||
*/
|
*/
|
||||||
public function with($data): TestCall
|
public function with(...$data): TestCall
|
||||||
{
|
{
|
||||||
$this->testCaseFactory->dataset = $data;
|
foreach ($data as $dataset) {
|
||||||
|
$this->testCaseFactory->datasets[] = $dataset;
|
||||||
|
}
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -51,6 +51,45 @@
|
|||||||
✓ it creates unique test case names with ('Name 2', Pest\Plugin Object (), true)
|
✓ it creates unique test case names with ('Name 2', Pest\Plugin Object (), true)
|
||||||
✓ it creates unique test case names with ('Name 1', Pest\Plugin Object (), true) #3
|
✓ it creates unique test case names with ('Name 1', Pest\Plugin Object (), true) #3
|
||||||
✓ it creates unique test case names - count
|
✓ it creates unique test case names - count
|
||||||
|
✓ lazy multiple datasets with (1) / (3)
|
||||||
|
✓ lazy multiple datasets with (1) / (4)
|
||||||
|
✓ lazy multiple datasets with (2) / (3)
|
||||||
|
✓ lazy multiple datasets with (2) / (4)
|
||||||
|
✓ lazy multiple datasets did the job right
|
||||||
|
✓ eager multiple datasets with (1) / (3)
|
||||||
|
✓ eager multiple datasets with (1) / (4)
|
||||||
|
✓ eager multiple datasets with (2) / (3)
|
||||||
|
✓ eager multiple datasets with (2) / (4)
|
||||||
|
✓ eager multiple datasets did the job right
|
||||||
|
✓ lazy registered multiple datasets with (1) / (1)
|
||||||
|
✓ lazy registered multiple datasets with (1) / (2)
|
||||||
|
✓ lazy registered multiple datasets with (2) / (1)
|
||||||
|
✓ lazy registered multiple datasets with (2) / (2)
|
||||||
|
✓ lazy registered multiple datasets did the job right
|
||||||
|
✓ eager registered multiple datasets with (1) / (1)
|
||||||
|
✓ eager registered multiple datasets with (1) / (2)
|
||||||
|
✓ eager registered multiple datasets with (2) / (1)
|
||||||
|
✓ eager registered multiple datasets with (2) / (2)
|
||||||
|
✓ eager registered multiple datasets did the job right
|
||||||
|
✓ eager wrapped registered multiple datasets with (1) / (1)
|
||||||
|
✓ eager wrapped registered multiple datasets with (1) / (2)
|
||||||
|
✓ eager wrapped registered multiple datasets with (2) / (1)
|
||||||
|
✓ eager wrapped registered multiple datasets with (2) / (2)
|
||||||
|
✓ eager wrapped registered multiple datasets did the job right
|
||||||
|
✓ named multiple datasets with data set "one" / data set "three"
|
||||||
|
✓ named multiple datasets with data set "one" / data set "four"
|
||||||
|
✓ named multiple datasets with data set "two" / data set "three"
|
||||||
|
✓ named multiple datasets with data set "two" / data set "four"
|
||||||
|
✓ named multiple datasets did the job right
|
||||||
|
✓ more than two datasets with (1) / (3) / (5)
|
||||||
|
✓ more than two datasets with (1) / (3) / (6)
|
||||||
|
✓ more than two datasets with (1) / (4) / (5)
|
||||||
|
✓ more than two datasets with (1) / (4) / (6)
|
||||||
|
✓ more than two datasets with (2) / (3) / (5)
|
||||||
|
✓ more than two datasets with (2) / (3) / (6)
|
||||||
|
✓ more than two datasets with (2) / (4) / (5)
|
||||||
|
✓ more than two datasets with (2) / (4) / (6)
|
||||||
|
✓ more than two datasets did the job right
|
||||||
|
|
||||||
PASS Tests\Features\Exceptions
|
PASS Tests\Features\Exceptions
|
||||||
✓ it gives access the the underlying expectException
|
✓ it gives access the the underlying expectException
|
||||||
@ -174,6 +213,9 @@
|
|||||||
PASS Tests\Unit\Datasets
|
PASS Tests\Unit\Datasets
|
||||||
✓ it show only the names of named datasets in their description
|
✓ it show only the names of named datasets in their description
|
||||||
✓ it show the actual dataset of non-named datasets in their description
|
✓ it show the actual dataset of non-named datasets in their description
|
||||||
|
✓ it show only the names of multiple named datasets in their description
|
||||||
|
✓ it show the actual dataset of multiple non-named datasets in their description
|
||||||
|
✓ it show the correct description for mixed named and not-named datasets
|
||||||
|
|
||||||
PASS Tests\Unit\Plugins\Version
|
PASS Tests\Unit\Plugins\Version
|
||||||
✓ it outputs the version when --version is used
|
✓ it outputs the version when --version is used
|
||||||
@ -224,5 +266,5 @@
|
|||||||
✓ it is a test
|
✓ it is a test
|
||||||
✓ it uses correct parent class
|
✓ it uses correct parent class
|
||||||
|
|
||||||
Tests: 7 skipped, 122 passed
|
Tests: 7 skipped, 164 passed
|
||||||
|
|
||||||
@ -137,3 +137,89 @@ it('creates unique test case names', function (string $name, Plugin $plugin, boo
|
|||||||
it('creates unique test case names - count', function () use (&$counter) {
|
it('creates unique test case names - count', function () use (&$counter) {
|
||||||
expect($counter)->toBe(6);
|
expect($counter)->toBe(6);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$datasets_a = [[1], [2]];
|
||||||
|
$datasets_b = [[3], [4]];
|
||||||
|
|
||||||
|
test('lazy multiple datasets', function ($text_a, $text_b) use ($state, $datasets_a, $datasets_b) {
|
||||||
|
$state->text .= $text_a . $text_b;
|
||||||
|
expect($datasets_a)->toContain([$text_a]);
|
||||||
|
expect($datasets_b)->toContain([$text_b]);
|
||||||
|
})->with($datasets_a, $datasets_b);
|
||||||
|
|
||||||
|
test('lazy multiple datasets did the job right', function () use ($state) {
|
||||||
|
expect($state->text)->toBe('12121212121213142324');
|
||||||
|
});
|
||||||
|
|
||||||
|
$state->text = '';
|
||||||
|
|
||||||
|
test('eager multiple datasets', function ($text_a, $text_b) use ($state, $datasets_a, $datasets_b) {
|
||||||
|
$state->text .= $text_a . $text_b;
|
||||||
|
expect($datasets_a)->toContain([$text_a]);
|
||||||
|
expect($datasets_b)->toContain([$text_b]);
|
||||||
|
})->with(function () use ($datasets_a) {
|
||||||
|
return $datasets_a;
|
||||||
|
})->with(function () use ($datasets_b) {
|
||||||
|
return $datasets_b;
|
||||||
|
});
|
||||||
|
|
||||||
|
test('eager multiple datasets did the job right', function () use ($state) {
|
||||||
|
expect($state->text)->toBe('1212121212121314232413142324');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('lazy registered multiple datasets', function ($text_a, $text_b) use ($state, $datasets) {
|
||||||
|
$state->text .= $text_a . $text_b;
|
||||||
|
expect($datasets)->toContain([$text_a]);
|
||||||
|
expect($datasets)->toContain([$text_b]);
|
||||||
|
})->with('numbers.array')->with('numbers.array');
|
||||||
|
|
||||||
|
test('lazy registered multiple datasets did the job right', function () use ($state) {
|
||||||
|
expect($state->text)->toBe('121212121212131423241314232411122122');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('eager registered multiple datasets', function ($text_a, $text_b) use ($state, $datasets) {
|
||||||
|
$state->text .= $text_a . $text_b;
|
||||||
|
expect($datasets)->toContain([$text_a]);
|
||||||
|
expect($datasets)->toContain([$text_b]);
|
||||||
|
})->with('numbers.array')->with('numbers.closure');
|
||||||
|
|
||||||
|
test('eager registered multiple datasets did the job right', function () use ($state) {
|
||||||
|
expect($state->text)->toBe('12121212121213142324131423241112212211122122');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('eager wrapped registered multiple datasets', function ($text_a, $text_b) use ($state, $datasets) {
|
||||||
|
$state->text .= $text_a . $text_b;
|
||||||
|
expect($datasets)->toContain([$text_a]);
|
||||||
|
expect($datasets)->toContain([$text_b]);
|
||||||
|
})->with('numbers.closure.wrapped')->with('numbers.closure');
|
||||||
|
|
||||||
|
test('eager wrapped registered multiple datasets did the job right', function () use ($state) {
|
||||||
|
expect($state->text)->toBe('1212121212121314232413142324111221221112212211122122');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('named multiple datasets', function ($text_a, $text_b) use ($state, $datasets_a, $datasets_b) {
|
||||||
|
$state->text .= $text_a . $text_b;
|
||||||
|
expect($datasets_a)->toContain([$text_a]);
|
||||||
|
expect($datasets_b)->toContain([$text_b]);
|
||||||
|
})->with([
|
||||||
|
'one' => [1],
|
||||||
|
'two' => [2],
|
||||||
|
])->with([
|
||||||
|
'three' => [3],
|
||||||
|
'four' => [4],
|
||||||
|
]);
|
||||||
|
|
||||||
|
test('named multiple datasets did the job right', function () use ($state) {
|
||||||
|
expect($state->text)->toBe('121212121212131423241314232411122122111221221112212213142324');
|
||||||
|
});
|
||||||
|
|
||||||
|
test('more than two datasets', function ($text_a, $text_b, $text_c) use ($state, $datasets_a, $datasets_b) {
|
||||||
|
$state->text .= $text_a . $text_b . $text_c;
|
||||||
|
expect($datasets_a)->toContain([$text_a]);
|
||||||
|
expect($datasets_b)->toContain([$text_b]);
|
||||||
|
expect([5, 6])->toContain($text_c);
|
||||||
|
})->with($datasets_a, $datasets_b)->with([5, 6]);
|
||||||
|
|
||||||
|
test('more than two datasets did the job right', function () use ($state) {
|
||||||
|
expect($state->text)->toBe('121212121212131423241314232411122122111221221112212213142324135136145146235236245246');
|
||||||
|
});
|
||||||
|
|||||||
@ -4,8 +4,10 @@ use Pest\Datasets;
|
|||||||
|
|
||||||
it('show only the names of named datasets in their description', function () {
|
it('show only the names of named datasets in their description', function () {
|
||||||
$descriptions = array_keys(Datasets::resolve('test description', [
|
$descriptions = array_keys(Datasets::resolve('test description', [
|
||||||
'one' => [1],
|
[
|
||||||
'two' => [[2]],
|
'one' => [1],
|
||||||
|
'two' => [[2]],
|
||||||
|
],
|
||||||
]));
|
]));
|
||||||
|
|
||||||
expect($descriptions[0])->toBe('test description with data set "one"');
|
expect($descriptions[0])->toBe('test description with data set "one"');
|
||||||
@ -14,10 +16,66 @@ it('show only the names of named datasets in their description', function () {
|
|||||||
|
|
||||||
it('show the actual dataset of non-named datasets in their description', function () {
|
it('show the actual dataset of non-named datasets in their description', function () {
|
||||||
$descriptions = array_keys(Datasets::resolve('test description', [
|
$descriptions = array_keys(Datasets::resolve('test description', [
|
||||||
[1],
|
[
|
||||||
[[2]],
|
[1],
|
||||||
|
[[2]],
|
||||||
|
],
|
||||||
]));
|
]));
|
||||||
|
|
||||||
expect($descriptions[0])->toBe('test description with (1)');
|
expect($descriptions[0])->toBe('test description with (1)');
|
||||||
expect($descriptions[1])->toBe('test description with (array(2))');
|
expect($descriptions[1])->toBe('test description with (array(2))');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('show only the names of multiple named datasets in their description', function () {
|
||||||
|
$descriptions = array_keys(Datasets::resolve('test description', [
|
||||||
|
[
|
||||||
|
'one' => [1],
|
||||||
|
'two' => [[2]],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
'three' => [3],
|
||||||
|
'four' => [[4]],
|
||||||
|
],
|
||||||
|
]));
|
||||||
|
|
||||||
|
expect($descriptions[0])->toBe('test description with data set "one" / data set "three"');
|
||||||
|
expect($descriptions[1])->toBe('test description with data set "one" / data set "four"');
|
||||||
|
expect($descriptions[2])->toBe('test description with data set "two" / data set "three"');
|
||||||
|
expect($descriptions[3])->toBe('test description with data set "two" / data set "four"');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('show the actual dataset of multiple non-named datasets in their description', function () {
|
||||||
|
$descriptions = array_keys(Datasets::resolve('test description', [
|
||||||
|
[
|
||||||
|
[1],
|
||||||
|
[[2]],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[3],
|
||||||
|
[[4]],
|
||||||
|
],
|
||||||
|
]));
|
||||||
|
|
||||||
|
expect($descriptions[0])->toBe('test description with (1) / (3)');
|
||||||
|
expect($descriptions[1])->toBe('test description with (1) / (array(4))');
|
||||||
|
expect($descriptions[2])->toBe('test description with (array(2)) / (3)');
|
||||||
|
expect($descriptions[3])->toBe('test description with (array(2)) / (array(4))');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('show the correct description for mixed named and not-named datasets', function () {
|
||||||
|
$descriptions = array_keys(Datasets::resolve('test description', [
|
||||||
|
[
|
||||||
|
'one' => [1],
|
||||||
|
[[2]],
|
||||||
|
],
|
||||||
|
[
|
||||||
|
[3],
|
||||||
|
'four' => [[4]],
|
||||||
|
],
|
||||||
|
]));
|
||||||
|
|
||||||
|
expect($descriptions[0])->toBe('test description with data set "one" / (3)');
|
||||||
|
expect($descriptions[1])->toBe('test description with data set "one" / data set "four"');
|
||||||
|
expect($descriptions[2])->toBe('test description with (array(2)) / (3)');
|
||||||
|
expect($descriptions[3])->toBe('test description with (array(2)) / data set "four"');
|
||||||
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user