├── LICENSE
├── PHPUnitStandard
├── Sniffs
│ └── Testing
│ │ ├── AllowedFunctionOverrideSniff.php
│ │ ├── ClassNameSniff.php
│ │ ├── ExtraneousClassSniff.php
│ │ ├── FileNameSuffixSniff.php
│ │ ├── NoInterfacesSniff.php
│ │ ├── NoOutputFunctionsSniff.php
│ │ ├── NoOutputStatementsSniff.php
│ │ ├── NoPrivateMethodsSniff.php
│ │ ├── NoReflectionSniff.php
│ │ ├── ProvenTestCaseSniff.php
│ │ ├── TestOrProviderFunctionsOnlySniff.php
│ │ ├── TestOrProviderIsPublicSniff.php
│ │ ├── UnusedProviderSniff.php
│ │ └── ValidFunctionNameSniff.php
└── ruleset.xml
├── README.md
└── package.xml
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2011 Etsy
2 |
3 | Permission is hereby granted, free of charge, to any person
4 | obtaining a copy of this software and associated documentation
5 | files (the "Software"), to deal in the Software without
6 | restriction, including without limitation the rights to use,
7 | copy, modify, merge, publish, distribute, sublicense, and/or sell
8 | copies of the Software, and to permit persons to whom the
9 | Software is furnished to do so, subject to the following
10 | conditions:
11 |
12 | The above copyright notice and this permission notice shall be
13 | included in all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 |
--------------------------------------------------------------------------------
/PHPUnitStandard/Sniffs/Testing/AllowedFunctionOverrideSniff.php:
--------------------------------------------------------------------------------
1 |
8 | array(
9 | 'setUp',
10 | 'tearDown',
11 | 'closeConnection',
12 | 'getConnection',
13 | 'getDatabaseTester',
14 | 'getDataSet',
15 | 'getSetUpOperation',
16 | 'getTearDownOperation',
17 | 'newDatabaseTester',
18 | 'createDefaultDBConnection',
19 | 'createFlatXMLDataSet',
20 | 'createXMLDataSet',
21 | 'createMySQLXMLDataSet',
22 | 'getOperations',
23 | ),
24 | 'PHPUnit_Extensions_MultipleDatabase_TestCase' =>
25 | array(
26 | 'setUp',
27 | 'tearDown',
28 | 'getDatabaseConfigs',
29 | ),
30 | 'PHPUnit_Extensions_OutputTestCase' =>
31 | array(
32 | 'setUp',
33 | 'tearDown',
34 | 'runTest',
35 | ),
36 | 'PHPUnit_Extensions_PhptTestCase' =>
37 | array(
38 | 'setUp',
39 | 'tearDown'
40 | ),
41 | 'PHPUnit_Extensions_RepeatedTestCase' =>
42 | array(
43 | 'setUp',
44 | 'tearDown'
45 | ),
46 | 'PHPUnit_Framework_TestCase' =>
47 | array(
48 | 'setUp',
49 | 'tearDown'
50 | ),
51 | );
52 |
53 | /**
54 | * Returns the token types that this sniff is interested in.
55 | *
56 | * @return array(int)
57 | */
58 | public function register() {
59 | return array(
60 | T_FUNCTION,
61 | );
62 | }
63 |
64 | /**
65 | * Processes the tokens that this sniff is interested in.
66 | *
67 | * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
68 | * @param int $stackPtr The position in the stack where
69 | * the token was found.
70 | *
71 | * @return void
72 | */
73 | public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) {
74 | $functionName = $phpcsFile->getDeclarationName($stackPtr);
75 | $classStackPtr = $phpcsFile->findPrevious(T_CLASS, $stackPtr);
76 | $className = $phpcsFile->findExtendedClassName($classStackPtr);
77 | $properties = $phpcsFile->getMethodProperties($stackPtr);
78 |
79 | if (!in_array($className, array_keys($this->functionWhitelist))) {
80 | return;
81 | }
82 |
83 | $allowedFunctions = $this->functionWhitelist[$className];
84 |
85 | $isProtected = $properties['scope'] === 'protected';
86 | $isWhitelisted = in_array($functionName, $allowedFunctions);
87 |
88 | if ($isProtected && !$isWhitelisted) {
89 | $phpcsFile->addError(
90 | 'Unexpected protected function encountered. Not a whitelisted override: %s',
91 | $stackPtr,
92 | 'Found',
93 | array($functionName)
94 | );
95 | } else if (!$isProtected && $isWhitelisted) {
96 | $phpcsFile->addWarning(
97 | 'Expected function to be protected: %s',
98 | $stackPtr,
99 | 'Found',
100 | array($functionName)
101 | );
102 | }
103 | }
104 | }
105 |
106 |
--------------------------------------------------------------------------------
/PHPUnitStandard/Sniffs/Testing/ClassNameSniff.php:
--------------------------------------------------------------------------------
1 | getFileName();
30 | if(!preg_match("@.*/tests/phpunit/(.*).php@", $filename, $matches)) {
31 | $phpcsFile->addWarning(
32 | 'File path does not match expected convention.',
33 | $stackPtr
34 | );
35 | return;
36 | }
37 |
38 | $expected = str_replace("/", "_", $matches[1]);
39 |
40 | $found = array();
41 | while ($stackPtr = $phpcsFile->findNext(T_CLASS, ++$stackPtr)) {
42 | $className = $phpcsFile->getDeclarationName($stackPtr);
43 | if ($className == $expected) {
44 | return; // SUCCESS
45 | }
46 | $found[] = $className;
47 | }
48 | $classNames = '[NONE]';
49 | if (!empty($found)) {
50 | $classNames = implode(', ', $found);
51 | }
52 | $phpcsFile->addError(
53 | 'File must contain a class named: %s; found %s',
54 | $origStackPtr,
55 | 'Found',
56 | array($expected, $classNames)
57 | );
58 | }
59 | }
60 |
61 |
--------------------------------------------------------------------------------
/PHPUnitStandard/Sniffs/Testing/ExtraneousClassSniff.php:
--------------------------------------------------------------------------------
1 | getFileName();
28 | if(!preg_match("@.*/tests/phpunit/(.*).php@", $filename, $matches)) {
29 | $phpcsFile->addWarning(
30 | 'Filepath does not match expected convention',
31 | $stackPtr
32 | );
33 | return;
34 | }
35 | $expected = str_replace("/", "_", $matches[1]);
36 |
37 | $declarationName = $phpcsFile->getDeclarationName($stackPtr);
38 | if ($declarationName != $expected) {
39 | $phpcsFile->addError(
40 | 'Unexpected extraneous class found: %s. Expected: %s',
41 | $stackPtr,
42 | 'Found',
43 | array($declarationName, $expected)
44 | );
45 | }
46 | }
47 | }
48 |
49 |
--------------------------------------------------------------------------------
/PHPUnitStandard/Sniffs/Testing/FileNameSuffixSniff.php:
--------------------------------------------------------------------------------
1 | getFileName();
28 | if (!preg_match("@.*$this->suffix@", $fileName)) {
29 | $phpcsFile->addError(
30 | "Test file must end with $this->suffix",
31 | $stackPtr
32 | );
33 | }
34 | }
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/PHPUnitStandard/Sniffs/Testing/NoInterfacesSniff.php:
--------------------------------------------------------------------------------
1 | getDeclarationName($stackPtr);
28 | $phpcsFile->addError(
29 | 'No interfaces allowed in tests; found %s',
30 | $stackPtr,
31 | 'Found',
32 | array($interfaceName)
33 | );
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/PHPUnitStandard/Sniffs/Testing/NoOutputFunctionsSniff.php:
--------------------------------------------------------------------------------
1 | NULL,
6 | 'print_r' => NULL,
7 | 'var_dump' => NULL,
8 | );
9 | }
10 |
--------------------------------------------------------------------------------
/PHPUnitStandard/Sniffs/Testing/NoOutputStatementsSniff.php:
--------------------------------------------------------------------------------
1 | addError(
12 | 'The use of the "echo" and "print" keywords is forbidden in tests',
13 | $stackPtr,
14 | 'NotAllowed',
15 | array()
16 | );
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/PHPUnitStandard/Sniffs/Testing/NoPrivateMethodsSniff.php:
--------------------------------------------------------------------------------
1 | getMethodProperties($stackPtr);
26 | if ($properties['scope'] === 'private') {
27 | $phpcsFile->addError(
28 | 'Private methods are prohibited; found %s',
29 | $stackPtr,
30 | 'Found',
31 | array($phpcsFile->getDeclarationName($stackPtr))
32 | );
33 | }
34 | }
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/PHPUnitStandard/Sniffs/Testing/NoReflectionSniff.php:
--------------------------------------------------------------------------------
1 | getTokens();
12 | $className = $phpcsFile->findNext(
13 | T_WHITESPACE, ($stackPtr + 1), NULL, TRUE
14 | );
15 |
16 | if ($tokens[$className]['code'] === T_STRING &&
17 | strpos($tokens[$className]['content'], 'Reflection') === 0) {
18 | $phpcsFile->addError(
19 | 'Reflection API usage found',
20 | $stackPtr,
21 | 'NotAllowed',
22 | array()
23 | );
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/PHPUnitStandard/Sniffs/Testing/ProvenTestCaseSniff.php:
--------------------------------------------------------------------------------
1 | getDeclarationName($stackPtr);
37 | $extendedClassName = $phpcsFile->findExtendedClassName($stackPtr);
38 | if (!($extendedClassName
39 | && in_array($extendedClassName, $this->classNameWhitelist))
40 | ) {
41 | $phpcsFile->addError(
42 | 'Must extend a proven PHPUnit_Framework_TestCase class; found %s.',
43 | $stackPtr,
44 | 'Found',
45 | array($extendedClassName)
46 | );
47 | }
48 | }
49 | }
50 |
51 |
--------------------------------------------------------------------------------
/PHPUnitStandard/Sniffs/Testing/TestOrProviderFunctionsOnlySniff.php:
--------------------------------------------------------------------------------
1 | findPrevious(T_CLASS, $stackPtr);
28 | $className = $phpcsFile->getDeclarationName($classStackPtr);
29 | $properties = $phpcsFile->getMethodProperties($stackPtr);
30 | $functionName = $phpcsFile->getDeclarationName($stackPtr);
31 | if (!in_array($properties['scope'], array('private', 'protected'))) {
32 | if (preg_match('@(test|provide)[A-Z_].*@', $functionName)) {
33 | return;
34 | }
35 | $phpcsFile->addError(
36 | 'Found a public method that is not a test or a provider: %s',
37 | $stackPtr,
38 | 'Found',
39 | array($functionName)
40 | );
41 | }
42 | }
43 | }
44 |
45 |
--------------------------------------------------------------------------------
/PHPUnitStandard/Sniffs/Testing/TestOrProviderIsPublicSniff.php:
--------------------------------------------------------------------------------
1 | findPrevious(T_CLASS, $stackPtr);
28 | $className = $phpcsFile->getDeclarationName($classStackPtr);
29 | $properties = $phpcsFile->getMethodProperties($stackPtr);
30 | $functionName = $phpcsFile->getDeclarationName($stackPtr);
31 | if (in_array($properties['scope'], array('private', 'protected'))) {
32 | if (!preg_match('@(test|provider)[A-Z_].*@', $functionName)) {
33 | return;
34 | }
35 | $phpcsFile->addWarning(
36 | 'Found non-public test or provider function: %s',
37 | $stackPtr,
38 | 'Found',
39 | array($functionName)
40 | );
41 | }
42 | }
43 | }
44 |
45 |
--------------------------------------------------------------------------------
/PHPUnitStandard/Sniffs/Testing/UnusedProviderSniff.php:
--------------------------------------------------------------------------------
1 | findPrevious(T_CLASS, $stackPtr);
28 | $className = $phpcsFile->getDeclarationName($classStackPtr);
29 |
30 | $functionName = $phpcsFile->getDeclarationName($stackPtr);
31 | if (!preg_match('@provide[A-Z_].*@', $functionName)) {
32 | return;
33 | }
34 |
35 | $tokens = $phpcsFile->getTokens();
36 | $commentStackPtr = 1;
37 | while ($commentStackPtr =
38 | $phpcsFile->findNext(T_DOC_COMMENT, ++$commentStackPtr)
39 | ) {
40 | $commentLine = $tokens[$commentStackPtr]['content'];
41 | if (preg_match("/\*\s+@dataProvider\s+$functionName/", $commentLine)) {
42 | return;
43 | }
44 | }
45 | $phpcsFile->addError(
46 | 'Unused provider method: %s',
47 | $stackPtr,
48 | 'Found',
49 | array($functionName)
50 | );
51 | }
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/PHPUnitStandard/Sniffs/Testing/ValidFunctionNameSniff.php:
--------------------------------------------------------------------------------
1 | getDeclarationName($stackPtr);
16 | if ($methodName === null) {
17 | return; // Ignore closures
18 | }
19 | $className = $phpcsFile->getDeclarationName($currScope);
20 | $errorData = array($className . '::' . $methodName);
21 |
22 | if (preg_match(';^(test|provider)(.*);', $methodName, $matches) !== 0) {
23 | if (empty($matches[2])) {
24 | $phpcsFile->addError(
25 | 'Method name cannot just be "%s"',
26 | $stackPtr,
27 | 'TestOrProviderOnly',
28 | array($matches[1])
29 | );
30 | return;
31 | }
32 | $parts = explode('_', $matches[2]);
33 |
34 | if (count($parts) > 2) {
35 | $phpcsFile->addError(
36 | 'Method name "%s" cannot have more than one dividing underscore.',
37 | $stackPtr,
38 | 'TooManyParts',
39 | $errorData
40 | );
41 | }
42 |
43 | if (preg_match(';_$;', $methodName) !== 0) {
44 | $phpcsFile->addError(
45 | 'Method name "%s" cannot end with an underscore.',
46 | $stackPtr,
47 | 'UnderscoreEnding',
48 | $errorData
49 | );
50 | }
51 |
52 | if (!empty($parts[0])
53 | && PHP_CodeSniffer::isCamelCaps($parts[0], true, true, false) === false) {
54 | $phpcsFile->addError(
55 | 'First part "%s" is not camel caps format with or without "%s".',
56 | $stackPtr,
57 | 'NotCamelCaps',
58 | array(
59 | $parts[0],
60 | $matches[1]
61 | )
62 | );
63 |
64 | }
65 |
66 | if (count($parts) > 1
67 | && !empty($parts[1])
68 | && PHP_CodeSniffer::isCamelCaps($parts[1], false, true, false) === false) {
69 | $phpcsFile->addError(
70 | 'Second part "%s" is not camel caps format.',
71 | $stackPtr,
72 | 'NotCamelCaps',
73 | array($parts[1])
74 | );
75 | }
76 | }
77 | }
78 | }
--------------------------------------------------------------------------------
/PHPUnitStandard/ruleset.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | The Etsy coding standard for testing.
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | See PEAR channel instructions at: http://elblinkin.github.com/Pirum/
2 |
3 | Note: My apologies, but the sniffs might have a few rough edges around them. Will be cleaning up and adding documentation soon.
--------------------------------------------------------------------------------
/package.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 | PHPUnitStandard
7 | pear.elblinkin.info
8 | PHP CodeSniffer Standard for PHPUnit tests.
9 |
10 | PHP CodeSniffer Standard for PHPUnit tests.
11 |
12 |
13 | Laura Beth Lincoln Denker
14 | elblinkin
15 | github@elblinkin.info
16 | yes
17 |
18 | 2012-02-13
19 |
20 | 0.2.0
21 | 0.2.0
22 |
23 |
24 | beta
25 | beta
26 |
27 | MIT
28 | -
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | 5.2.17
58 |
59 |
60 | 1.9.1
61 |
62 |
63 | PHP_CodeSniffer
64 | pear
65 | 1.3.0
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------