automated-typo3-update/Documentation/source/extending.rst

151 lines
5.3 KiB
ReStructuredText

.. _extending:
Extending
=========
It's possible to extend the provided migrations.
Also adding tests is pretty easy and done by adding a folder with an input file and an file
holding the expectations.
.. _extending-sniffs:
Sniffs
------
Follow the official docs of `phpcs`_:
https://github.com/squizlabs/PHP_CodeSniffer/wiki/Coding-Standard-Tutorial#user-content-creating-the-sniff
The following resources might be helpful during working with ``phpcs``:
- https://secure.php.net/manual/en/tokens.php
- :file:`CodeSniffer/Tokens.php`
- :file:`CodeSniffer/File.php`
.. _extending-features:
Features
--------
Sniffs do not always add errors or warnings in our standard, instead for more flexibility, we use
them to find specific "tokens", e.g. class names. We then attach so called *Features* to sniffs to
work on that token.
E.g. we deliver the Feature ``LegacyClassnameFeature`` which will check whether a given class name
is legacy and should be replaced. As class names may occur in many places like type hints or php doc
blocks, the sniffs will detect the class names and the feature will work on them.
Features can be attached to the sniffs. A feature has to implement the ``FeatureInterface`` and will
work on tokens found by sniffs.
To attach a Feature to Sniffs, provide a yaml-configuration, see :ref:`configuration-features`.
.. _extending-tests:
Tests
-----
We are using `phpunit` as testing framework.
Adding tests for sniffs is as easy as providing the same folder structure as for the sniff, just
inside the :file:`tests/Fixtures` folder. Instead of adding the sniff as a file, you have to provide
a folder named like the sniff. E.g. you want to add a test for sniff
:file:`src/Standards/Typo3Update/Sniffs/LegacyClassnames/DocCommentSniff.php`, the following folder
has to exist: :file:`tests/Fixtures/Standards/Typo3Update/Sniffs/LegacyClassnames/DocCommentSniff/`.
Also for convenience add a test class with following content:
.. code-block:: php
<?php
namespace Typo3Update\Tests\Sniffs\Removed;
/*
* Copyright (C) 2017 Daniel Siepmann <coding@daniel-siepmann.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
use Typo3Update\Tests\SniffsTest;
class TypoScriptSniffTest extends SniffsTest
{
}
Place it accordingly to namespace. Adjust namespace and class name. No code is needed, everything is
done in ``SniffsTest``. But this enables you to add ``--filter`` to ``phpunit`` to run just one
test. Also IDEs support to run the single test file. This makes development much faster and failing
tests more helpfull as they contain the class name.
.. _extending-tests-single:
Single test per sniff
^^^^^^^^^^^^^^^^^^^^^
Inside of the folder at least a file :file:`InputFileForIssues.php` has to exist, containing PHP
code to use for the test. Also a file :file:`Expected.json` has to exist, with the json result of
calling ``phpcs`` with :file:`InputFileForIssues.php`.
Everything else is done out of the box.
If your sniff also implements fixable errors or warnings, you can further provide a
:file:`Expected.diff` which is generated by ``phpcbf``.
.. _extending-tests-multiple:
Multiple tests per sniff
^^^^^^^^^^^^^^^^^^^^^^^^
Also it's possible to provide multiple tests for a single sniff, e.g. with different cli arguments
like options for the sniff. In that case you have to place a :file:`Arguments.php` in the folder.
This file returns an array:
.. code-block:: php
<?php
return [
'defaultVendor' => [],
'customVendor' => [
'runtime-set' => [
'vendor' => 'MyCustomVendor',
],
],
];
In the example above ``defaultVendor`` and ``customVendor`` are subfolders containing the same
structure as documented for :ref:`extending-tests-single`.
This way it's possible to run multiple tests per sniff.
Also you can provide further cli arguments on a key -> value base. Where ``runtime-set`` is special,
as it contains a sub array to provide multiple runtime sets.
How sniff tests are implemented
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
We just find all folders below :file:`tests/Fixtures/Standards/Typo3Update/Sniffs` ending with
``Sniff`` and check the structure. They are provided to the test itself through a dataprovider in
phpunit.
We then build the phpcs cli call and execute it against the :file:`InputFileForIssues.php` and
compare the result against the :file:`Expected.json`. Same for :file:`Expected.diff`. The existence
of :file:`Expected.diff` itself will trigger the test for ``phpcbf``.
.. _phpcs: https://github.com/squizlabs/PHP_CodeSniffer
.. _phpunit: https://phpunit.de/