Skip to content

Commit

Permalink
PHPCS 3.x compat: Update readme, build script and config files
Browse files Browse the repository at this point in the history
Travis:
* No longer test the build against PHP 5.2.
* Only test against PHP 5.3 icw PHPCS 2.x.
* Test all other PHP versions against both PHPCS 2.x as well as `master` (3.x).
* Test the build against PHPCS 3.x using the `master` branch.
* Removed allowance for build failures against `master`.
* Adjusted phpunit command to allow for testing on both PHPCS 2.x as well as 3.x.

Composer:
* Add the minimum required PHP version.
* Make the PHPCS requirement more specific and allow for PHPCS 3.x.

"Own" PHPCS custom ruleset:
* Enforce PSR1 namespaces.

Readme:
* Adjusted (minimum) requirements information.
* Updated installation instructions.
* Updated travis example code.

Contributing
* Updated unit test instructions.
* Updated example sniff code.
* Removed reference to potentially upstreaming WPCS to PHPCS as reason for using the PHPCS unit test suite. Let's be fair: the sniffs ought to be unit tested anyway, no matter what.
* Update unit testing conventions example. The example was referring to a now deprecated sniff, so selected another sniff for the example code.
  • Loading branch information
jrfnl committed Jul 24, 2017
1 parent 10847d8 commit f005097
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 93 deletions.
44 changes: 18 additions & 26 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ dist: trusty

cache:
apt: true

language:
- php

Expand All @@ -14,11 +14,12 @@ php:
- 5.6
- 7.0
- 7.1
- nightly

env:
# Branch for patches against 2.x. `master` is now 3.x which WPCS is not (yet) compatible with.
- PHPCS_BRANCH=2.9 LINT=1
# Tagged release
# `master` is now 3.x.
- PHPCS_BRANCH=master LINT=1
# Lowest tagged release in the 2.x series with which WPCS is compatible.
- PHPCS_BRANCH=2.9.0

matrix:
Expand All @@ -31,38 +32,27 @@ matrix:
apt:
packages:
- libxml2-utils
# Run against PHPCS 3.0. I just picked to run it against 5.6.
- php: 5.6
env: PHPCS_BRANCH=master

# Run against HHVM and PHP nightly.
- php: hhvm
sudo: required
dist: trusty
dist: trusty
group: edge
env: PHPCS_BRANCH=2.9 LINT=1
- php: nightly
env: PHPCS_BRANCH=2.9 LINT=1
# Test PHP 5.3 with short_open_tags set to On (is Off by default)
- php: 5.3
env: PHPCS_BRANCH=2.9 SHORT_OPEN_TAGS=true
dist: precise
env: PHPCS_BRANCH=master LINT=1

# Test PHP 5.3 only against PHPCS 2.x as PHPCS 3.x has a minimum requirement of PHP 5.4.
- php: 5.3
env: PHPCS_BRANCH=2.9
env: PHPCS_BRANCH=2.9 LINT=1
dist: precise
# Test PHP 5.3 with short_open_tags set to On (is Off by default)
- php: 5.3
env: PHPCS_BRANCH=2.9.0
dist: precise
- php: 5.2
env: PHPCS_BRANCH=2.9
dist: precise
- php: 5.2
env: PHPCS_BRANCH=2.9.0
env: PHPCS_BRANCH=2.9.0 SHORT_OPEN_TAGS=true
dist: precise

allow_failures:
# Allow failures for unstable builds.
- php: nightly
- php: hhvm
- env: PHPCS_BRANCH=master

before_install:
- export XMLLINT_INDENT=" "
Expand All @@ -82,8 +72,10 @@ script:
# Lint the PHP files against parse errors.
- if [[ "$LINT" == "1" ]]; then if find . -name "*.php" -exec php -l {} \; | grep "^[Parse error|Fatal error]"; then exit 1; fi; fi
# Run the unit tests.
- if [[ ${TRAVIS_PHP_VERSION:0:2} == "5." ]]; then phpunit --filter WordPress /tmp/phpcs/tests/AllTests.php; fi
- if [[ ${TRAVIS_PHP_VERSION:0:2} != "5." ]]; then php $PHPUNIT_DIR/phpunit-5.7.17.phar --filter WordPress /tmp/phpcs/tests/AllTests.php; fi
- if [[ ${TRAVIS_PHP_VERSION:0:2} == "5." && ${PHPCS_BRANCH:0:2} == "2." ]]; then phpunit --filter WordPress $(pwd)/Test/AllTests.php; fi
- if [[ ${TRAVIS_PHP_VERSION:0:2} == "5." && ${PHPCS_BRANCH:0:2} != "2." ]]; then phpunit --filter WordPress $PHPCS_DIR/tests/AllTests.php; fi
- if [[ ${TRAVIS_PHP_VERSION:0:2} != "5." && ${PHPCS_BRANCH:0:2} == "2." ]]; then php $PHPUNIT_DIR/phpunit-5.7.17.phar --filter WordPress $(pwd)/Test/AllTests.php; fi
- if [[ ${TRAVIS_PHP_VERSION:0:2} != "5." && ${PHPCS_BRANCH:0:2} != "2." ]]; then php $PHPUNIT_DIR/phpunit-5.7.17.phar --filter WordPress $PHPCS_DIR/tests/AllTests.php; fi
# WordPress Coding Standards.
# @link https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards
# @link http://pear.php.net/package/PHP_CodeSniffer/
Expand Down
174 changes: 114 additions & 60 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@ When you introduce new `public` sniff properties, or your sniff extends a class
Sometimes, a sniff will flag code which upon further inspection by a human turns out to be OK.
If the sniff you are writing is susceptible to this, please consider adding the ability to [whitelist lines of code](https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/wiki/Whitelisting-code-which-flags-errors).

To this end, the `WordPress_Sniff::has_whitelist_comment()` method was introduced.
To this end, the `WordPress\Sniff::has_whitelist_comment()` method was introduced.

Example usage:
```php
class WordPress_Sniffs_CSRF_NonceVerificationSniff extends WordPress_Sniff {
namespace WordPress\Sniffs\CSRF;

use WordPress\Sniff;

class NonceVerificationSniff extends Sniff {

public function process_token( $stackPtr ) {

Expand All @@ -48,92 +52,142 @@ When you introduce a new whitelist comment, please don't forget to update the [w

# Unit Testing

TL;DR
## Pre-requisites
* WordPress-Coding-Standards
* PHP CodeSniffer 2.9.x or 3.x
* PHPUnit 4.x or 5.x

If you have installed `phpcs` and the WordPress-Coding-Standards as [noted in the README](https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards#how-to-use-this), then you can navigate to the directory where the `phpcs` repo is checked out and do:
The WordPress Coding Standards use the PHP CodeSniffer native unit test suite for unit testing the sniffs.

```sh
composer install
vendor/bin/phpunit --filter WordPress tests/AllTests.php
Presuming you have installed PHP CodeSniffer and the WordPress-Coding-Standards as [noted in the README](https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards#how-to-use-this), all you need now is `PHPUnit`.

If you already have PHPUnit installed on your system: Congrats, you're all set.

If not, you can navigate to the directory where the `PHP_CodeSniffer` repo is checked out and do `composer install` to install the `dev` dependencies.
Alternatively, you can [install PHPUnit](https://phpunit.de/manual/5.7/en/installation.html) as a PHAR file.

**Pro-tip**: PHPUnit is easiest to work with if you add the installation directory to your `PATH` environment variable.

## Before running the unit tests

N.B.: _If you used Composer to install the WordPress Coding Standards, you can skip this step._

For the unit tests to work, you need to make sure PHPUnit can find your `PHP_CodeSniffer` install.

The easiest way to do this is to add a `phpunit.xml` file to the root of your WPCS installation and set a `PHPCS_DIR` environment variable from within this file. Make sure to adjust the path to reflect your local setup.
```xml
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd"
backupGlobals="true">
<php>
<env name="PHPCS_DIR" value="/path/to/PHP_CodeSniffer/"/>
</php>
</phpunit>
```

## Running the unit tests

The WordPress Coding Standards are compatible with both PHPCS 2.x as well as 3.x. This has some implications for running the unit tests.

* Navigate to the directory in which you installed WPCS.
* To run the unit tests with PHPCS 3.x:
```sh
phpunit --bootstrap="./Test/phpcs3-bootstrap.php" --filter WordPress /path/to/PHP_CodeSniffer/tests/AllTests.php
```
* To run the unit tests with PHPCS 2.x:
```sh
phpunit --bootstrap="./Test/phpcs2-bootstrap.php" --filter WordPress ./Test/AllTests.php
```

Expected output:
```
PHPUnit 4.8.19 by Sebastian Bergmann and contributors.

[![asciicast](https://asciinema.org/a/98078.png)](https://asciinema.org/a/98078)
Runtime: PHP 7.1.3 with Xdebug 2.5.1
Configuration: /WordPressCS/phpunit.xml

......................................................

Tests generated 558 unique error codes; 48 were fixable (8.6%)

Time: 12.25 seconds, Memory: 24.00Mb

You can ignore any skipped tests as these are for `PHP_CodeSniffer` external tools.
OK (54 tests, 0 assertions)
```
The reason why we need to checkout from `PHP_CodeSniffer` git repo to run the tests is because
PEAR installation is intended for ready-to-use not for development. At some point `WordPress-Coding-Standards`
might be submitted to `PHP_CodeSniffer` repo and using their existing convention for unit tests
will eventually help them to test the code before merging in.
[![asciicast](https://asciinema.org/a/98078.png)](https://asciinema.org/a/98078)
## Unit Testing conventions
If you see inside the `WordPress/Tests`, the structure mimics the `WordPress/Sniffs`. For example,
the `WordPress/Sniffs/Arrays/ArrayDeclarationSniff.php` sniff has unit test class defined in
`WordPress/Tests/Arrays/ArrayDeclarationUnitTest.php` that check `WordPress/Tests/Arrays/ArrayDeclarationUnitTest.inc`
file. See the file naming convention? Lets take a look what inside `ArrayDeclarationUnitTest.php`:
If you look inside the `WordPress/Tests` subdirectory, you'll see the structure mimics the `WordPress/Sniffs` subdirectory structure. For example, the `WordPress/Sniffs/PHP/POSIXFunctionsSniff.php` sniff has its unit test class defined in `WordPress/Tests/PHP/POSIXFunctionsUnitTest.php` which checks the `WordPress/Tests/PHP/POSIXFunctionsUnitTest.inc` test case file. See the file naming convention?
Lets take a look at what's inside `POSIXFunctionsUnitTest.php`:
```php
...
class WordPress_Tests_Arrays_ArrayDeclarationUnitTest extends AbstractSniffUnitTest
{
public function getErrorList()
{
return array(
3 => 1,
7 => 1,
9 => 1,
16 => 1,
31 => 2,
);

}//end getErrorList()
}
namespace WordPress\Tests\PHP;
use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest;
class POSIXFunctionsUnitTest extends AbstractSniffUnitTest {
/**
* Returns the lines where errors should occur.
*
* @return array <int line number> => <int number of errors>
*/
public function getErrorList() {
return array(
13 => 1,
16 => 1,
18 => 1,
20 => 1,
22 => 1,
24 => 1,
26 => 1,
);
}
...
```

Also note the class name convention. The method `getErrorList` MUST return an array of line numbers
indicating errors (when running `phpcs`) found in `WordPress/Tests/Arrays/ArrayDeclarationUnitTest.inc`.
Also note the class name convention. The method `getErrorList()` MUST return an array of line numbers indicating errors (when running `phpcs`) found in `WordPress/Tests/PHP/POSIXFunctionsUnitTest.inc`.
If you run:

```sh
$ cd /path-to-cloned/phpcs
$ ./scripts/phpcs --standard=Wordpress -s CodeSniffer/Standards/WordPress/Tests/Arrays/ArrayDeclarationUnitTest.inc
$ ./bin/phpcs --standard=Wordpress -s /path/to/WordPress/Tests/PHP/POSIXFunctionsUnitTest.inc --sniffs=WordPress.PHP.POSIXFunctions
...
--------------------------------------------------------------------------------
FOUND 8 ERROR(S) AND 2 WARNING(S) AFFECTING 6 LINE(S)
FOUND 7 ERRORS AFFECTING 7 LINES
--------------------------------------------------------------------------------
3 | ERROR | Array keyword should be lower case; expected "array" but found
| | "Array" (WordPress.Arrays.ArrayDeclaration)
7 | ERROR | There must be no space between the Array keyword and the
| | opening parenthesis (WordPress.Arrays.ArrayDeclaration)
9 | ERROR | Empty array declaration must have no space between the
| | parentheses (WordPress.Arrays.ArrayDeclaration)
12 | WARNING | No space after opening parenthesis of array is bad style
| | (WordPress.Arrays.ArrayDeclaration)
12 | WARNING | No space before closing parenthesis of array is bad style
| | (WordPress.Arrays.ArrayDeclaration)
16 | ERROR | Each line in an array declaration must end in a comma
| | (WordPress.Arrays.ArrayDeclaration)
31 | ERROR | Expected 1 space between "'type'" and double arrow; 0 found
| | (WordPress.Arrays.ArrayDeclaration)
31 | ERROR | Expected 1 space between double arrow and "'post'"; 0 found
| | (WordPress.Arrays.ArrayDeclaration)
31 | ERROR | Expected 1 space before "=>"; 0 found
| | (WordPress.WhiteSpace.OperatorSpacing)
31 | ERROR | Expected 1 space after "=>"; 0 found
| | (WordPress.WhiteSpace.OperatorSpacing)
13 | ERROR | ereg() has been deprecated since PHP 5.3 and removed in PHP 7.0,
| | please use preg_match() instead.
| | (WordPress.PHP.POSIXFunctions.ereg_ereg)
16 | ERROR | eregi() has been deprecated since PHP 5.3 and removed in PHP 7.0,
| | please use preg_match() instead.
| | (WordPress.PHP.POSIXFunctions.ereg_eregi)
18 | ERROR | ereg_replace() has been deprecated since PHP 5.3 and removed in PHP
| | 7.0, please use preg_replace() instead.
| | (WordPress.PHP.POSIXFunctions.ereg_replace_ereg_replace)
20 | ERROR | eregi_replace() has been deprecated since PHP 5.3 and removed in PHP
| | 7.0, please use preg_replace() instead.
| | (WordPress.PHP.POSIXFunctions.ereg_replace_eregi_replace)
22 | ERROR | split() has been deprecated since PHP 5.3 and removed in PHP 7.0,
| | please use explode(), str_split() or preg_split() instead.
| | (WordPress.PHP.POSIXFunctions.split_split)
24 | ERROR | spliti() has been deprecated since PHP 5.3 and removed in PHP 7.0,
| | please use explode(), str_split() or preg_split() instead.
| | (WordPress.PHP.POSIXFunctions.split_spliti)
26 | ERROR | sql_regcase() has been deprecated since PHP 5.3 and removed in PHP
| | 7.0, please use preg_match() instead.
| | (WordPress.PHP.POSIXFunctions.ereg_sql_regcase)
--------------------------------------------------------------------------------
....
```
You'll see the line number and number of ERRORs we need to return in the `getErrorList()` method.

You'll see the line number and number of ERRORs we need to return in `getErrorList` method.
In line #31 there are two ERRORs belong to `WordPress.WhiteSpace.OperatorSpacing` sniff and
it MUST not included in `ArrayDeclarationUnitTest` (that's why we only return 2 errros for line #31).
Also there's `getWarningList` method in unit test class that returns an array of line numbers
indicating WARNINGs.
The `--sniffs=...` directive limits the output to the sniff you are testing.

## Sniff Code Standards

Expand Down
15 changes: 9 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ This project is a collection of [PHP_CodeSniffer](https://github.com/squizlabs/P

### Requirements

The WordPress Coding Standards require PHP 5.2 or higher and the [PHP_CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) version **2.9.0** or higher.
The WordPress Coding Standards are currently [not compatible with the upcoming PHPCS 3 release](https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards/issues/718).
The WordPress Coding Standards require PHP 5.3 or higher and [PHP CodeSniffer](https://github.com/squizlabs/PHP_CodeSniffer) version **2.9.0** or higher.
As of version 0.13.0, the WordPress Coding Standards are compatible with PHPCS 3.0.2+. In that case, the minimum PHP requirement is PHP 5.4.

### Composer

Expand All @@ -58,7 +58,7 @@ Running this command will:
3. Register WordPress standards in PHP_CodeSniffer configuration.
4. Make `phpcs` command available from `wpcs/vendor/bin`.

For the convenience of using `phpcs` as a global command, you may want to add the `wpcs/vendor/bin` path to a PATH environment in your operating system.
For the convenience of using `phpcs` as a global command, you may want to add the path to the `wpcs/vendor/scripts` (PHPCS 2.x) and/or `wpcs/vendor/bin` (PHPCS 3.x) directories to a `PATH` environment variable for your operating system.

#### Installing WPCS as a dependency

Expand Down Expand Up @@ -96,10 +96,13 @@ cd ~/projects
git clone https://github.com/squizlabs/PHP_CodeSniffer.git phpcs
git clone -b master https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards.git wpcs
cd phpcs
#PHPCS 2.x
./scripts/phpcs --config-set installed_paths ../wpcs
#PHPCS 3.x
./bin/phpcs --config-set installed_paths ../wpcs
```

And then add the `~/projects/phpcs/scripts` directory to your `PATH` environment variable via your `.bashrc`.
And then add the `~/projects/phpcs/scripts` (PHPCS 2.x) or `~/projects/phpcs/bin` (PHPCS 3.x) directory to your `PATH` environment variable via your `.bashrc`.

You should then see `WordPress-Core` et al listed when you run `phpcs -i`.

Expand Down Expand Up @@ -241,7 +244,7 @@ before_install:
# Install WordPress Coding Standards.
- if [[ "$SNIFF" == "1" ]]; then git clone -b master --depth 1 https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards.git $SNIFFS_DIR; fi
# Set install path for WordPress Coding Standards.
- if [[ "$SNIFF" == "1" ]]; then $PHPCS_DIR/scripts/phpcs --config-set installed_paths $SNIFFS_DIR; fi
- if [[ "$SNIFF" == "1" ]]; then $PHPCS_DIR/bin/phpcs --config-set installed_paths $SNIFFS_DIR; fi
# After CodeSniffer install you should refresh your path.
- if [[ "$SNIFF" == "1" ]]; then phpenv rehash; fi

Expand All @@ -251,7 +254,7 @@ script:
# for example: `--standard=wpcs.xml`.
# You can use any of the normal PHPCS command line arguments in the command:
# https://github.com/squizlabs/PHP_CodeSniffer/wiki/Usage
- if [[ "$SNIFF" == "1" ]]; then $PHPCS_DIR/scripts/phpcs -p . --standard=WordPress; fi
- if [[ "$SNIFF" == "1" ]]; then $PHPCS_DIR/bin/phpcs -p . --standard=WordPress; fi
```
Expand Down
3 changes: 3 additions & 0 deletions bin/phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@

<rule ref="WordPress-Docs" />

<!-- Enforce PSR1 compatible namespaces. -->
<rule ref="PSR1.Classes.ClassDeclaration"/>

</ruleset>
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
}
],
"require" : {
"squizlabs/php_codesniffer": "^2.9.0"
"php" : ">=5.3",
"squizlabs/php_codesniffer": "^2.9.0 || ^3.0.2"
},
"suggest" : {
"dealerdirect/phpcodesniffer-composer-installer": "*"
Expand Down

0 comments on commit f005097

Please sign in to comment.