(c) Mikhail Kamorin aka raptor_MVK
Package contains following components:
-
trait
ExtraUtilsTrait
that contains set of service methods used to make testing easier -
trait
ExtraAssertionsTrait
that contains set of additional assertions -
trait
WithVFSTrait
that provides adapted interface formikey179/vfsstream
(virtual file system) -
test data loader from JSON files that wraps each test case into test data container
-
command
generate-ide-test-containers
that generate service file for IDE used to autocomplete
The suggested installation method is via composer:
php composer.phar require raptor/test-utils:@stable
Add trait ExtraUtilsTrait
to the class that contains tests or to the common
base test class. After that the following static methods will be available:
-
invokeMethod(object $object, string $methodName, ?array $parameters = null)
invokes protected or private method with the given parameters -
expectExceptionExactMessage(string $message)
checks that an exception is thrown with exact given message
Add trait ExtraAssertionsTrait
to the class that contains tests or to the
common base test class. After that the following additional assertions will be
available:
-
assertArraysAreSame(array $expected, array $actual, ?string $message = null)
checks the assertion that two arrays are same (order of elements, their types coincides at every level). Before checking, arrays are encoded as JSON strings, therefore you cannot use objects or functions as elements of an array. -
assertArraysAreSameIgnoringOrder(array $expected, array $actual, ?string $message = null)
checks the assertion that two associative arrays contains same elements (at every level) ignoring their order at the top level. Before checking, arrays are encoded as JSON strings, therefore you cannot use objects or functions as elements of an array. -
assertArraysAreSameIgnoringOrderRecursive(array $expected, array $actual, ?string $message = null)
checks the assertion that two associative arrays contains same elements ignoring their order at every level. Before checking, arrays are encoded as JSON strings, therefore you cannot use objects or functions as elements of an array. -
assertReturnsCarbonNow(callable $func, ?string $message = null)
checks the assertion that the given function returns result ofCarbon::now()
, invoked while running -
assertReturnsCarbonNowWithoutMicroseconds(callable $func, ?string $message = null)
checks the assertion that the given function returns result ofCarbon::now()
, invoked while running, with zeroed microseconds -
assertStringsAreSameIgnoringEOL(string $expected, string $actual, ?string $message = null)
checks the assertion that two given strings are same ignoring the difference in EOL characters
Add trait WithVFSTrait
to the class that contains tests or to the common base
test class. Method setupVFS
should be used in setUp
method or in the test
method just before using other methods of the trait. No tearDown actions is
needed regarding virtual file system. After that the following additional
methods will be available:
-
addFileToVFS(string $filename, ?int $permissions = null, ?string $content = null)
adds file with given permissions and content to virtual file system. -
addDirectoryToVFS(string $dirname, ?int $permissions = null)
adds directory with given permissions to virtual file system -
addStructure(array $structure)
adds directory structure to virtual file system. Structure is represented as a tree, where leaves are files with key as the file name and value as the file content -
getFullPath(string $path)
returns full path to the file that is used outside virtual file system
Data loader allows you to extract test data from data provider into separate JSON file. As a result of data loading a set of test cases is formed, where data for each test case is wrapped into container object. Values of specific fields from file are returned by getters. Such an approach allows you to solve the following tasks:
-
extract test data from code to separate JSON files
-
pass into testing method many parameters without inflating method signature
-
organize test data into hierarchical structure, when there is common data in several test cases
Requirements to JSON file:
-
file should contain array of JSON objects, array may contain single object
-
field names should not start with underscore except cases specifically noted below
-
field names should contain only lowercase letters, digits and underscore
-
each object of the array should belong to one of two types:
-
Test case. Such objects should not contain service field
_children
and should contain service field_name
-
Array of test cases with default values for some fields. Such objects should contain service field
_children
and should not contain service field_name
-
-
service field
_name
should contain string, it is name of the test case -
values of service field
_name
should be unique and non-empty -
service field
_children
should contain array, that meets the same requirements as the root array of the file
Objects of first type are processed by following algorithm:
-
if object being processed has parent object of second type, then:
-
if parent object contains fields, that does not belong to the object being processed, then they are added to the object being processed with appropriate values
-
if parent object has parent object of second type too, then procedure is repeated for its parent and so on
Intermediate result of data loader is an array of all objects of first type with
values of service field _name
as keys. Service field _name
itself is
excluded from the objects.
Then each array value is wrapped into TestDataContainer object. Values are retrieved from containers using getters. Name of getters follow standard agreements:
-
if the name of field starts with 'is', then the getter name is field name converted to camel case
-
otherwise, if the field is of bool type, then the getter name is field name converted to studly case and prefixed with 'is'
-
otherwise, the getter name is field name converted to studly case and prefixed with 'get'
Service file for IDE is used for auto-completion when using container objects. Generator is called by following command:
php vendor/raptor/test-utils/generate-ide-test-containers path
where path
- path to directory with JSON files that contain test data.
Directory is processed recursively. Requirements to JSON files:
-
the name of each JSON file without an extension is converted to studly case, after that conversion all strings must be different. Duplicate names will not be processed
-
each JSON file should meet the requirements from the section Test data loader
As a result of the command execution, the _ide_test_containers.php file is
generated in the project root. This file contains container class for each JSON
file in the specified directory. Each container class is located in the root
namespace and has the name obtained by converting the name of the JSON file to
studly case and adding the suffix DataContainer
. You can use auto-completion
after adding a PHPDoc comment @var
with appropriate class and variable.
use Raptor\Test\TestDataContainer\TestDataContainer;
class someTests extends TestCase
{
use WithDataLoaderTrait;
...
/**
* @dataProvider someDataProvider
*/
public function testSomething(TestDataContainer $dataContainer): void
{
/** @var \SomeTestsDataContainer $dataContainer */
$value = $dataContainer->getValue();
...
}
public function someDataProvider(): array
{
return $this->loadFromFile('some_tests.json');
}
...
}
- Mikhail Kamorin aka raptor_MVK
- Igor Vodka