forked from moodlehq/moodle-cs
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
PHPUnit tests should have a return type
- Loading branch information
1 parent
5503396
commit 7156233
Showing
11 changed files
with
469 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
<?php | ||
// This file is part of Moodle - http://moodle.org/ | ||
// | ||
// Moodle 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 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// Moodle 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 Moodle. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
namespace MoodleHQ\MoodleCS\moodle\Sniffs\PHPUnit; | ||
|
||
// phpcs:disable moodle.NamingConventions | ||
|
||
use MoodleHQ\MoodleCS\moodle\Util\MoodleUtil; | ||
use PHP_CodeSniffer\Sniffs\Sniff; | ||
use PHP_CodeSniffer\Files\File; | ||
use PHPCSUtils\Utils\FunctionDeclarations; | ||
use PHPCSUtils\Utils\ObjectDeclarations; | ||
|
||
/** | ||
* Checks that a test file has the @coversxxx annotations properly defined. | ||
* | ||
* @package local_codechecker | ||
* @copyright 2022 onwards Eloy Lafuente (stronk7) {@link https://stronk7.com} | ||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | ||
*/ | ||
class TestReturnTypeSniff implements Sniff | ||
{ | ||
|
||
/** | ||
* Register for open tag (only process once per file). | ||
*/ | ||
public function register() { | ||
return [ | ||
T_OPEN_TAG, | ||
]; | ||
} | ||
|
||
/** | ||
* Processes php files and perform various checks with file. | ||
* | ||
* @param File $file The file being scanned. | ||
* @param int $pointer The position in the stack. | ||
*/ | ||
public function process(File $file, $pointer) | ||
{ | ||
// Before starting any check, let's look for various things. | ||
|
||
// If we aren't checking Moodle 4.0dev (400) and up, nothing to check. | ||
// Make and exception for codechecker phpunit tests, so they are run always. | ||
if (!MoodleUtil::meetsMinimumMoodleVersion($file, 400) && !MoodleUtil::isUnitTestRunning()) { | ||
return; // @codeCoverageIgnore | ||
} | ||
|
||
// If the file is not a unit test file, nothing to check. | ||
if (!MoodleUtil::isUnitTest($file) && !MoodleUtil::isUnitTestRunning()) { | ||
return; // @codeCoverageIgnore | ||
} | ||
|
||
// We have all we need from core, let's start processing the file. | ||
|
||
// Get the file tokens, for ease of use. | ||
$tokens = $file->getTokens(); | ||
|
||
// We only want to do this once per file. | ||
$prevopentag = $file->findPrevious(T_OPEN_TAG, | ||
$pointer - 1 | ||
); | ||
if ($prevopentag !== false) { | ||
return; // @codeCoverageIgnore | ||
} | ||
|
||
// Iterate over all the classes (hopefully only one, but that's not this sniff problem). | ||
$cStart = $pointer; | ||
while ($cStart = $file->findNext(T_CLASS, $cStart + 1)) { | ||
if (MoodleUtil::isUnitTestCaseClass($file, $cStart) === false) { | ||
// This class does not related to a uit test. | ||
continue; | ||
} | ||
|
||
$classInfo = ObjectDeclarations::getClassProperties($file, $cStart); | ||
|
||
// Iterate over all the methods in the class. | ||
$mStart = $cStart; | ||
while ($mStart = $file->findNext(T_FUNCTION, $mStart + 1, $tokens[$cStart]['scope_closer'])) { | ||
$method = $file->getDeclarationName($mStart); | ||
|
||
// Ignore non test_xxxx() methods. | ||
if (strpos($method, 'test_') !== 0) { | ||
continue; | ||
} | ||
|
||
// Get the function declaration. | ||
$functionInfo = FunctionDeclarations::getProperties($file, $mStart); | ||
|
||
// 'return_type_token' => int|false, // The stack pointer to the start of the return type. | ||
if ($functionInfo['return_type_token'] !== false) { | ||
// This method has a return type. | ||
// In most cases that will be void, but it could be anything in the | ||
// case of chained or dependant tests. | ||
// TODO: Detect all cases of chained tests and dependant tests. | ||
continue; | ||
} | ||
|
||
$methodNamePtr = $file->findNext(T_STRING, $mStart + 1, $tokens[$mStart]['parenthesis_opener']); | ||
$methodEnd = $file->findNext(T_CLOSE_PARENTHESIS, $mStart + 1); | ||
|
||
// Detect if the method has a return statement. | ||
// If it does, then see if it has a value or not. | ||
$hasReturn = $file->findNext(T_RETURN, $mStart + 1, $tokens[$mStart]['scope_closer']); | ||
$probablyVoid = !$hasReturn; | ||
if ($hasReturn) { | ||
$next = $file->findNext( | ||
T_WHITESPACE, | ||
$hasReturn + 1, | ||
$tokens[$mStart]['scope_closer'], | ||
true | ||
); | ||
if ($tokens[$next]['code'] === T_SEMICOLON) { | ||
$probablyVoid = true; | ||
} | ||
} | ||
|
||
$fix = false; | ||
if ($probablyVoid) { | ||
$fix = $file->addFixableWarning( | ||
'Test method %s() is missing a return type', | ||
$methodNamePtr, | ||
'MissingReturnType', | ||
[$method] | ||
); | ||
} else { | ||
$file->addWarning( | ||
'Test method %s() is missing a return type', | ||
$methodNamePtr, | ||
'MissingReturnType', | ||
[$method] | ||
); | ||
} | ||
|
||
if ($fix) { | ||
$file->fixer->beginChangeset(); | ||
$file->fixer->addContent($methodEnd, ': void'); | ||
$file->fixer->endChangeset(); | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
<?php | ||
// This file is part of Moodle - http://moodle.org/ | ||
// | ||
// Moodle 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 3 of the License, or | ||
// (at your option) any later version. | ||
// | ||
// Moodle 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 Moodle. If not, see <http://www.gnu.org/licenses/>. | ||
|
||
namespace MoodleHQ\MoodleCS\moodle\Tests; | ||
|
||
// phpcs:disable moodle.NamingConventions | ||
|
||
/** | ||
* Test the PHPUnitTestReturnTypeSniff sniff. | ||
* | ||
* @package local_codechecker | ||
* @category test | ||
* @copyright 2022 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} | ||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | ||
* | ||
* @covers \MoodleHQ\MoodleCS\moodle\Sniffs\PHPUnit\TestReturnTypeSniff | ||
*/ | ||
class PHPUnitTestReturnTypeTest extends MoodleCSBaseTestCase { | ||
|
||
/** | ||
* Data provider for self::provider_phpunit_data_returntypes | ||
*/ | ||
public function provider_phpunit_data_returntypes(): array { | ||
return [ | ||
'Provider Casing' => [ | ||
'fixture' => 'fixtures/phpunit/TestReturnType/returntypes.php', | ||
'errors' => [ | ||
], | ||
'warnings' => [ | ||
6 => 'Test method test_one() is missing a return type', | ||
27 => 'Test method test_with_a_return() is missing a return type', | ||
32 => 'Test method test_with_another_return() is missing a return type', | ||
38 => 'Test method test_with_empty_return() is missing a return type', | ||
], | ||
], | ||
]; | ||
} | ||
|
||
/** | ||
* Test the moodle.PHPUnit.TestCaseCovers sniff | ||
* | ||
* @param string $fixture relative path to fixture to use. | ||
* @param array $errors array of errors expected. | ||
* @param array $warnings array of warnings expected. | ||
* @dataProvider provider_phpunit_data_returntypes | ||
*/ | ||
public function test_phpunit_test_returntypes( | ||
string $fixture, | ||
array $errors, | ||
array $warnings | ||
): void { | ||
// Define the standard, sniff and fixture to use. | ||
$this->set_standard('moodle'); | ||
$this->set_sniff('moodle.PHPUnit.TestReturnType'); | ||
$this->set_fixture(__DIR__ . '/' . $fixture); | ||
|
||
// Define expected results (errors and warnings). Format, array of: | ||
// - line => number of problems, or | ||
// - line => array of contents for message / source problem matching. | ||
// - line => string of contents for message / source problem matching (only 1). | ||
$this->set_errors($errors); | ||
$this->set_warnings($warnings); | ||
|
||
// Let's do all the hard work! | ||
$this->verify_cs_results(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,7 +28,7 @@ | |
* @copyright 2023 Andrew Lyons <[email protected]> | ||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | ||
* | ||
* @covers \MoodleHQ\MoodleCS\moodle\Sniffs\Namespaces\NoLeadingSlashSniff | ||
* @covers \MoodleHQ\MoodleCS\moodle\Sniffs\Namespaces\NamespaceStatementSniff | ||
*/ | ||
class NamespaceStatementSniffTest extends MoodleCSBaseTestCase | ||
{ | ||
|
5 changes: 5 additions & 0 deletions
5
moodle/Tests/fixtures/moodleutil/istestcaseclass/is_testcase.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<?php | ||
defined('MOODLE_INTERNAL') || die(); // Make this always the 1st line in all CS fixtures. | ||
|
||
class is_testcase extends base_test { | ||
} |
14 changes: 14 additions & 0 deletions
14
moodle/Tests/fixtures/moodleutil/istestcaseclass/multiple_classes_test.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<?php | ||
defined('MOODLE_INTERNAL') || die(); // Make this always the 1st line in all CS fixtures. | ||
|
||
class is_testcase extends base_test { | ||
} | ||
|
||
class not_a_test_class extends base_test { | ||
} | ||
|
||
class some_other_class_with_test_in_name extends base_test { | ||
} | ||
|
||
class some_other_class_with_test_in_name_not_extending_test { | ||
} |
5 changes: 5 additions & 0 deletions
5
moodle/Tests/fixtures/moodleutil/istestcaseclass/not_testcase.php
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
<?php | ||
defined('MOODLE_INTERNAL') || die(); // Make this always the 1st line in all CS fixtures. | ||
|
||
class not_a_test_case_class extends base_test { | ||
} |
Oops, something went wrong.