2
0
forked from Wavyzz/dolibarr

Qual: Refactor CodingPhpTest / CommonClassTest - less verbosity, but better when error (#28388)

* Qual: CommonClassTest - less verbosity, but better when error

# Qual: CommonClassTest - less verbosity, but better when error

- Report the test method and parameters in case of error.
- Less verbosity about setup.
- $_ENV was empty array, replaced with getenv()

* Qual: Refactor CodingPhpTest

# Qual: Refactor CodingPhpTest

- Use dataprovider (better progress report, better errors, better continuation)
- Use dol_dir_list's exclude_filter capability (do not traverse the excluded dirs)
- Reduce debug output from dolibarr.log (not really relevant for these tests).

* Fix: References to loop variables outside loop

# Fix: References to loop variables outside loop

The test referenced some undefined variables outside foreach loops ($val[0])

* Update CommonClassTest.class.php

---------

Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
This commit is contained in:
MDW
2024-02-24 14:12:32 +01:00
committed by GitHub
parent 6341df1795
commit 8842f8ab10
2 changed files with 506 additions and 486 deletions

View File

@@ -81,42 +81,53 @@ $conf->global->MAIN_DISABLE_ALL_MAILS = 1;
*/
class CodingPhpTest extends CommonClassTest
{
/**
* Return list of files for which to verify Php checks
*
* @return array{name:string,path:string,level1name:string,relativename:string,fullname:string,date:string,size:int,perm:int,type:string} List of php files to check (dol_dir_list)
*/
public function phpFilesProvider()
{
// File functions are needed
include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
$excludeRegexList
= array(
'\/includes\/',
'\/install\/doctemplates\/websites\/',
'\/custom\/',
'\/dolimed',
'\/nltechno',
'\/teclib',
);
$fullRegex = '(?:'.implode('|', $excludeRegexList).')';
$filesarray = dol_dir_list(DOL_DOCUMENT_ROOT, 'files', 1, '\.php', [$fullRegex], 'fullname', SORT_ASC, 0, 1, '', 1);
/*
$filteredArray = array_filter(
$filesarray,
static function($file) use (&$fullRegex) {
return !preg_match($fullRegex, $file['relativename']);
}
));
*/
return array_map(function ($value) {
return array($value);
}, $filesarray);
}
/**
* testPHP
*
* @param array{name:string,path:string,level1name:string,relativename:string,fullname:string,date:string,size:int,perm:int,type:string} $file File information
* @return string
*
* @dataProvider phpFilesProvider
*/
public function testPHP()
public function testPHP($file)
{
global $conf,$user,$langs,$db;
$conf = $this->savconf;
$user = $this->savuser;
$langs = $this->savlangs;
$db = $this->savdb;
include_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
$filesarray = dol_dir_list(DOL_DOCUMENT_ROOT, 'files', 1, '\.php', null, 'fullname', SORT_ASC, 0, 1, '', 1);
foreach ($filesarray as $key => $file) {
if (preg_match('/\/(htdocs|html)\/includes\//', $file['fullname'])) {
continue;
}
if (preg_match('/\/(htdocs|html)\/install\/doctemplates\/websites\//', $file['fullname'])) {
continue;
}
if (preg_match('/\/(htdocs|html)\/custom\//', $file['fullname'])) {
continue;
}
if (preg_match('/\/(htdocs|html)\/dolimed/', $file['fullname'])) {
continue;
}
if (preg_match('/\/(htdocs|html)\/nltechno/', $file['fullname'])) {
continue;
}
if (preg_match('/\/(htdocs|html)\/teclib/', $file['fullname'])) {
continue;
}
$this->nbLinesToShow = 1;
//print 'Check php file '.$file['relativename']."\n";
$filecontent = file_get_contents($file['fullname']);
@@ -368,24 +379,28 @@ class CodingPhpTest extends CommonClassTest
// Check string sql|set|WHERE|...'".$yyy->xxx with xxx that is not 'escape', 'idate', .... It means we forget a db->escape when forging sql request.
$ok = true;
$matches = array();
$found = "";
preg_match_all('/(sql|SET|WHERE|INSERT|VALUES|LIKE).+\s*\'"\s*\.\s*\$(.......)/', $filecontent, $matches, PREG_SET_ORDER);
foreach ($matches as $key => $val) {
if (! in_array($val[2], array('this->d', 'this->e', 'db->esc', 'dbs->es', 'dbs->id', 'mydb->e', 'dbsessi', 'db->ida', 'escaped', 'exclude', 'include'))) {
$found = $val[0];
$ok = false; // This will generate error
break;
}
//if ($reg[0] != 'db') $ok=false;
}
//print __METHOD__." Result for checking we don't have non escaped string in sql requests for file ".$file."\n";
$this->assertTrue($ok, 'Found non escaped string in building of a sql request (case 2) in '.$file['relativename'].': '.$val[0].' - Bad.');
$this->assertTrue($ok, 'Found non escaped string in building of a sql request (case 2) in '.$file['relativename'].': '.$found.' - Bad.');
//exit;
// Check string sql|set...'.$yyy->xxx with xxx that is not 'escape', 'idate', .... It means we forget a db->escape when forging sql request.
$ok = true;
$matches = array();
$found = "";
preg_match_all('/(\$sql|SET\s|WHERE\s|INSERT\s|VALUES\s|VALUES\().+\s*\'\s*\.\s*\$(.........)/', $filecontent, $matches, PREG_SET_ORDER);
foreach ($matches as $key => $val) {
if (! in_array($val[2], array('this->db-', 'db->prefi', 'db->sanit', 'dbs->pref', 'dbs->sani', 'conf->ent', 'key : \'\')', 'key])."\')', 'excludefi', 'regexstri', ''))) {
$found = $val[0];
$ok = false;
var_dump($matches);
break;
@@ -393,7 +408,7 @@ class CodingPhpTest extends CommonClassTest
//if ($reg[0] != 'db') $ok=false;
}
//print __METHOD__." Result for checking we don't have non escaped string in sql requests for file ".$file."\n";
$this->assertTrue($ok, 'Found non escaped string in building of a sql request (case 3) in '.$file['relativename'].': '.$val[0].' - Bad.');
$this->assertTrue($ok, 'Found non escaped string in building of a sql request (case 3) in '.$file['relativename'].': '.$found.' - Bad.');
//exit;
// Checks with IN
@@ -577,9 +592,6 @@ class CodingPhpTest extends CommonClassTest
$this->assertTrue($ok, 'Found a CURDATE\(\) into code. Do not use this SQL method in file '.$file['relativename'].'. You must use the PHP function dol_now() instead.');
}
return;
}
/**
* Verify that only known modules are used

View File

@@ -79,7 +79,9 @@ abstract class CommonClassTest extends TestCase
$this->savlangs = $langs;
$this->savdb = $db;
print __METHOD__." db->type=".$db->type." user->id=".$user->id;
if ((int) getenv('PHPUNIT_DEBUG') > 0) {
print get_called_class()." db->type=".$db->type." user->id=".$user->id;
}
//print " - db ".$db->db;
print PHP_EOL;
}
@@ -94,13 +96,8 @@ abstract class CommonClassTest extends TestCase
global $conf,$user,$langs,$db;
$db->begin(); // This is to have all actions inside a transaction even if test launched without suite.
if (!isModEnabled('agenda')) {
print get_called_class()." module agenda must be enabled.".PHP_EOL;
die(1);
}
if (isset($_ENV['PHPUNIT_DEBUG'])) {
print get_called_class().PHP_EOL;
if ((int) getenv('PHPUNIT_DEBUG') > 0) {
print get_called_class()."::".__FUNCTION__.PHP_EOL;
}
}
@@ -126,12 +123,24 @@ abstract class CommonClassTest extends TestCase
// Get the last line of the log
$last_lines = array_slice($lines, $first_line, $nbLinesToShow);
$failedTestMethod = $this->getName(false);
$className = get_called_class();
// Get the test method's reflection
$reflectionMethod = new ReflectionMethod($className, $failedTestMethod);
// Get the test method's data set
$argsText = $this->getDataSetAsString(true);
// Show log file
print PHP_EOL."----- Test fails. Show last ".$nbLinesToShow." lines of dolibarr.log file -----".PHP_EOL;
print PHP_EOL;
print "----- $className::$failedTestMethod failed - $argsText.".PHP_EOL;
print "Show last ".$nbLinesToShow." lines of dolibarr.log file -----".PHP_EOL;
foreach ($last_lines as $line) {
print $line . "<br>";
}
print PHP_EOL;
print "----- end of dolibarr.log for $className::$failedTestMethod".PHP_EOL;
parent::onNotSuccessfulTest($t);
}
@@ -150,10 +159,9 @@ abstract class CommonClassTest extends TestCase
$langs = $this->savlangs;
$db = $this->savdb;
if (isset($_ENV['PHPUNIT_DEBUG'])) {
print get_called_class().PHP_EOL;
if ((int) getenv('PHPUNIT_DEBUG') > 0) {
print get_called_class().'::'.$this->getName(false)."::".__FUNCTION__.PHP_EOL;
}
print __METHOD__."\n";
//print $db->getVersion()."\n";
}
@@ -164,8 +172,8 @@ abstract class CommonClassTest extends TestCase
*/
protected function tearDown(): void
{
if (isset($_ENV['PHPUNIT_DEBUG'])) {
print get_called_class().PHP_EOL;
if ((int) getenv('PHPUNIT_DEBUG') > 0) {
print get_called_class().'::'.$this->getName(false)."::".__FUNCTION__.PHP_EOL;
}
}
@@ -178,8 +186,8 @@ abstract class CommonClassTest extends TestCase
{
global $db;
$db->rollback();
if (isset($_ENV['PHPUNIT_DEBUG'])) {
print get_called_class().PHP_EOL;
if ((int) getenv('PHPUNIT_DEBUG') > 0) {
print get_called_class()."::".__FUNCTION__.PHP_EOL;
}
}